Одномерная ошибка с внешними индикаторами и несколькими акциями в quantstrat

Мы используем индикаторы, внешние по отношению к торговым данным, которые мы объединяем с объектом OLHC. Наша цель — построить модель квантстрата, учитывающую несколько акций, но мы продолжаем получать сообщения об ошибках, указывающие на то, что мы не построили ее должным образом. Кроме того, ошибка относится к EMA, хотя мы явно не используем EMA.

Я начал с кода #FXQuantTrader, принятого в качестве ответа здесь: quantstrat: как для создания нескольких индикаторов, правил сигналов, которые я могу заставить работать с индикаторами, внешними по отношению к данным OHLC, и пользовательской функцией, вызываемой add.signal, но не могу перейти к нескольким акциям.

Эта запись переполнения стека R - Quantstart: Testing Strategy on Multiple Equities обратиться к предмету напрямую, но приведенный пример предлагает предложение

«загрузите тестовую стратегию, которую вы бы использовали сами»

в связи с чем возникает вопрос о том, как построить стратегию с несколькими акциями. Попытка реализовать вызов applyStrategy из этого сообщения с использованием моей стратегии приводит к ошибке

«формальный аргумент 'n' соответствует нескольким фактическим аргументам».

Комментирование раздела параметров этого вызова возвращает меня к исходной ошибке.

Документация Quantstrat https://www.rdocumentation.org/packages/quantstrat/versions/0.16.2 относится к следующему, но в каждом примере используется только один капитал: (a) MaCross (основная часть документации), (b) курс DataCamp https://www.datacamp.com/community/blog/financial-trading-in-r-with-ilya-kipnis (взяла целиком), (c) презентация qauntstrat http://past.rinfinance.com/agenda/2018/BrianPeterson.html#1 на конференции R/Finance 2018 использует один EFT: EEM.

Другие ресурсы включают заметки Гая Йоллина http://www.r-programming.org/papers, но слайды 18, 21 и 41 его первой (установочной) колоды представляют то же стандартное отклонение и ретроспективный анализ «n», что и сообщение SO, упомянутое выше, без объяснения причин. Я пробовал разные комбинации, но все равно были те же ошибки.

Сообщения в блоге Ильны Кипнис «Гайки и болты…» https://quantstrattrader.wordpress.com/2014/09/09/nuts-and-bolts-of-quantstrat-part-i/ демонстрирует использование нескольких акций, но не перечисляет параметры в вызове applyStrategy, так что, возможно, моя проблема не в этом. Похоже, это подтверждается онлайн-книгой Тима Трайса по квантстрату (еще один ресурс, на который ссылается документация квантстрата), где он говорит — в контексте приложения множественного капитала — что

«На данный момент нет необходимости вникать в дополнительные параметры». (раздел 5.5).

Я также экспериментировал с функцией «применить», но безуспешно.

.blotter <- new.env()
.strategy <- new.env()

fastMA = 12 
slowMA = 26 

currency('USD')
startDate='2017-03-24'
endDate = "2017-08-05" 

initEq=1000000
portfolio.st='macd'
account.st='macd'

symbols <- c("NOV", # National-Oilwell Varco, Inc.
         "AERI", # Aerie Pharmaceuticals Inc
         "AGN" # Allergan plc
)

Cx.AERI <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0)
Cx.AGN <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Cx.NOV <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0)
getSymbols(symbols,from=startDate, to=endDate) # gets xts object

Tplus <- merge.xts(AERI, AGN, NOV, Cx.AERI,Cx.AGN,Cx.NOV) 
stock.st='Tplus'
initPortf(portfolio.st,symbols=stock.st)
initAcct(account.st,portfolios=portfolio.st)
initOrders(portfolio=portfolio.st)
stock(symbols,currency="USD", multiplier =1) 
strat.st<-portfolio.st
strategy(strat.st, store=TRUE)

add.indicator(strat.st, name = "MACD", 
          arguments = list(x=quote(Cl(mktdata)),
                           nFast=fastMA, 
                           nSlow=slowMA),
          label='_' 
)

macdSMAsig2 <- function(data) {
  sig <- data[, "Cx._"] >0 & data[, "macd._"] > 0
  colnames(sig) <- "upSig"
  sig
}

add.signal(strat.st,name="macdSMAsig2",
       arguments = list(data = quote(mktdata)),
       label="enterSig"
)

add.signal(strat.st,name="sigThreshold",
       arguments = list(column="signal._",
                        relationship="lt",
                        threshold=0,
                        cross=TRUE),
       label="signal.lt.zero"
)

add.rule(strat.st,name='ruleSignal', 
     # be careful to get the label of the signal column correct:
     arguments = list(sigcol="upSig.enterSig",
                      sigval=TRUE, 
                      orderqty=100, 
                      ordertype='market', 
                      orderside='long', 
                      threshold=NULL),
     type='enter',
     label='enter',
     storefun=FALSE
)

add.rule(strat.st,name='ruleSignal', 
     arguments = list(sigcol="signal.lt.zero",
                      sigval=TRUE, 
                      orderqty='all', 
                      ordertype='market', 
                      orderside='long', 
                      threshold=NULL,
                      orderset='exit2'),
     type='exit',
     label='exit'
)

out<-applyStrategy(strat.st , portfolios=portfolio.st,verbose=TRUE)

Я ожидал некоторых сделок, но вместо этого получил это сообщение об ошибке:

 >Error in EMA(c(45.849998, 45.549999, 45.450001, 45.25, 45.450001, 
 45.349998,  :   ncol(x) > 1. EMA only supports univariate 'x'

person W Barker    schedule 31.07.2019    source источник
comment
Я думаю, ваша проблема должна быть в том, что MACD должен вызвать EMA, и есть конфликт в измерениях данных (не подается по одному, как вы ожидаете). Одна вещь, которую вы могли бы сделать, это запустить каждый бэктест отдельно, сохранить результаты/транзакции, а затем использовать это в цикле, чтобы объединить результаты для создания своего рода доходности портфеля. Это означает, что это даст вам подробную информацию о том, будет ли / когда у вас будет позиция по другому символу, соответственно обновите свой P / L и т. Д. Quantstrat не может сделать это самостоятельно.   -  person Jared Marks    schedule 31.07.2019


Ответы (2)


Я думаю, ваша проблема должна быть в том, что MACD должен вызвать EMA, и есть конфликт в измерениях данных (не подается по одному, как вы ожидаете). Насколько я знаю, Quantstrat может проводить только ИНДИВИДУАЛЬНОЕ тестирование на истории более чем одной акции за раз, но не знает, что произошло в других тестах на истории. Одна вещь, которую вы могли бы сделать, это запустить каждый бэктест по отдельности, сохранить результаты/транзакции, а затем использовать это в цикле, чтобы объединить результаты, создав своего рода доход «портфеля». Это означает, что это даст вам подробную информацию о том, будет ли / когда у вас будет позиция по другому символу, соответственно обновите свой P/L и т. д.

person Jared Marks    schedule 31.07.2019
comment
Да, #Джаред, я понимаю, что quantstrat не предназначен для решения ситуаций, когда занятие любой данной позиции зависит от занятия другой позиции; это не то, что я намереваюсь. Как вы предполагаете, с тех пор я узнал, что, хотя quantstrat обрабатывает несколько акций одновременно (и независимо), он ожидает, что внешние индикаторы будут добавляться к каждому объекту ценной бумаги отдельно. Поэтому мне нужно объединить.xts мои сигналы Cx.NOV с объектом NOV, созданным с помощью getSymbols и т. д. Я сделал это, но теперь получаю Error in [.xts(data, , Cx._) : индекс выходит за пределы. Моя метка Cx._ неверна? - person W Barker; 01.08.2019
comment
@WBarker Может помочь попробовать вызвать applyIndicators и applySignals, чтобы отладить подобные ошибки, и посмотреть, скажем, tail(mktdata), чтобы увидеть, что на каждом шаге все соответствует вашим ожиданиям, а не вызывать полный applyStrategy. Ваша ошибка звучит так, будто у вас есть проблема в сигнальной функции (когда вы вызываете applySignals. - person FXQuantTrader; 01.08.2019

Расширяя существующий ответ, ваша ошибка должна иметь для вас больше смысла, если вы сделаете это:

Cl(Tplus)

Обратите внимание, как возвращаются 3 столбца вместо одного закрытого столбца? (Cl ищет имена столбцов со словом «закрыть/закрыть» и возвращает их все (аналогично для Hi, Lo и т. д.)

Функция MACD ожидает один одномерный (закрытый) ценовой ряд, в противном случае вы получите ошибку (MACD вызывает функции EMA, которые ожидают одномерный ценовой ряд)

Самое простое исправление - сделать это:

add.indicator(strat.st, name = "MACD", 
              arguments = list(x=quote(Cl(mktdata)[,1]),
                               nFast=fastMA, 
                               nSlow=slowMA),
              label='_' 
)

out<-applyStrategy(strat.st , portfolios=portfolio.st,verbose=TRUE)

head(mktdata)

Теперь вы не получаете свою ошибку (хотя я думаю, что вы хотите сделать больше, чем вычислить MACD только для одного временного ряда). Теперь вы можете видеть, что добавлены 2 столбца. Это результат вызова MACD по первому ряду цен закрытия.

Если вы хотите вычислить MACD всех трех ценовых рядов в одном объекте рыночных данных, который для вас выглядит как Tplus, вам следует написать пользовательскую функцию индикатора, которая вычисляет MACD каждого отдельного ряда, объединить результаты и вернуться из функции индикатора клиента. (Я предполагаю, что вы хотите делать такие вещи, как, скажем, купить AERI, если MACD(cl(AERI)) > MACD(cl(AERI)) и MACD(cl(AERI) > MACD(cl(NOV)), поэтому вы храните несколько серий цен в одном объекте mktdata). Надеюсь, это имеет смысл.

Между прочим, несмотря на то, что applyStrategy действительно смотрит по символам независимо друг от друга, вы можете обеспечить некоторую интерактивность между сделками на разных ценовых сериях, используя вместо этого applyStrategy.rebalancing, если вам это действительно необходимо. applyStrategy.rebalancing эффективно запускает двойной цикл: цикл по пакету баров/строк, затем по каждому символу в этом пакете баров, повторение до тех пор, пока не будет пройден весь временной диапазон наборов данных. Этот двойной цикл позволяет принимать некоторые торговые решения (например, rulePctEquity), основанные на сделках с различными рыночными данными в определенные моменты времени при тестировании на исторических данных.

Чтобы значительно ускорить моделирование на больших наборах данных, идея quantstrat состоит в том, чтобы предварительно вычислить (в идеале векторизовать) как можно больше заранее, прежде чем циклически просматривать строки рыночных данных в поисках строк, в которых может произойти торговое действие.

Легко изменить applyStrategy.rebalancing на двойную петлю на каждом баре, если вы действительно этого хотите, но это требует невероятно высоких вычислительных затрат, если вы сканируете данные баров (или, что более реалистично, тиков) за месяцы/годы.

person FXQuantTrader    schedule 01.08.2019