Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
clean way to compute indicators and signals
library(TTR)
library(xts)
library(data.table)
# - [x] use list element names instead of `label` argument
# - [x] allow to reuse preceeded indicators, reduce amount of indicator computation
# - [x] cleaner way of providing indicators and signals, provide R language object directly instead of `get` object by name
ma_crossover = function(ma_slow, ma_fast){
setDT(list(sig_buy = ma_fast > ma_slow, sig_sell = ma_fast < ma_slow))[sig_buy==TRUE, sig := 1L][sig_sell==TRUE, sig := -1L][!sig%in%c(1L,-1L), sig := 0L]$sig
}
compute_signal = function(data, indicator, signal){
indicator = substitute(indicator)
signal = substitute(signal)
stopifnot(is.language(indicator), indicator[[1L]]==quote(list), is.language(signal), signal[[1L]]==quote(list))
indicator = as.list(indicator[-1L])
signal = as.list(signal[-1L])
lapply(names(indicator), function(name) data[, (name) := eval(indicator[[name]])])
lapply(names(signal), function(name) data[, (name) := eval(signal[[name]])])
data
}
# PS. I know that below indicators doesn't make sense, just wanted to show a way of reusing computed first indicators in the later ones.
utils::data(sample_matrix, package = "xts")
data = as.data.table(sample_matrix, keep.rownames = "date")
compute_signal(
data = data,
indicator = list(sma_5 = SMA(Close, 5L), sma_20 = SMA(Close, 20L), sma_5_to_open_ratio = sma_5 / Open, sma_10_sma_20 = SMA(sma_20, 10L)),
signal = list(sig_sma20_sma5 = ma_crossover(sma_20, sma_5))
)
print(data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment