【问题标题】:Quantstrat Trade Statistics yielding -100% cumulative returns?Quantstrat 贸易统计产生 -100% 的累积回报?
【发布时间】:2018-10-01 08:58:41
【问题描述】:

我在 Quantstrat 上使用交易统计并获得了与这个世界不同的正结束股票(起始股票 = 1m)。然而,令人费解的是,当我将业绩列成表格时,累积回报是-1.0。

如何才能拥有正的期末净值和负的累积回报?我对结束股权的理解是错误的吗?

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 ="2009-01-01"
to ="2013-01-01"
symbols = c("SPY")
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(portfolio.st)
rm.strat(account.st)


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<- 200
nEMAM<- 30
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")

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

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



### Add Signal- Enter

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

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

### Add rule - Enter

add.rule(strategy.st,
         name='ruleSignal',
         arguments = list(sigcol="upSig.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)
}

tstats <- tradeStats(portfolio.st)
t(tstats)

rets <- PortfReturns(Account = account.st)
rownames(rets) <- NULL
charts.PerformanceSummary(rets, colorset = bluefocus)

tab.perf <- table.Arbitrary(rets,
                            metrics=c(
                              "Return.cumulative",
                              "Return.annualized",
                              "SharpeRatio.annualized",
                              "CalmarRatio"),
                            metricsNames=c(
                              "Cumulative Return",
                              "Annualized Return",
                              "Annualized Sharpe Ratio",
                              "Calmar Ratio"))
tab.perf


#Test here
#test <-try(applyIndicators(strategy.st,mktdata=OHLC(AAPL)))
#head(test, n=40)

【问题讨论】:

    标签: r trading quantstrat technical-indicator


    【解决方案1】:

    首先,您只是进入了很多多头头寸。然后是很多连续的退出交易!问题是您在很长一段时间内在每个信号条上都收到了长进场信号。而且您不会限制您的策略进入越来越多的多头头寸,每个头寸大小为 1000。您可以使用osMaxPosaddPosLimit 来处理在特定方向开仓时限制可能的交易数量。

    以下是您可以停止在每个栏上出现如此多长条目的方法。当 rsi 上下穿过 50 时,您希望输入为真。使用sigCrossover。其次,使用addPosLimit 来限制允许的总仓位大小。下次也看看mktdata 来调试你的策略,检查你没有一个接一个的多个入场信号。

    因为您提供了无意义的输入,您将获得 -1 的回报。如此多的买入(当入场信号为真时,您连续每天买入 1k 单位,然后连续卖出更多天)。显然这不是故意的。检查getTxns 的输出以查看问题。此外,您的最终资产可能为负数,因为您只是将投资组合中的现金盈亏加到初始资本中。即,一旦您的实际资产变为负数,quantstrat 就不会停止交易。你可以这样想:quantstrat 只是假设你有更多资金可以交易,即使你的损失超过初始净值,也会继续交易。

    如果你设置了合理的参数,你的净值永远不会在 quantstrat 中变为负数(除非你的策略真的很糟糕并且一直在亏损,或者你在回测中交易了很长时间,以至于破产或更糟的可能性很大在允许的时间内发生)。

    这里有一些调整,即sigCrossover 并使用 300 的交易规模,在您的策略中获得更合理的数字。也使用osMaxPos。它仍然在这里购买最多 3 个级别的堆叠头寸。

    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 ="2009-01-01"
    to ="2013-01-01"
    symbols = c("SPY")
    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(portfolio.st)
    rm.strat(account.st)
    
    
    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<- 200
    nEMAM<- 30
    nEMAS<- 13
    nEMAF<- 5
    
    tradeSize <- 100
    for (sym in symbols) {
      addPosLimit(portfolio.st, sym, start(get(sym)), maxpos = 300, longlevels = 3)
    }
    
    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")
    
    # important to set cross = TRUE in sigThreshold
    add.signal(strategy.st, name = "sigThreshold",
               arguments = list(column = "rsi", threshold = 50, relationship = "gt", cross = TRUE),
               label = "rsiUp")
    
    add.signal(strategy.st, name = "sigThreshold",
               arguments = list(column = "rsi", threshold = 50, relationship = "lt", cross = TRUE),
               label = "rsiDn")
    
    upsig <- function(data) {
      sig <- data[, "rsiUp"] & data[, "EMA.EMAM"] > data[, "EMA.EMAL"]   
      colnames(sig) <- "upSig"
      sig
    }
    
    downsig <- function(data) {
      sig <- data[, "rsiDn"] & data[, "EMA.EMAM"] < data[, "EMA.EMAL"]   
      colnames(sig) <- "downSig"
      sig
    }
    
    
    
    ### Add Signal- Enter
    
    add.signal(strategy.st, name="upsig",
               arguments=list(data = quote(mktdata)),
               label = "entersig")
    
    add.signal(strategy.st, name="downsig",
               arguments=list(data = quote(mktdata)),
               label = "exitsig")
    
    ### Add rule - Enter
    
    add.rule(strategy.st,
             name='ruleSignal',
             arguments = list(sigcol="upSig.entersig",
                              sigval=TRUE,
                              orderqty=100,
                              ordertype='market',
                              orderside='long',
                              threshold=NULL,
                              osFUN = osMaxPos), # <- need this to cap trade levels to at most 3
             type='enter',
             path.dep=TRUE)
    
    
    ### Add rule- Exit
    
    add.rule(strategy.st,
             name='ruleSignal',
             arguments = list(sigcol="downSig.exitsig",
                              sigval=TRUE,
                              orderqty= -100,
                              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)
    }
    
    tstats <- tradeStats(portfolio.st)
    t(tstats)
    
    rets <- PortfReturns(Account = account.st)
    rownames(rets) <- NULL
    charts.PerformanceSummary(rets, colorset = bluefocus)
    
    tab.perf <- table.Arbitrary(rets,
                                metrics=c(
                                  "Return.cumulative",
                                  "Return.annualized",
                                  "SharpeRatio.annualized",
                                  "CalmarRatio"),
                                metricsNames=c(
                                  "Cumulative Return",
                                  "Annualized Return",
                                  "Annualized Sharpe Ratio",
                                  "Calmar Ratio"))
    tab.perf
    
    
    tail(.blotter$account.mystrat$summary)
    # Additions Withdrawals Realized.PL Unrealized.PL Interest Gross.Trading.PL Txn.Fees Net.Trading.PL Advisory.Fees Net.Performance  End.Eq
    # 2012-12-20 19:00:00         0           0           0        -392.4        0        -392.4006        0      -392.4006             0       -392.4006 1012255
    # 2012-12-23 19:00:00         0           0           0        -132.0        0        -131.9961        0      -131.9961             0       -131.9961 1012123
    # 2012-12-25 19:00:00         0           0           0        -180.0        0        -180.0018        0      -180.0018             0       -180.0018 1011943
    # 2012-12-26 19:00:00         0           0           0         -57.0        0         -57.0006        0       -57.0006             0        -57.0006 1011886
    # 2012-12-27 19:00:00         0           0           0        -459.0        0        -458.9997        0      -458.9997             0       -458.9997 1011427
    # 2012-12-30 19:00:00         0           0           0         714.0        0         714.0015        0       714.0015             0        714.0015 1012141
    

    【讨论】:

    • #FXQantTrader:感谢您在许多 SO quantstrat 帖子上的 cmets/answers;在这里我有一个问题。您提供建议,以免“一排接一排地出现多个入场信号”。当然,您会同意强信号(无论方向如何)可能会持续数天(行)。那么你为什么认为这是一个问题呢?
    • @WBarker 嗨。让指标/信号在多个柱(“天/行”)上保持看涨是可以的,但我的意思是让特定信号对应在一个柱之后逐步增加头寸是没有意义的另一个用于“数十”行连续。这对我来说没有任何意义。你肯定有逻辑,每次你得到一个强烈的买入/卖出信号时,你肯定会在头寸中堆积/金字塔(这样的交易很可能会略微降低你的盈亏波动率/提升锐度),但你不想人为地这样做一个接一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2021-07-21
    • 2011-02-19
    相关资源
    最近更新 更多