1

我試圖用「quantstrat」包來回溯交易策略。我的策略由4個指標,3個不同的EMA和1個滯後的EMA組成。從R轉換爲quantstrat設置進行交易策略回測

我想去的地方時長:EMA1> EMA2 & EMA1> EMA3 & EMA1_lag < EMA1 我想退出和走平的時候:EMA1 < EMA3

這很簡單,但我不能寫呢進入量子環境。

這裏是在這兩個例子中使用的數據完整性檢查功能:

# 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設置中,但我無法精確地找出它。

回答

2

由於多種原因,基於量子的代碼不會提供相同的結果。一個是你的第一個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%爲您開啓長事務,但你總是購買quantstrat版本900股。您可以使用自定義訂單大小調整功能來在quantstrat中執行類似操作(有關如何編寫自定義訂單大小調整功能的示例,請參閱osNoOposMaxPos)。