2015-03-31 65 views
3

一般信息:Quantstrat多种货币。 Blotter :: UpdateAcct中可能存在的Bug

R-版本:3.1.0

吸墨纸: 0.8.19

问题描述:

我想实现一个quantstrat帐户它使用多个不同货币的portofolios。

因此,这里是我的基本设置:

  • 1帐户EUR
  • 1组合在于是为了USD

这个工作我必须设置的汇率,这是我基于从雅虎检索的数据。然后,我应该运行我的基本策略,并通过updateAcct函数在最后一步自动完成转换。

现在这里是擦...我认为updateAcct函数有一个错误。

mycode的:

initDate="1990-01-01" 
from="2007-01-01" 
to="2012-12-31" 
options(width=70) 

options("getSymbols.warning4.0"=FALSE) 
currency(c('USD','EUR')) 
exchange_rate("USDEUR", tick_size = 0.01) 
USDEUR <- Cl(getSymbols("EUR=X",src="yahoo", auto.assign = FALSE)) 
Sys.setenv(TZ="UTC") 
#not sure why this might work 
.blotter <- new.env() 
.strategy <- new.env() 

symbols <- c("^IXIC" #Nasdaq 
      ) 
if(!"XLB" %in% ls()) { 
    suppressMessages(getSymbols(symbols, from=from, to=to, src="yahoo", adjust=TRUE)) 
    } 

#need this to remove index call symbol (yahoo.) from string. I.e. get ^IXIC, but named IXIC 
symbols<-gsub("\\^", "", symbols) 

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

#trade sizing and initial equity settings 
tradeSize <- 10000 
initEq <- tradeSize*length(symbols) 
strategy.st <- portfolio.st <- account.st <- "TradeNasdaq100" 

#clear old strategies etc. 
suppressWarnings(try(rm.strat(strategy.st), silent=TRUE)) 

#initialize portfolio and account 
initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD') 
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='EUR',initEq=initEq) 
initOrders(portfolio.st, initDate=initDate) 
strategy(strategy.st, store=TRUE) 

然后我用一些指标,信号,规则等....

#apply strategy 
t1 <- Sys.time() 
out <- applyStrategy(strategy=strategy.st,portfolios=portfolio.st) 
t2 <- Sys.time() 
print(t2-t1) 
#set up analytics 
updatePortf(portfolio.st) 
dateRange <- time(getPortfolio(portfolio.st)$summary)[-1] 
updateAcct(account.st,dateRange) 

一切正常,直到代码到达最后一行。

最后一行会给出错误信息:Error in isTRUE(invert) : object 'invert' not found

可能的错误: 所以我决定检查出updateAcct功能在这里试用了一下调试......我敢肯定,有是代码中的错误。第63行的if子句查询isTRUE(反转),但仅当反转实际为真时才创建反转(请参阅其他子句第46行)。但是invert没有初始化,因此如果它实际上是false,代码将会失败。

这里的源代码记事簿(原)

function (name = "default", Dates = NULL) 
{ 
    Account <- getAccount(name) 
    if (!is.null(attr(Account, "currency"))) { 
     a.ccy.str <- attr(Account, "currency") 
    } 
    Portfolios = names(Account$portfolios) 
    if (is.null(Dates)) 
     Dates <- unique(do.call(c, c(lapply(Portfolios, function(x) index(.getPortfolio(x)$summary)), 
      use.names = FALSE, recursive = FALSE)))[-1] 
    if (!length(Dates)) 
     return(name) 
    if (last(index(Account$summary)) > .parseISO8601(Dates)$first.time) { 
     whichi <- first(Account$summary[paste(.parseISO8601(Dates)$first.time, 
      "::", sep = ""), which.i = TRUE]) 
     if (!is.null(whichi)) 
      whichi = whichi - 1 
     if (whichi < 1) 
      whichi = 1 
     Account$summary = Account$summary[1:whichi, ] 
    } 
    for (pname in Portfolios) { 
     Portfolio = .getPortfolio(pname) 
     if (!is.null(attr(Portfolio, "currency"))) { 
      p.ccy.str <- attr(Portfolio, "currency") 
     } 
     psummary = Portfolio$summary[Dates] 
     if (a.ccy.str != p.ccy.str) { 
      CcyMult <- NA 
      port_currency <- try(getInstrument(p.ccy.str), silent = TRUE) 
      if (inherits(port_currency, "try-error") | !is.instrument(port_currency)) { 
       warning("Currency", p.ccy.str, " not found, using currency multiplier of 1") 
       CcyMult <- 1 
      } 
      else { 
       FXrate.str <- paste(p.ccy.str, a.ccy.str, sep = "") 
       FXrate <- try(get(FXrate.str), silent = TRUE) 
       if (inherits(FXrate, "try-error")) { 
        FXrate.str <- paste(a.ccy.str, p.ccy.str, sep = "") 
        FXrate <- try(get(FXrate.str), silent = TRUE) 
        if (inherits(FXrate, "try-error")) { 
        warning("Exchange Rate", FXrate.str, " not found for symbol,',Symbol,' using currency multiplier of 1") 
        CcyMult <- 1 
        } 
        else { 
        invert = TRUE 
        } 
       } 
      } 
      if (is.na(CcyMult) && !is.na(FXrate)) { 
       if (inherits(FXrate, "xts")) { 
        CcyMult <- FXrate[Dates] 
        CcyMult <- na.locf(merge(CcyMult, index(psummary))) 
        CcyMult <- drop(CcyMult[index(psummary)]) 
       } 
       else { 
        CcyMult <- as.numeric(FXrate) 
       } 
      } 
      else { 
       CcyMult <- 1 
      } 
      if (isTRUE(invert)) { 
       CcyMult <- 1/CcyMult 
      } 
      psummary <- psummary * CcyMult 
     } 
     Account$portfolios[[pname]] = rbind(Account$portfolios[[pname]], 
      psummary) 
    } 
    summary = NULL 
    table = .getByPortf(Account, "Net.Trading.PL", Dates) 
    obsLength = length(index(table)) 
    obsDates = index(table) 
    if (obsLength > 1) 
     on = periodicity(table)$units 
    else on = "none" 
    Attributes = c("Additions", "Withdrawals", "Realized.PL", 
     "Unrealized.PL", "Interest", "Gross.Trading.PL", "Txn.Fees", 
     "Net.Trading.PL", "Advisory.Fees", "Net.Performance", 
     "End.Eq") 
    for (Attribute in Attributes) { 
     switch(Attribute, Realized.PL = , Unrealized.PL = , Gross.Trading.PL = , 
      Txn.Fees = , Net.Trading.PL = { 
       table = .getByPortf(Account, Attribute, Dates) 
       result = xts(rowSums(table, na.rm = TRUE), order.by = index(table)) 
      }, Additions = { 
       result = if (on == "none") as.xts(sum(Account$Additions[paste("::", 
        obsDates, sep = "")]), order.by = index(table)) else { 
        if (length(Account$Additions[obsDates]) > 0) period.apply(Account$Additions[obsDates], 
        endpoints(Account$Additions[obsDates], on = on), 
        sum) else xts(rep(0, obsLength), order.by = obsDates) 
       } 
      }, Withdrawals = { 
       result = if (on == "none") as.xts(sum(Account$Withdrawals[paste("::", 
        obsDates, sep = "")]), order.by = index(table)) else { 
        if (length(Account$Additions[obsDates]) > 0) period.apply(Account$Withdrawals[obsDates], 
        endpoints(Account$Withdrawals[obsDates], 
         on = periodicity(table)$units), sum) else xts(rep(0, 
        obsLength), order.by = obsDates) 
       } 
      }, Interest = { 
       result = if (on == "none") as.xts(sum(Account$Interest[paste("::", 
        obsDates, sep = "")]), , order.by = index(table)) else { 
        if (length(Account$Additions[obsDates]) > 0) period.apply(Account$Interest[obsDates], 
        endpoints(Account$Interest[obsDates], on = periodicity(table)$units), 
        sum) else xts(rep(0, obsLength), order.by = obsDates) 
       } 
      }, Advisory.Fees = , Net.Performance = , End.Eq = { 
       result = xts(rep(0, obsLength), order.by = obsDates) 
      }) 
     colnames(result) = Attribute 
     if (is.null(summary)) { 
      summary = result 
     } 
     else { 
      summary = cbind(summary, result) 
     } 
    } 
    summary[is.na(summary)] <- 0 
    Account$summary <- rbind(Account$summary, summary) 
    assign(paste("account", name, sep = "."), Account, envir = .blotter) 
    return(name) 
} 

这里是我认为它应该像(摘录行28-50)...

if (a.ccy.str != p.ccy.str) { 
    CcyMult <- NA 
    port_currency <- try(getInstrument(p.ccy.str), silent = TRUE) 
    if (inherits(port_currency, "try-error") | !is.instrument(port_currency)) { 
    warning("Currency", p.ccy.str, " not found, using currency multiplier of 1") 
    CcyMult <- 1 
    } 
    else { 
    FXrate.str <- paste(p.ccy.str, a.ccy.str, sep = "") 
    FXrate <- try(get(FXrate.str), silent = TRUE) 
    invert=FALSE #THIS IS THE LINE NEEDED FOR FIXING 
    if (inherits(FXrate, "try-error")) { 
     FXrate.str <- paste(a.ccy.str, p.ccy.str, sep = "") 
     FXrate <- try(get(FXrate.str), silent = TRUE) 
     if (inherits(FXrate, "try-error")) { 
     warning("Exchange Rate", FXrate.str, " not found for symbol,',Symbol,' using currency multiplier of 1") 
     CcyMult <- 1 
     } 
     else { 
     invert = TRUE 
     } 
    } 
    } 

TL ; DR

我认为在流水账中存在一个错误:当货币兑换不需要反转汇率时发生updateAcct ...

问题: 我是对的,这是一个错误?或者我错过了什么?

PS:

我通常会提交这是一个错误,但A)我不知道如何向笔者B中的错误)我仍然quantstrat,总结和公司,我认为一个新手别人也应该检查这一点(作者也经常在这里闲逛)...

回答

3

感谢您的可重复的例子。为了将来的参考,最好提供一个比20-30行代码差的代码。我花了一段时间才注意到你刚刚添加了一行。

> svn diff blotter/R/updateAcct.R 
Index: blotter/R/updateAcct.R 
=================================================================== 
--- blotter/R/updateAcct.R (revision 1681) 
+++ blotter/R/updateAcct.R (working copy) 
@@ -51,6 +51,7 @@ 
       FXrate.str<-paste(p.ccy.str,a.ccy.str,sep='') # currency quote convention is EURUSD which reads as "USD per EUR" 
       FXrate<-try(get(FXrate.str), silent=TRUE) 
       #TODO FIXME: this uses convention to sort out the rate, we should check $currency and $counter_currency and make sure directionality is correct 
+    invert=FALSE 
       if(inherits(FXrate,"try-error")){ 
        FXrate.str<-paste(a.ccy.str,p.ccy.str,sep='') 
        FXrate<-try(get(FXrate.str), silent=TRUE) 

固定在revision 1682。感谢报告!

+0

谢谢约书亚!我将来会这样做。快速问题:有没有一种正确的方法来报告错误?不知道SO是否适合它。 – user3293236 2015-04-02 05:55:43

+0

@ user3293236:请在[TradeAnalytics R-Forge bug跟踪器](https://r-forge.r-project.org/tracker/?atid=1269&group_id=316&func=browse)上提交错误 – 2015-04-02 13:12:43