Генерация торговых сигналов и стратегий с помощью dplyr

Недавно я играл с техническими методами торговли в R.

Одна из вещей, которая, как мне кажется, становится проблемой, особенно при большом количестве высокочастотной информации, — это создание вектора стратегии из вектора сигналов. Мне было интересно, нет ли более быстрого способа использования dplyr?

Давайте начнем с загрузки акций Apple и создания коротких и длинных скользящих средних.

library("TTR")
library("quantmod")
library("PerformanceAnalytics")
library("dplyr")

getSymbols("AAPL", src = "google")
stock <- AAPL
stock <- window(stock['2015-10-01::2017-01-01'])

# Plot if you want to see
#lineChart(stock)

Short <- EMA(Cl(stock), n=5)
Long <- EMA(Cl(stock), n=6)

Теперь у нас есть выбранная акция, давайте сгенерируем наш сигнальный вектор, который указывает ордер на покупку и продажу, когда две скользящие средние пересекаются.

# Signal
Signal <-
  Lag(ifelse(
    Lag(Short) < Lag(Long) & Short > Long, 1,
    ifelse(
      Lag(Short) > Lag(Long) & Short < Long, -1, 0)
  ))
Signal[is.na(Signal)] <- 0

Затем мы используем этот сигнал для построения стратегии - это часть, которая занимает много времени в высокочастотных данных - что, очевидно, связано с циклом for

# Strategy
Strategy <- ifelse(Signal > 1, 0, 1)
for (i in 1:length(Cl(stock))) {
  Strategy[i] <-
    ifelse(Signal[i] == 1, 1, ifelse(Signal[i] == -1, 0, Strategy[i - 1]))
}
x <- as.numeric(Strategy$Lag.1)
x[is.na(x)] <- 0

Мой текущий подход к dplyr выглядит следующим образом, но он генерирует неправильную стратегию

dplyr_strat <-
Signal %>% tbl_df() %>% 
  mutate(Change = if_else(Lag.1 == -1, "Sell", "Buy", "NoChange") ) %>% 
  mutate(Strategy = ifelse(Change == "Buy", 1, 
                           ifelse( Change == "Sell", 0, 
                                   lag(Strategy)) ) ) %>% select(Strategy)
y <- as.numeric(dplyr_strat$Strategy)

И тест

all.equal(x,y)

person Hanjo Odendaal    schedule 10.02.2017    source источник
comment
Не могли бы вы предоставить примеры данных временных рядов и ожидаемый результат? Просить людей загружать данные только для того, чтобы решить ваш вопрос, — это слишком далеко.   -  person mtoto    schedule 10.02.2017
comment
Большинство вопросов, связанных с финансами, используют функцию getSymbols quantmod, так что на самом деле это не слишком много. Другая проблема, возникающая при предоставлении данных, заключается в том, что, как и в случае с финансовыми вопросами, вы работаете с ежедневными данными в течение длительного периода времени. Это не может быть упаковано в простой небольшой фрейм данных. Ожидаемый вывод должен состоять в том, что вывод dplyr должен совпадать с выводом for циклов. Таким образом, all.equal(x,y) должно вернуть TRUE   -  person Hanjo Odendaal    schedule 10.02.2017
comment
Что вы считаете неправильным? И каким будет правильный ответ/ожидаемый результат?   -  person Uwe    schedule 10.02.2017
comment
Я не проверял это. Мутация должна быть ближе к оригиналу. что-то вроде dplyr_strat <- Signal %>% tbl_df() %>% mutate(Strategy = ifelse(Signal == 1, 1, ifelse(Signal == -1, 0, lag(Strategy))))   -  person Andrew Lavers    schedule 10.02.2017
comment
Подумав об этом, я думаю, что вы не можете использовать функции, которые зависят от измененных (мутированных) значений. Они применяются к исходному фрейму данных, а не к мутированному фрейму данных. Я не мог сразу найти ссылку, чтобы поддержать это   -  person Andrew Lavers    schedule 10.02.2017


Ответы (1)


Я согласен с комментарием epi99 о том, чтобы он соответствовал вашему начальному циклу for. Я использовал data.table и получил точное совпадение, см. ниже:

## Using data.table
dt.Signal <- setDT(as.data.frame(Signal))
dt.Signal[, Strategy := ifelse(Lag.1 == 1, 1, ifelse(Lag.1 == -1, 0, lag(Strategy)))]
dt.Signal[is.na(dt.Signal)] <- 0
z <- as.numeric(dt.Signal[, Strategy])

all.equal(x,z)

Вероятно, у вас возникла проблема с логикой «Купить», «Продать» и «Без сдачи».

person GarAust89    schedule 10.02.2017