从R转换为交易策略回测的定量设置



我正在尝试用"quantstrat"包回测一个交易策略。我的策略由4个指标、3个不同的EMA和1个滞后EMA组成。

我想做多当:EMA1> EMA2 &EMA1> EMA3 &EMA1_lag & lt;EMA1当:EMA1

这很简单,但我不能把它写进量子环境。

以下是两个示例中使用的数据完整性检查函数:
# Data integrity check
checkBlotterUpdate <- function(port.st,account.st,verbose=TRUE)
{
    ok <- TRUE
    p <- getPortfolio(port.st)
    a <- getAccount(account.st)
    syms <- names(p$symbols)
    port.tot <- sum(sapply(syms,FUN = function(x) eval(parse(
        text=paste("sum(p$symbols",x,"posPL.USD$Net.Trading.PL)",sep="$")))))
    port.sum.tot <- sum(p$summary$Net.Trading.PL)
    if( !isTRUE(all.equal(port.tot,port.sum.tot)) ) {
        ok <- FALSE
        if( verbose )
            print("portfolio P&L doesn't match sum of symbols P&L")
    }
    initEq <- as.numeric(first(a$summary$End.Eq))
    endEq <- as.numeric(last(a$summary$End.Eq))
    if( !isTRUE(all.equal(port.tot,endEq-initEq)) ) {
        ok <- FALSE
        if( verbose )
            print("portfolio P&L doesn't match account P&L")
    }
    if( sum(duplicated(index(p$summary))) ) {
        ok <- FALSE
        if( verbose )
            print("duplicate timestamps in portfolio summary")
    }
    if( sum(duplicated(index(a$summary))) ) {
        ok <- FALSE
        if( verbose )
            print("duplicate timestamps in account summary")
    }
    return(ok)
}

这是我想要的吸墨纸代码:

# Working Strategy
# it works well only with one portfolio
library(quantstrat)
suppressWarnings({
  try(rm(list=ls(FinancialInstrument:::.instrument),
         pos=FinancialInstrument:::.instrument), silent=TRUE)
  try(rm(list=c("account.bGiulio","portfolio.bGiulio","order_book"),
         pos=.blotter), silent=TRUE)
  try(rm(list=c("b.strategy","myTheme","SPY",".getSymbols")), silent=TRUE)
})
#### all currency instruments must be defined
#### before instruments of other types can be defined
# Initialize a currency and a stock instrument
currency("USD")
stock("SPY",currency="USD",multiplier=1)
#Fetch historic data
# system settings
initDate <- '1997-12-31'
startDate <- '1998-01-01'
endDate <- '2014-06-30'
initEq <- 1e6
Sys.setenv(TZ="UTC")
getSymbols('SPY', from=startDate, to=endDate, index.class="POSIXct", adjust=T)
# convert data to weekly
SPY=to.weekly(SPY, indexAt='endof', drop.time=FALSE)
SPY$EMA_1<-EMA(na.locf(Cl(SPY)),10) # 10 o 3
SPY$EMA_2<-EMA(na.locf(Cl(SPY)),25) # 50 o 10
SPY$EMA_3<-EMA(na.locf(Cl(SPY)),30) # 200 o 50
SPY$EMA_1_lag<-lag(EMA(na.locf(Cl(SPY)),10),1) # 200 o 50
# inizialization on both 
b.strategy <- "bGiulio"
initPortf(b.strategy, 'SPY', initDate=initDate)
initAcct(b.strategy, portfolios=b.strategy, initDate=initDate, initEq=initEq)
initOrders(portfolio=b.strategy,initDate=initDate)
# trading algo 
for( i in 1:nrow(SPY) )
{
    # update values for this date
    CurrentDate <- time(SPY)[i]
    equity = getEndEq(b.strategy, CurrentDate)
    ClosePrice <- as.numeric(Cl(SPY[i,]))
    Posn <- getPosQty(b.strategy, Symbol='SPY', Date=CurrentDate)
    UnitSize = as.numeric(trunc(equity/ClosePrice))
    EMA1 <- as.numeric(SPY[i,'EMA_1'])
    EMA2 <- as.numeric(SPY[i,'EMA_2'])
    EMA3 <- as.numeric(SPY[i,'EMA_3'])
    EMA1_lag <- as.numeric(SPY[i,'EMA_1_lag'])
    # change market position if necessary
    if( !is.na(EMA1)  & # if the moving average has begun
        !is.na(EMA2)  & # if the moving average has begun
        !is.na(EMA3) &
        !is.na(EMA1_lag) ) # if the moving average has begun
    {
        if( Posn == 0 ) { # No position, test to go Long
            if( EMA1 > EMA2 & EMA1 > EMA3 & EMA1_lag<EMA1) {
                # enter long position
                addTxn(b.strategy, Symbol='SPY', TxnDate=CurrentDate,
                       TxnPrice=ClosePrice, TxnQty = UnitSize , TxnFees=0)
            }
        } else { # Have a position, so check exit
            if( EMA1 < EMA3) {
                # exit position
                addTxn(b.strategy, Symbol='SPY', TxnDate=CurrentDate,
                       TxnPrice=ClosePrice, TxnQty = -Posn , TxnFees=0)
            } else {
                if( i==nrow(SPY) ) # exit on last day
                    addTxn(b.strategy, Symbol='SPY', TxnDate=CurrentDate,
                           TxnPrice=ClosePrice, TxnQty = -Posn , TxnFees=0)
            }
        }
    }
    updatePortf(b.strategy,Dates=CurrentDate)
    updateAcct(b.strategy,Dates=CurrentDate)
    updateEndEq(b.strategy,CurrentDate)
} # End dates loop
# transactions
#getTxns(Portfolio=b.strategy, Symbol="SPY")
checkBlotterUpdate(b.strategy,b.strategy)
## [1] TRUE
tstats <- t(tradeStats(b.strategy))
perTradeStats(b.strategy)
library(lattice)
a <- getAccount(b.strategy)
xyplot(a$summary,type="h",col=4)
equity <- a$summary$End.Eq
plot(equity,main="Giulio Strategy Equity Curve")
ret <- Return.calculate(equity,method="log")
charts.PerformanceSummary(ret, colorset = bluefocus,
                          main="Giulio Strategy Performance")

我尝试用quantstrat(使用add.indicator, add.signal, add.rule)复制上述策略,但结果肯定不同。这里是第二个带有quantstrat的代码:

# Here the code that does not work
library(quantstrat)
#Initialize a currency and a stock instrument
currency("USD")
stock("SPY",currency="USD",multiplier=1)
# system settings
initDate <- '1997-12-31'
startDate <- '1998-01-01'
endDate <- '2014-06-30'
initEq <- 1e6
Sys.setenv(TZ="UTC")
getSymbols('SPY', from=startDate, to=endDate, index.class="POSIXct", adjust=T)
SPY <- to.weekly(SPY, indexAt='endof', drop.time=FALSE)
SPY$EMA1<-EMA(na.locf(Cl(SPY)),10) # 10 o 3
SPY$EMA2<-EMA(na.locf(Cl(SPY)),25) # 50 o 10
SPY$EMA3<-EMA(na.locf(Cl(SPY)),30) # 200 o 50
SPY$EMA1_lag<-lag(EMA(na.locf(Cl(SPY)),10)) # 200 o 50
# initialize portfolio/account
qs.strategy <- "qsGiulio"
rm.strat(qs.strategy) # remove strategy etc. if this is a re-run
initPortf(qs.strategy,'SPY', initDate=initDate)
initAcct(qs.strategy,portfolios=qs.strategy, initDate=initDate, initEq=initEq)
# initialize orders container
initOrders(portfolio=qs.strategy,initDate=initDate)
# instantiate a new strategy object
strategy(qs.strategy,store=TRUE)
strat <-getStrategy(qs.strategy)
add.indicator(strategy = qs.strategy, name = "EMA",
              arguments = list(x = quote(na.locf(Cl(mktdata))), n=10), label="EMA1")
add.indicator(strategy = qs.strategy, name = "EMA",
              arguments = list(x = quote(na.locf(Cl(mktdata))), n=25), label="EMA2")
add.indicator(strategy = qs.strategy, name = "EMA",
              arguments = list(x = quote(na.locf(Cl(mktdata))), n=30), label="EMA3")
add.indicator(strategy = qs.strategy, name = "EMA",
              arguments = list(x = quote(lag(na.locf(Cl(mktdata)))), n=10), label="EMA1_lag")
# entry signals
add.signal(qs.strategy,name="sigComparison",
           arguments = list(columns=c("EMA1","EMA2"),relationship="gt"),
           label="EMA1.gt.EMA2")
add.signal(qs.strategy,name="sigComparison",
           arguments = list(columns=c("EMA1","EMA3"),relationship="gt"),
           label="EMA1.gt.EMA3")
add.signal(qs.strategy,name="sigComparison",
           arguments = list(columns=c("EMA1","EMA1_lag"),relationship="gt"),
           label="EMA1.gt.EMA1_lag")
add.signal(qs.strategy, name = "sigFormula",
           arguments = list(formula="EMA1.gt.EMA2 & EMA1.gt.EMA3 & EMA1.gt.EMA1_lag"),
           label="longEntry")
# exit signals
add.signal(qs.strategy,name="sigComparison",
           arguments = list(columns=c("EMA1","EMA3"),relationship="lt"),
           label="EMA1.lt.EMA3")
# RULES
# go long when 3 condition
add.rule(qs.strategy, name='ruleSignal',
         arguments = 
                 list(sigcol="longEntry", sigval=TRUE, orderqty=900,
                      ordertype='market', orderside='long'), 
         type='enter')
# exit when 1 condition
add.rule(qs.strategy, name='ruleSignal',
         arguments = list(sigcol="EMA1.lt.EMA3", sigval=TRUE, orderqty='all',
                          ordertype='market', orderside='long'),
         type='exit')
applyStrategy(strategy=qs.strategy , portfolios=qs.strategy)
# transactions
#getTxns(Portfolio=qs.strategy, Symbol="SPY")
checkBlotterUpdate(b.strategy,b.strategy)
## [1] TRUE
# update portfolio/account
updatePortf(qs.strategy)
updateAcct(qs.strategy)
updateEndEq(qs.strategy)
tstats <- t(tradeStats(qs.strategy))
perTradeStats(qs.strategy)
library(lattice)
a <- getAccount(qs.strategy)
xyplot(a$summary,type="h",col=4)
equity <- a$summary$End.Eq
plot(equity,main="Giulio Strategy Equity Curve")
ret <- Return.calculate(equity,method="log")
charts.PerformanceSummary(ret, colorset = bluefocus,
                          main="Giulio Strategy Performance")

谁能帮我理解为什么第二个代码没有给出相同的结果?我认为我的错误是在add.indicator, add.signal, add.rule设置,但我不能准确地找出它。

基于量子论的代码由于几个原因不会提供相同的结果。一个是你的列是不正确的在你的前3 add.signal调用。所有列都需要有一个"EMA."前缀:

add.signal(qs.strategy,name="sigComparison",
  arguments = list(columns=c("EMA.EMA1","EMA.EMA2"),relationship="gt"),
  label="EMA1.gt.EMA2")
add.signal(qs.strategy,name="sigComparison",
  arguments = list(columns=c("EMA.EMA1","EMA.EMA3"),relationship="gt"),
  label="EMA1.gt.EMA3")
add.signal(qs.strategy,name="sigComparison",
  arguments = list(columns=c("EMA.EMA1","EMA.EMA1_lag"),relationship="gt"),
  label="EMA1.gt.EMA1_lag")

另一个问题,可能是造成差异的最大原因,是下一个信号:

add.signal(qs.strategy, name = "sigFormula",
  arguments = list(formula="EMA1.gt.EMA2 & EMA1.gt.EMA3 & EMA1.gt.EMA1_lag"),
  label="longEntry")

这将为公式为真的每个观测值创建一个信号,而不仅仅是公式从假变为真的观测值。您只需要公式交叉处的观测值,因此您应该使用:

add.signal(qs.strategy, name = "sigFormula",
  arguments = list(formula="EMA1.gt.EMA2 & EMA1.gt.EMA3 & EMA1.gt.EMA1_lag",
  cross = TRUE),
  label="longEntry")

差异的另一个来源是,在吸盘版本中,您总是使用~100%的可用股本进行开场多头交易,但在量子版本中,您总是购买900股。在quantstrat中,您可以通过使用自定义顺序大小函数来完成类似的工作(有关如何编写自定义顺序大小函数的示例,请参阅osNoOposMaxPos)。

相关内容

  • 没有找到相关文章