quantstrat: как создать несколько индикаторов, правила сигналов

Я хочу добавить несколько правил на основе разных сигналов, таких как SMA50 > SMA10 и MACD > 0. Однако я получаю сообщение об ошибке, используя sigComparision. Может ли кто-нибудь предложить лучший способ сделать это?


person Rajat    schedule 14.04.2018    source источник


Ответы (2)


Есть два очевидных подхода, которые вы можете использовать: вы можете создать составную сигнальную функцию в правилах добавления или вы можете использовать sigFormula. Последний известен своей медлительностью. Например, посмотрите эту тему:

https://stat.ethz.ch/pipermail/r-sig-finance/2012q1/009310.html

Здесь я выделяю ключевой раздел:

sigFormula использует функцию синтаксиса R, которая позволяет использовать имена столбцов непосредственно как переменные в формуле. Частичное сопоставление не выполняется, поскольку столбцы становятся переменными формулы.

....

Я предупрежу вас, что, хотя sigFormula очень гибкая, R не очень быстр, используя эту методологию. Кажется, это побочный эффект того, как data.frames хранятся в виде списков, и того, как синтаксис eval(parse(text=formula),x) управляется внутри R.

Для ежедневных или низкочастотных данных это, вероятно, нормально, но для более высоких частот я обычно считаю целесообразным написать собственный индикатор сигнальной функции для более сложных сравнений.

В следующем примере (основанном на демонстрации macd.R в пакете quantstrat) вы можете поэкспериментировать с обоими подходами:

require(quantstrat)
suppressWarnings(rm("order_book.macd",pos=.strategy))
suppressWarnings(rm("account.macd","portfolio.macd",pos=.blotter))
suppressWarnings(rm("account.st","portfolio.st","stock.str","stratMACD","startDate","initEq",'start_t','end_t'))

stock.str='AAPL' # what are we trying it on


fastMA = 12 
slowMA = 26 
signalMA = 8
maType="EMA"

currency('USD')
stock(stock.str,currency='USD',multiplier=1)

startDate='2006-12-31'
initEq=1000000
portfolio.st='macd'
account.st='macd'

getSymbols(stock.str,from=startDate)


initPortf(portfolio.st,symbols=stock.str)
initAcct(account.st,portfolios=portfolio.st)
initOrders(portfolio=portfolio.st)

strat.st<-portfolio.st
# define the strategy
strategy(strat.st, store=TRUE)

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

add.indicator(strat.st, name = "SMA", 
              arguments = list(x=quote(Cl(mktdata)),
                               n=10),
              label='SMA10' 
)



add.indicator(strat.st, name = "SMA", 
              arguments = list(x=quote(Cl(mktdata)),
                               n = 50),
              label='SMA50' 
)

# Create your own signal for entry:
macdSMAsig <- function(data) {
  # first condition:
  sig <- data[, "SMA.SMA50"] > data[, "SMA.SMA10"] & data[, "macd._"] > 0
  colnames(sig) <- "upSig"
  sig
}



 # Activate (uncomment) only ONE of the following signals.  Both do the same thing:

#OPTION 1 for entry signal based on combining signals:
add.signal(strat.st,name="macdSMAsig",
           arguments = list(data = quote(mktdata)),
           label="enterSig"
)

#OPTION 2 for entry signal based on combining signals:
# add.signal(strat.st, name = "sigFormula",
#            arguments = list(data = quote(mktdata),
#                             formula = "SMA.SMA50 > SMA.SMA10 & macd._ > 0"),
#            label = "upSig.enterSig"
#            )



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

####
# add rules

# entry
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
)

# exit
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'
)

#end rules
####


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



updatePortf(Portfolio=portfolio.st,Dates=paste('::',as.Date(Sys.time()),sep=''))

chart.Posn(Portfolio=portfolio.st,Symbol=stock.str)

tx <- getTxns(portfolio.st, stock.str)
sum(tx$Net.Txn.Realized.PL)
person FXQuantTrader    schedule 15.04.2018
comment
#FXQuantTrader, правильно ли я понимаю, что созданная вами функция macdSMAsig используется для ВАРИАНТА 1, но не для ВАРИАНТА 2, так как в последнем вы используете sigFormula? - person W Barker; 23.07.2019
comment
Да. вариант 2, очевидно, быстрее и проще для прототипирования, но как только вы выполняете очень большое количество вызовов функций (тестирование на истории на очень большом количестве строк в ваших объектах xts), подход 1 должен быть намного быстрее - person FXQuantTrader; 24.07.2019
comment
#FXQuantTrader, я использовал предложенный вами выше код (подход 1) для одной модели акций, но теперь решил попробовать его на нескольких акциях, и у меня возникли проблемы; Я опубликовал новый вопрос: «stackoverflow.com/questions/57281786/'. Буду признателен за ваши комментарии там! - person W Barker; 31.07.2019

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

Ошибка в applyRules (портфель = портфель, символ = символ, стратегия = стратегия,: mktdata не содержит 'sigcol': entersig

Вот что я сделал:

    library(quantmod)
library(FinancialInstrument)
library(PerformanceAnalytics)
library(foreach)
library(blotter)
library(quantstrat)

options("getSymbols.yahoo.warning"=FALSE)
options("getSymbols.warning4.0"=FALSE)

initDate="1990-01-01"
from ="2003-01-01"
to ="2012-12-31"
symbols = c("AAPL")
currency("USD")
getSymbols(symbols, from=from, to=to, adjust=TRUE)

stock(symbols, currency="USD", multiplier=1)
initEq=1000000

strategy.st <- portfolio.st <- account.st <- "mystrat"

rm.strat("mystrat")


initPortf(name=portfolio.st,
          symbols=symbols,
          initDate=initDate,
          currency='USD')
initAcct(name=account.st,
         portfolios=portfolio.st,
         initDate=initDate,
         currency='USD',
         initEq=initEq)
initOrders(portfolio=portfolio.st,
           initDate=initDate)

strategy(strategy.st, store=TRUE)

### Add Indicators

nRSI <- 21
buyThresh <- 50
sellThresh <- 50

#Indicator for EMA long medium short

nEMAL<- 80
nEMAM<- 21
nEMAS<- 13
nEMAF<- 5

add.indicator(strategy.st, name="RSI",
              arguments=list(price=quote(Cl(mktdata)), n=nRSI),
              label="rsi")

add.indicator(strategy.st, name="EMA",
              arguments=list(x=quote(Cl(mktdata)), n=nEMAL),
              label="EMAL")

add.indicator(strategy.st, name="EMA",
              arguments=list(x=quote(Cl(mktdata)), n=nEMAM),
              label="EMAM")

add.indicator(strategy.st, name="EMA",
              arguments=list(x=quote(Cl(mktdata)), n=nEMAS),
              label="EMAS")

add.indicator(strategy.st, name="EMA",
              arguments=list(x=quote(Cl(mktdata)), n=nEMAF),
              label="EMAF")

#customsig <- function(data) {
  sig <- data[, "EMA.EMAF"] > data[, "EMA.EMAS"] & data[, "EMA.EMAF"] > data[, "EMA.EMAM"] & data[, "rsi"] >50 & data[, "EMA.EMAM"] > data[, "EMA.EMAL"] & data[, "EMA.EMAS"] > data[, "EMA.EMAL"]  
  colnames(sig) <- "upSig"
  sig
}

#downsig <- function(data) {
  sig <- data[, "EMA.EMAF"] < data[, "EMA.EMAS"] & data[, "EMA.EMAF"] < data[, "EMA.EMAM"] & data[, "rsi"] <50 & data[, "EMA.EMAM"] < data[, "EMA.EMAL"] & data[, "EMA.EMAS"] < data[, "EMA.EMAL"]  
  colnames(sig) <- "downSig"
  sig
}



### Add Signal- Enter

add.signal(strategy.st, name="customsig",
           arguments=list(data = quote(mktdata)),
           label = "entersig")

add.signal(strategy.st, name="downsig",
           arguments=list(data = quote(mktdata)),
           label = "downsig.exitsig")

### Add rule - Enter

add.rule(strategy.st,
         name='ruleSignal',
         arguments = list(sigcol="entersig",
                          sigval=TRUE,
                          orderqty=1000,
                          ordertype='market',
                          orderside='long',
                          threshold=NULL),
         type='enter',
         path.dep=TRUE)


### Add rule- Exit

add.rule(strategy.st,
         name='ruleSignal',
         arguments = list(sigcol="downsig.exitsig",
                          sigval=TRUE,
                          orderqty=1000,
                          ordertype='market',
                          orderside='long',
                          pricemethod='market',
                          replace=FALSE),
         type='exit',
         path.dep=TRUE)

start_t<-Sys.time()
out<-try(applyStrategy(strategy=strategy.st,
                       portfolios=portfolio.st))


updatePortf(portfolio.st)
updateAcct(portfolio.st)
updateEndEq(account.st)

for(symbol in symbols) {
  chart.Posn(
    Portfolio=portfolio.st,
    Symbol=symbol,
    log=TRUE)
}
person Bryan Lwy    schedule 19.04.2018