1

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

我想在以下情况下做多:EMA1 > EMA2 & EMA1 > EMA3 & EMA1_lag < EMA1 我想在以下情况下平仓平仓:EMA1 < EMA3

这很简单,但我无法将其写入 quantstrat 环境。

这是两个示例中使用的数据完整性检查功能:

# 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设置中,但我无法准确地弄清楚。

4

1 回答 1

3

由于几个原因,基于 quastrat 的代码不会提供相同的结果。一个是您的前 3add.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% 的可用资产来进行记账版本的开仓多头交易,但在 quantstrat 版本中您总是购买 900 股。您可以在 quantstrat 中通过使用自定义定单调整函数来执行类似的操作(请参阅有关如何编写自定义定单调整函数的示例)osNoOposMaxPos

于 2015-09-10T14:41:20.950 回答