From noreply at r-forge.r-project.org Mon Sep 9 21:29:52 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 9 Sep 2013 21:29:52 +0200 (CEST) Subject: [Blotter-commits] r1500 - in pkg/blotter: . R man Message-ID: <20130909192952.6E5F6181213@r-forge.r-project.org> Author: braverock Date: 2013-09-09 21:29:52 +0200 (Mon, 09 Sep 2013) New Revision: 1500 Added: pkg/blotter/R/AcctReturns.R pkg/blotter/man/AcctReturns.Rd Modified: pkg/blotter/DESCRIPTION Log: - add AcctReturns function by Andrii Babii (moved from PortfolioAttribution) Modified: pkg/blotter/DESCRIPTION =================================================================== --- pkg/blotter/DESCRIPTION 2013-08-26 09:01:15 UTC (rev 1499) +++ pkg/blotter/DESCRIPTION 2013-09-09 19:29:52 UTC (rev 1500) @@ -26,42 +26,5 @@ Contributors: Dirk Eddelbuettel, Jan Humme, Lance Levenson, Ben McCann, Jeff Ryan, Garrett See, Joshua Ulrich, Wolfgang Wu URL: https://r-forge.r-project.org/projects/blotter/ -Copyright: (c) 2008-2012 +Copyright: (c) 2008-2013 ByteCompile: TRUE -Collate: - 'PortfReturns.R' - 'addPortfInstr.R' - 'addTxn.R' - 'addAcctTxn.R' - 'calcPortfWgt.R' - 'calcPosAvgCost.R' - 'calcTxnAvgCost.R' - 'calcTxnValue.R' - 'chart.ME.R' - 'chart.Posn.R' - 'chart.Reconcile.R' - 'chart.Spread.R' - 'extractTests.R' - 'getAccount.R' - 'getByPortf.R' - 'getBySymbol.R' - 'getEndEq.R' - 'getPortfAcct.R' - 'getPortfolio.R' - 'getPos.R' - 'getPosAvgCost.R' - 'getPosQty.R' - 'getTxn.R' - 'initAcct.R' - 'initPortf.R' - 'initPosPL.R' - 'initSummary.R' - 'initTxn.R' - 'perTradeStats.R' - 'put.portfolio.R' - 'tradeStats.R' - 'updateAcct.R' - 'updateEndEq.R' - 'updatePortf.R' - 'updatePosPL.R' - 'put.account.R' Added: pkg/blotter/R/AcctReturns.R =================================================================== --- pkg/blotter/R/AcctReturns.R (rev 0) +++ pkg/blotter/R/AcctReturns.R 2013-09-09 19:29:52 UTC (rev 1500) @@ -0,0 +1,129 @@ +#' Calculate account returns +#' +#' Similar to the \code{PortfReturns} function, but gives returns for the +#' entire account and takes into account external cashflows. External cashflows +#' are defined as contributions to or withdrawals from the account. Allows +#' selecting between time-weighted returns and linked modified Dietz approach. +#' If time-weighted method is selected, returns at time \eqn{t} are computed +#' using: \deqn{r_{t}=\frac{V_{t}}{V_{t-1}+C_{t}}-1} +#' where \eqn{V_{t}} - account value at time \eqn{t}, \eqn{C_{t}} - cashflow at +#' time \eqn{t}. The implicit assumption made here is that the cash flow is +#' available for the portfolio manager to invest from the beginning of the day. +#' These returns then can be chain linked with geometric compounding (for +#' instance using \code{Return.cumulative} function from the +#' \code{PerformanceAnalytics} package) to yield cumulative multi-period +#' returns: +#' \deqn{1+r=\prod_{t=1}^{T}(1+r_{t})=\prod_{t=1}^{T}\frac{V_{t}}{V_{t-1}+C_{t}}} +#' In the case if there were no cashflows, the result reduces to simple +#' one-period returns. Time-weighted returns has also an interpretation in +#' terms of unit value pricing. +#' If Modified Dietz method is selected, monthly returns are computed taking +#' into account cashflows within each month: +#' \deqn{r = \frac{V_{t}-V_{t-1}-C}{V_{t-1}+\sum_{t}C_{t}\times W_{t}}} +#' where \eqn{C} - total external cash flows within a month, +#' \eqn{C_{t}} - external cashflow at time \eqn{t}, +#' \deqn{W_{t}=\frac{TD-D_{t}}{TD}} - weighting ratio to be applied to external +#' cashflow on day \eqn{t}, +#' \eqn{TD} - total number of days within the month, +#' \eqn{D_{t}} - number of days since the beginning of the month including +#' weekends and public holidays. +#' Finally monthly Modified Dietz returns can also be linked geometrically. +#' +#' @aliases AcctReturns +#' @param Account string name of the account to generate returns for +#' @param \dots any other passthru parameters (like \code{native} for +#' \code{.getBySymbol} +#' @param Dates xts style ISO 8601 date subset to retrieve, default NULL +#' (all dates) +#' @param Portfolios concatenated string vector for portfolio names to retrieve +#' returns on, default NULL (all portfolios) +#' @param method Used to select between time-weighted and linked modified Dietz +#' returns. May be any of: \itemize{\item timeweighted \item dietz} By default +#' time-weighted is selected +#' @return returns xts with account returns +#' @author Brian Peterson, Andrii Babii +#' @seealso PortfReturns +#' @references Christopherson, Jon A., Carino, David R., Ferson, Wayne E. +#' \emph{Portfolio Performance Measurement and Benchmarking}. McGraw-Hill. +#' 2009. Chapter 5 \cr Bacon, C. \emph{Practical Portfolio Performance +#' Measurement and Attribution}. Wiley. 2004. Chapter 2 \cr +#' @keywords portfolio returns +#' @note +#' TODO handle portfolio and account in different currencies (not hard, just not done) +#' +#' TODO explicitly handle portfolio weights +#' +#' TODO support additions and withdrawals to available capital +#' @export +AcctReturns <- +function(Account, Dates = NULL, Portfolios = NULL, method = c("timeweighted", "dietz"), ...) +{ # @author Brian Peterson, Andrii Babii + aname <- Account + if(!grepl("account\\.", aname)){ + Account <- try(get(paste("account", aname, sep = '.'), envir = .blotter)) + } else{ + Account <- try(get(aname, envir = .blotter)) + } + if(inherits(Account, "try-error")){ + stop(paste("Account ", aname, " not found, use initAcct() to create a new + account")) + } + if(!inherits(Account, "account")){ + stop("Account ", aname, " passed is not the name of an account object.") + } + if(is.null(Portfolios)){ + Portfolios = names(Account$portfolios) + } + + # Get xts with net trading P&L for all portfolios associated with account + table = NULL + for(pname in Portfolios){ + Portfolio <- getPortfolio(pname) + if(is.null(Dates)){ + Dates <- paste("::", last(index(Portfolio$summary)), sep = '') + } + ptable = .getBySymbol(Portfolio = Portfolio, Attribute = "Net.Trading.PL", + Dates = Dates) + if(is.null(table)){ + table=ptable + } + else{ + table=cbind(table,ptable) + } + } + if(!is.null(attr(Account, 'initEq'))){ + initEq <- as.numeric(attr(Account, 'initEq')) + if(initEq == 0){ + stop("Initial equity of zero would produce div by zero NaN, Inf, -Inf + returns, please fix in initAcct().") + } + + #TODO check portfolio and account currencies and convert if necessary + + CF = Account$summary$Additions - Account$summary$Withdrawals # Cashflows + V = initEq + reclass(rowSums(table), table) # Account values + method = method[1] + + if (method == "timeweighted"){ + # Time-weighted returns + returns = V / (lag(V) + CF) - 1 + } + + if (method == "dietz"){ + # Linked modified Dietz + C = apply.monthly(CF, sum) # total monthly cashflow + V = apply.monthly(V, first) # monthly account values + cfweighted <- function(CF){ + TD = ndays(CF) # total number of days within the period + # number of days since the beginning of the period + D = round(as.vector((index(CF) - index(CF)[1])/3600/24)) + W = (TD - D) / TD # weights + cashfl = sum(CF * W) # weighted sum of cashflows within the period + return(cashfl) + } + cashfl = apply.monthly(CF, cfweighted) + returns = (V - lag(V) - C) / (lag(V) + cashfl) # Modified Dietz + } + } + return(returns) +} Added: pkg/blotter/man/AcctReturns.Rd =================================================================== --- pkg/blotter/man/AcctReturns.Rd (rev 0) +++ pkg/blotter/man/AcctReturns.Rd 2013-09-09 19:29:52 UTC (rev 1500) @@ -0,0 +1,88 @@ +\name{AcctReturns} +\alias{AcctReturns} +\title{Calculate account returns} +\usage{ + AcctReturns(Account, Dates = NULL, Portfolios = NULL, + method = c("timeweighted", "dietz"), ...) +} +\arguments{ + \item{Account}{string name of the account to generate + returns for} + + \item{\dots}{any other passthru parameters (like + \code{native} for \code{.getBySymbol}} + + \item{Dates}{xts style ISO 8601 date subset to retrieve, + default NULL (all dates)} + + \item{Portfolios}{concatenated string vector for + portfolio names to retrieve returns on, default NULL (all + portfolios)} + + \item{method}{Used to select between time-weighted and + linked modified Dietz returns. May be any of: + \itemize{\item timeweighted \item dietz} By default + time-weighted is selected} +} +\value{ + returns xts with account returns +} +\description{ + Similar to the \code{PortfReturns} function, but gives + returns for the entire account and takes into account + external cashflows. External cashflows are defined as + contributions to or withdrawals from the account. Allows + selecting between time-weighted returns and linked + modified Dietz approach. If time-weighted method is + selected, returns at time \eqn{t} are computed using: + \deqn{r_{t}=\frac{V_{t}}{V_{t-1}+C_{t}}-1} where + \eqn{V_{t}} - account value at time \eqn{t}, \eqn{C_{t}} + - cashflow at time \eqn{t}. The implicit assumption made + here is that the cash flow is available for the portfolio + manager to invest from the beginning of the day. These + returns then can be chain linked with geometric + compounding (for instance using \code{Return.cumulative} + function from the \code{PerformanceAnalytics} package) to + yield cumulative multi-period returns: + \deqn{1+r=\prod_{t=1}^{T}(1+r_{t})=\prod_{t=1}^{T}\frac{V_{t}}{V_{t-1}+C_{t}}} + In the case if there were no cashflows, the result + reduces to simple one-period returns. Time-weighted + returns has also an interpretation in terms of unit value + pricing. If Modified Dietz method is selected, monthly + returns are computed taking into account cashflows within + each month: \deqn{r = + \frac{V_{t}-V_{t-1}-C}{V_{t-1}+\sum_{t}C_{t}\times + W_{t}}} where \eqn{C} - total external cash flows within + a month, \eqn{C_{t}} - external cashflow at time \eqn{t}, + \deqn{W_{t}=\frac{TD-D_{t}}{TD}} - weighting ratio to be + applied to external cashflow on day \eqn{t}, \eqn{TD} - + total number of days within the month, \eqn{D_{t}} - + number of days since the beginning of the month including + weekends and public holidays. Finally monthly Modified + Dietz returns can also be linked geometrically. +} +\note{ + TODO handle portfolio and account in different currencies + (not hard, just not done) + + TODO explicitly handle portfolio weights + + TODO support additions and withdrawals to available + capital +} +\author{ + Brian Peterson, Andrii Babii +} +\references{ + Christopherson, Jon A., Carino, David R., Ferson, Wayne + E. \emph{Portfolio Performance Measurement and + Benchmarking}. McGraw-Hill. 2009. Chapter 5 \cr Bacon, C. + \emph{Practical Portfolio Performance Measurement and + Attribution}. Wiley. 2004. Chapter 2 \cr +} +\seealso{ + PortfReturns +} +\keyword{portfolio} +\keyword{returns} + From noreply at r-forge.r-project.org Thu Sep 12 18:04:36 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 12 Sep 2013 18:04:36 +0200 (CEST) Subject: [Blotter-commits] r1501 - pkg/quantstrat/demo Message-ID: <20130912160436.E9314183E9A@r-forge.r-project.org> Author: erastus Date: 2013-09-12 18:04:36 +0200 (Thu, 12 Sep 2013) New Revision: 1501 Modified: pkg/quantstrat/demo/macdRebalancing.R Log: - fixed column name match issue in macdRebalancing.R Modified: pkg/quantstrat/demo/macdRebalancing.R =================================================================== --- pkg/quantstrat/demo/macdRebalancing.R 2013-09-09 19:29:52 UTC (rev 1500) +++ pkg/quantstrat/demo/macdRebalancing.R 2013-09-12 16:04:36 UTC (rev 1501) @@ -62,14 +62,14 @@ #two signals add.signal(strat.st,name="sigThreshold", - arguments = list(column="signal", + arguments = list(column="signal.MACD.ind", relationship="gt", threshold=0, cross=TRUE), label="signal.gt.zero") add.signal(strat.st,name="sigThreshold", - arguments = list(column="signal", + arguments = list(column="signal.MACD.ind", relationship="lt", threshold=0, cross=TRUE), From noreply at r-forge.r-project.org Fri Sep 13 19:13:11 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 13 Sep 2013 19:13:11 +0200 (CEST) Subject: [Blotter-commits] r1502 - pkg/blotter/R Message-ID: <20130913171311.36754184D98@r-forge.r-project.org> Author: braverock Date: 2013-09-13 19:13:10 +0200 (Fri, 13 Sep 2013) New Revision: 1502 Modified: pkg/blotter/R/initPortf.R Log: - change portfolio list to a hashed environent, thanks to JR and Josh Ulrich for pointers Modified: pkg/blotter/R/initPortf.R =================================================================== --- pkg/blotter/R/initPortf.R 2013-09-12 16:04:36 UTC (rev 1501) +++ pkg/blotter/R/initPortf.R 2013-09-13 17:13:10 UTC (rev 1502) @@ -60,30 +60,35 @@ #' @export initPortf <- function(name="default", symbols, initPosQty = 0, initDate = '1950-01-01', currency='USD', ...) { # @author Peter Carl - if(exists(paste("portfolio",name,sep='.'), envir=.blotter,inherits=TRUE)) - stop(paste("Portfolio",name,"already exists, use updatePortf() or addPortfInstr() to update it.")) - - # FUNCTION - portfolio=list() - portfolio$symbols=vector("list",length=length(symbols)) - names(portfolio$symbols)=symbols - if(length(initPosQty)==1) - initPosQty=rep(initPosQty, length(symbols)) - if(length(initPosQty)!=length(symbols)) - stop("The length of initPosQty is unequal to the number of symbols in the portfolio.") - for(instrument in symbols){ - i = match(instrument, symbols) - portfolio$symbols[[instrument]]$txn = .initTxn(initDate = initDate, initPosQty = initPosQty[i],...=...) - portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = initPosQty[i],...=...) - portfolio$symbols[[instrument]][[paste('posPL',currency,sep='.')]] = portfolio$symbols[[instrument]]$posPL - } - portfolio$summary<-.initSummary(initDate=initDate) - class(portfolio)<-c("blotter_portfolio", "portfolio") - attr(portfolio,'currency')<-currency - attr(portfolio,'initDate')<-initDate - #return(portfolio) - assign(paste("portfolio",as.character(name),sep='.'),portfolio,envir=.blotter) - return(name) # not sure this is a good idea + if(exists(paste("portfolio",name,sep='.'), envir=.blotter,inherits=TRUE)) + stop(paste("Portfolio",name,"already exists, use updatePortf() or addPortfInstr() to update it.")) + + # FUNCTION + + # portfolio=list() + # Initialize a hashed environment for this portfolio + # Thanks to Jeff Ryan and Josh Ulrich for pointers + portfolio = new.env(hash=TRUE) + + portfolio$symbols=vector("list",length=length(symbols)) + names(portfolio$symbols)=symbols + if(length(initPosQty)==1) + initPosQty=rep(initPosQty, length(symbols)) + if(length(initPosQty)!=length(symbols)) + stop("The length of initPosQty is unequal to the number of symbols in the portfolio.") + for(instrument in symbols){ + i = match(instrument, symbols) + portfolio$symbols[[instrument]]$txn = .initTxn(initDate = initDate, initPosQty = initPosQty[i],...=...) + portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = initPosQty[i],...=...) + portfolio$symbols[[instrument]][[paste('posPL',currency,sep='.')]] = portfolio$symbols[[instrument]]$posPL + } + portfolio$summary<-.initSummary(initDate=initDate) + class(portfolio)<-c("blotter_portfolio", "portfolio") + attr(portfolio,'currency')<-currency + attr(portfolio,'initDate')<-initDate + #return(portfolio) + assign(paste("portfolio",as.character(name),sep='.'),portfolio,envir=.blotter) + return(name) # not sure this is a good idea } ############################################################################### From noreply at r-forge.r-project.org Fri Sep 13 23:37:20 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 13 Sep 2013 23:37:20 +0200 (CEST) Subject: [Blotter-commits] r1503 - in pkg: blotter/R quantstrat/R Message-ID: <20130913213720.9233D185DBF@r-forge.r-project.org> Author: braverock Date: 2013-09-13 23:37:20 +0200 (Fri, 13 Sep 2013) New Revision: 1503 Modified: pkg/blotter/R/calcPortfWgt.R pkg/blotter/R/chart.Posn.R pkg/blotter/R/extractTests.R pkg/blotter/R/getBySymbol.R pkg/blotter/R/initPortf.R pkg/blotter/R/perTradeStats.R pkg/blotter/R/tradeStats.R pkg/blotter/R/updatePortf.R pkg/quantstrat/R/applyStrategy.rebalancing.R pkg/quantstrat/R/orders.R pkg/quantstrat/R/parameters.R pkg/quantstrat/R/paramsets.R pkg/quantstrat/R/rebalance.rules.R pkg/quantstrat/R/strategy.R pkg/quantstrat/R/wrapup.R Log: - almost all the work to convert the symbols slot in portfolio and each asset into an environment - thanks to Josh Ulrich for helping conceptualize this, and JR for the suggestion Modified: pkg/blotter/R/calcPortfWgt.R =================================================================== --- pkg/blotter/R/calcPortfWgt.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/calcPortfWgt.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -31,7 +31,7 @@ pname<-Portfolio Portfolio<-getPortfolio(pname) # TODO add Date handling - if(is.null(Symbols)) Symbols<-names(Portfolio$symbols) + if(is.null(Symbols)) Symbols<-ls(Portfolio$symbols) pos.value = .getBySymbol(Portfolio = Portfolio, Dates = Dates, Attribute = "Pos.Value", Symbols = Symbols) portf.value = .getByPortf(Account=getAccount(Account),Attribute = denominator[1], Dates = Dates) Modified: pkg/blotter/R/chart.Posn.R =================================================================== --- pkg/blotter/R/chart.Posn.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/chart.Posn.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -13,7 +13,7 @@ { # @author Peter Carl, Brian Peterson pname<-Portfolio Portfolio<-getPortfolio(pname) - if (missing(Symbol)) Symbol <- names(Portfolio$symbols)[[1]] + if (missing(Symbol)) Symbol <- ls(Portfolio$symbols)[[1]] else Symbol <- Symbol[1] # FUNCTION Modified: pkg/blotter/R/extractTests.R =================================================================== --- pkg/blotter/R/extractTests.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/extractTests.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -25,7 +25,7 @@ if(inherits(Portfolio,"try-error")) stop(paste("Portfolio",pname," not found, use initPortf() to create a new portfolio first")) out<-NULL - symbolnames<-names(Portfolio[['symbols']]) + symbolnames<-ls(Portfolio[['symbols']]) for (Symbol in symbolnames) { tmpTxns<-Portfolio$symbols[[Symbol]]$txn[-1,] if (nrow(tmpTxns)>=1){ Modified: pkg/blotter/R/getBySymbol.R =================================================================== --- pkg/blotter/R/getBySymbol.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/getBySymbol.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -32,7 +32,7 @@ table = NULL ## Need a reference time index if(is.null(Symbols)) - symbols=names(Portfolio$symbols) + symbols=ls(Portfolio$symbols) else symbols = Symbols Modified: pkg/blotter/R/initPortf.R =================================================================== --- pkg/blotter/R/initPortf.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/initPortf.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -3,7 +3,7 @@ #' Constructs and initializes a portfolio object, which is used to contain transactions, positions, and aggregate level values. #' #' Initializes a portfolio object, which is constructed from the following: -#' $symbols: the identifier used for each instrument contained in the portfolio. Use \code{names(Portfolio$symbols)} to get a list of symbols. +#' $symbols: the identifier used for each instrument contained in the portfolio. Use \code{ls(Portfolio$symbols)} to get a list of symbols. #' $symbols$[symbol]$txn: irregular xts object of transactions data #' $symbols$[symbol]$posPL: regular xts object of positions P&L calculated from transactions #' $symbols$[symbol]$posPL.ccy: regular xts object of positions P&L converted to portfolio currency @@ -70,13 +70,17 @@ # Thanks to Jeff Ryan and Josh Ulrich for pointers portfolio = new.env(hash=TRUE) - portfolio$symbols=vector("list",length=length(symbols)) - names(portfolio$symbols)=symbols + #portfolio$symbols=vector("list",length=length(symbols)) + #names(portfolio$symbols)=symbols + portfolio[['symbols']] = new.env(hash=TRUE) + if(length(initPosQty)==1) initPosQty=rep(initPosQty, length(symbols)) if(length(initPosQty)!=length(symbols)) stop("The length of initPosQty is unequal to the number of symbols in the portfolio.") for(instrument in symbols){ + portfolio$symbols[[instrument]] = new.env(hash=TRUE) + #portfolio$symbols[[instrument]] = list() i = match(instrument, symbols) portfolio$symbols[[instrument]]$txn = .initTxn(initDate = initDate, initPosQty = initPosQty[i],...=...) portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = initPosQty[i],...=...) Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/perTradeStats.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -46,7 +46,7 @@ perTradeStats <- function(Portfolio, Symbol, includeOpenTrade=TRUE, ...) { portf <- getPortfolio(Portfolio) - if(missing(Symbol)) Symbol <- names(portf$symbols)[[1]] + if(missing(Symbol)) Symbol <- ls(portf$symbols)[[1]] posPL <- portf$symbols[[Symbol]]$posPL Modified: pkg/blotter/R/tradeStats.R =================================================================== --- pkg/blotter/R/tradeStats.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/tradeStats.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -104,7 +104,7 @@ ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- names(Portfolio$symbols) + if(missing(Symbols)) symbols <- ls(Portfolio$symbols) else symbols <- Symbols ## Trade Statistics @@ -258,7 +258,7 @@ ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- names(Portfolio$symbols) + if(missing(Symbols)) symbols <- ls(Portfolio$symbols) else symbols <- Symbols ## Trade Statistics @@ -301,7 +301,7 @@ ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- names(Portfolio$symbols) + if(missing(Symbols)) symbols <- ls(Portfolio$symbols) else symbols <- Symbols ## Trade Statistics Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/blotter/R/updatePortf.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -17,91 +17,95 @@ #' @export updatePortf <- function(Portfolio, Symbols=NULL, Dates=NULL, Prices=NULL, ...) { #' @author Peter Carl, Brian Peterson - pname<-Portfolio - Portfolio<-getPortfolio(pname) # TODO add Date handling - - # FUNCTION - if(is.null(Symbols)){ - Symbols = names(Portfolio$symbols) - } - for(symbol in Symbols){ - tmp_instr<-try(getInstrument(symbol), silent=TRUE) - .updatePosPL(Portfolio=pname, Symbol=as.character(symbol), Dates=Dates, Prices=Prices, ...=...) - } - - # Calculate and store portfolio summary table - Portfolio<-getPortfolio(pname) # refresh with an updated object - if(is.null(Dates)) Dates <- xts:::time.xts(Portfolio$symbols[[1]]$posPL) #not quite right, only using first symbol... - #Symbols = names(Portfolio$symbols) - Attributes = c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value', 'Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') - summary = NULL - tmp.attr=NULL - for(attribute in Attributes) { - result=NULL - switch(attribute, - Net.Value =, - Gross.Value =, - Long.Value =, - Short.Value =,{ - # all these use Pos.Value - if(is.null(tmp.attr)){ - table = .getBySymbol(Portfolio = Portfolio, Attribute = "Pos.Value", Dates = Dates, Symbols = Symbols) - tmp.attr="Pos.Value" - } - switch(attribute, - Gross.Value = { result = xts(rowSums(abs(table), na.rm=TRUE), order.by=index(table))}, - Long.Value = { tmat = apply(table,MARGIN=c(1,2),FUN=max,0)# comes out a matrix - result = xts(rowSums(tmat, na.rm=TRUE), order.by=index(table)) - }, - Short.Value = { tmat = apply(table,MARGIN=c(1,2),FUN=min,0) # comes out a matrix - result = xts(rowSums(tmat, na.rm=TRUE), order.by=index(table)) - }, - Net.Value = { result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) } - ) - }, - Period.Realized.PL =, - Period.Unrealized.PL =, - Gross.Trading.PL =, - Txn.Fees =, - Net.Trading.PL = { - table = .getBySymbol(Portfolio = Portfolio, Attribute = attribute, Dates = Dates, Symbols = Symbols) - tmp.attr = NULL - result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) - } - ) - - colnames(result) = attribute - if(is.null(summary)) {summary=result} - else {summary=cbind(summary,result)} - } - - # get rid of duplicated indices in the summary data, - # thanks to Guy Yollin for the bug report and Josh Ulrich for the elegant approach to fixing it - d <- duplicated(.index(summary)) | duplicated(.index(summary), fromLast=TRUE) - if(any(d)){ - f <- function(x) { - cLast <- c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value') - cSums <- c('Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') - setNames( merge(last(x[,cLast]), xts(t(colSums(x[,cSums],na.rm=TRUE)),last(index(x)))), colnames(x) ) - } - summary.dups <- summary[d,] - ds <- duplicated(.index(summary.dups)) & !duplicated(.index(summary.dups), fromLast=TRUE) - slist <- period.apply(summary.dups, c(0, which(ds)), f) - summary <- rbind(summary[!d,], slist) # put it all back together - } - - if(!is.timeBased(Dates)) Dates = xts:::time.xts(Portfolio$symbols[[1]][["posPL"]][Dates]) - startDate = first(xts:::.parseISO8601(Dates))$first.time-.00001 - # trim summary slot to not double count, related to bug 831 on R-Forge, and rbind new summary - if( as.POSIXct(attr(Portfolio,'initDate'))>=startDate || length(Portfolio$summary)==0 ){ - Portfolio$summary<-summary #changes to subset might not return a empty dimnames set of columns - }else{ - Portfolio$summary<-rbind(Portfolio$summary[paste('::',startDate,sep='')],summary) - } - # assign Portfolio to environment - assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) - - return(pname) #not sure this is a good idea + pname<-Portfolio + Portfolio<-getPortfolio(pname) # TODO add Date handling + + # FUNCTION + if(is.null(Symbols)){ + Symbols = ls(Portfolio$symbols) + } + for(symbol in Symbols){ + tmp_instr<-try(getInstrument(symbol), silent=TRUE) + .updatePosPL(Portfolio=pname, Symbol=as.character(symbol), Dates=Dates, Prices=Prices, ...=...) + } + + # Calculate and store portfolio summary table + Portfolio<-getPortfolio(pname) # refresh with an updated object + #if(is.null(Dates)) Dates <- xts:::time.xts(Portfolio$symbols[[1]]$posPL) #not quite right, only using first symbol... + if(is.null(Dates)) Dates <- xts(,do.call(unlist,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) )))) + + #Symbols = ls(Portfolio$symbols) + Attributes = c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value', 'Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') + summary = NULL + tmp.attr=NULL + for(attribute in Attributes) { + result=NULL + switch(attribute, + Net.Value =, + Gross.Value =, + Long.Value =, + Short.Value =,{ + # all these use Pos.Value + if(is.null(tmp.attr)){ + table = .getBySymbol(Portfolio = Portfolio, Attribute = "Pos.Value", Dates = Dates, Symbols = Symbols) + tmp.attr="Pos.Value" + } + switch(attribute, + Gross.Value = { result = xts(rowSums(abs(table), na.rm=TRUE), order.by=index(table))}, + Long.Value = { tmat = apply(table,MARGIN=c(1,2),FUN=max,0)# comes out a matrix + result = xts(rowSums(tmat, na.rm=TRUE), order.by=index(table)) + }, + Short.Value = { tmat = apply(table,MARGIN=c(1,2),FUN=min,0) # comes out a matrix + result = xts(rowSums(tmat, na.rm=TRUE), order.by=index(table)) + }, + Net.Value = { result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) } + ) + }, + Period.Realized.PL =, + Period.Unrealized.PL =, + Gross.Trading.PL =, + Txn.Fees =, + Net.Trading.PL = { + table = .getBySymbol(Portfolio = Portfolio, Attribute = attribute, Dates = Dates, Symbols = Symbols) + tmp.attr = NULL + result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) + } + ) + + colnames(result) = attribute + if(is.null(summary)) {summary=result} + else {summary=cbind(summary,result)} + } + + # get rid of duplicated indices in the summary data, + # thanks to Guy Yollin for the bug report and Josh Ulrich for the elegant approach to fixing it + d <- duplicated(.index(summary)) | duplicated(.index(summary), fromLast=TRUE) + if(any(d)){ + f <- function(x) { + cLast <- c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value') + cSums <- c('Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') + setNames( merge(last(x[,cLast]), xts(t(colSums(x[,cSums],na.rm=TRUE)),last(index(x)))), colnames(x) ) + } + summary.dups <- summary[d,] + ds <- duplicated(.index(summary.dups)) & !duplicated(.index(summary.dups), fromLast=TRUE) + slist <- period.apply(summary.dups, c(0, which(ds)), f) + summary <- rbind(summary[!d,], slist) # put it all back together + } + + # if(!is.timeBased(Dates)) Dates = xts:::time.xts(Portfolio$symbols[[1]][["posPL"]][Dates]) + #xts(,do.call(unlist,c(lapply(symbols,index),use.names=FALSE))) + if(!is.timeBased(Dates)) Dates <- xts(,do.call(unlist,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) )))) + startDate = first(xts:::.parseISO8601(Dates))$first.time-.00001 + # trim summary slot to not double count, related to bug 831 on R-Forge, and rbind new summary + if( as.POSIXct(attr(Portfolio,'initDate'))>=startDate || length(Portfolio$summary)==0 ){ + Portfolio$summary<-summary #changes to subset might not return a empty dimnames set of columns + }else{ + Portfolio$summary<-rbind(Portfolio$summary[paste('::',startDate,sep='')],summary) + } + # assign Portfolio to environment + assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) + + return(pname) #not sure this is a good idea } ############################################################################### Modified: pkg/quantstrat/R/applyStrategy.rebalancing.R =================================================================== --- pkg/quantstrat/R/applyStrategy.rebalancing.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/applyStrategy.rebalancing.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -76,7 +76,7 @@ ret[[portfolio]]<-list() # this is slot [[i]] which we will use later pobj<-getPortfolio(portfolio) - symbols<-names(pobj$symbols) + symbols<-ls(pobj$symbols) st<-new.env() #should be able to use this directly Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/orders.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -87,7 +87,7 @@ if(is.null(symbols)) { pfolio<-getPortfolio(portfolio) - symbols<-names(pfolio$symbols) + symbols<-ls(pfolio$symbols) } if(!is.null(symbols)){ orders[[portfolio]][symbols] <- list(NULL) Modified: pkg/quantstrat/R/parameters.R =================================================================== --- pkg/quantstrat/R/parameters.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/parameters.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -398,11 +398,11 @@ #need to create combination of distribution values in each slot of the parameterPool initialPortf<-getPortfolio(portfolios) - symbols<-names(initialPortf$symbols) + symbols<-ls(initialPortf$symbols) initDate<-time(first(initialPortf$symbols[[1]]$posPL)) limits<-list() - for(symbol in names(initialPortf$symbols)) + for(symbol in ls(initialPortf$symbols)) limits[[symbol]]<-initialPortf$symbols[[symbol]]$PosLimit tmp_strategy<-strategy Modified: pkg/quantstrat/R/paramsets.R =================================================================== --- pkg/quantstrat/R/paramsets.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/paramsets.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -11,7 +11,7 @@ # ############################################################################### # -# Authors: Yu Chen, Jan Humme +# Authors: Jan Humme, Brian Peterson # # This code is a based on earlier work by Yu Chen # @@ -51,7 +51,7 @@ if(strip.history==TRUE) { - for(symbol in names(portfolio$symbols)) + for(symbol in ls(portfolio$symbols)) { portfolio$symbols[[symbol]]$txn <- portfolio$symbols[[symbol]]$txn[1,] Modified: pkg/quantstrat/R/rebalance.rules.R =================================================================== --- pkg/quantstrat/R/rebalance.rules.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/rebalance.rules.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -1,118 +1,118 @@ -#' rule to base trade size on a percentage of available equity. -#' -#' This rule works with \code{\link{applyStrategy.rebalancing}} to set the -#' maximum trade size by calling \code{\link{addPosLimit}}. -#' -#' To use it, you need to specify it as (part of) a rule of type 'rebalance'. -#' note that \code{\link{applyStrategy.rebalancing}} will expect a -#' 'rebalance_on' argument to be included in the \code{arguments=list(...)} -#' of the rule definition. -#' -#' -#' -#' @param trade.percent max percentage of equity to allow the strategy to trade in this symbol -#' @param longlevels numeric number of levels -#' @param shortlevels numeric number of short levels, default longlevels -#' @param digits if not NULL(the default), will call \code{\link{round}} with specified number of digits -#' @param refprice if not NULL(the default), will divide the calculated tra -#' @param portfolio text name of the portfolio to place orders in, typically set automatically -#' @param symbol identifier of the instrument to cancel orders for, typically set automatically -#' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on, typically set automatically -#' @param \dots any other passthrough parameters -#' @seealso \code{\link{osMaxPos}} , -#' \code{\link{applyStrategy.rebalancing}}, -#' \code{\link{addPosLimit}}, -#' \code{\link{add.rule}} -#' -#' @examples -#' # example rule definition -#' \dontrun{ -#' add.rule(strategy.name, 'rulePctEquity', -#' arguments=list(rebalance_on='months', -#' trade.percent=.02, -#' refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])), -#' digits=0 -#' ), -#' type='rebalance', -#' label='rebalance') -#' } -#' @export -rulePctEquity <- function (trade.percent=.02, - ..., - longlevels=1, - shortlevels=1, - digits=NULL, - refprice=NULL, - portfolio, - symbol, - timestamp) -{ - dummy <- updatePortf(Portfolio=portfolio, - Dates=paste('::',timestamp,sep='')) - trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) - total.equity <- initEq+trading.pl - tradeSize <- total.equity * trade.percent - if(!is.null(refprice)) tradeSize <- tradeSize/refprice - if(!is.null(digits)) tradeSize<-round(tradeSize,digits) - addPosLimit(portfolio = portfolio, - symbol = symbol, - timestamp = timestamp, - maxpos = tradeSize, - longlevels = longlevels, - minpos = -tradeSize, - shortlevels = shortlevels) -} - -ruleWeights <- function (weights=NULL, - ..., - longlevels=1, - shortlevels=1, - digits=NULL, - portfolio, - symbol, - account=NULL, - timestamp) -{ - #update portfolio - dummy <- updatePortf(Portfolio=portfolio, - Dates=paste('::',timestamp,sep='')) - - #get total account equity - if(!is.null(account)){ - dummy <- updateAcct(Account=account, - Dates=paste('::',timestamp,sep='')) - dummy <- updateEndEq(Account=account, - Dates=paste('::',timestamp,sep='')) - total.equity<-getEndEq(account) - } else { - trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) - total.equity <- initEq+trading.pl - } - - if(!is.null(digits)) tradeSize<-round(tradeSize,digits) - addPosLimit(portfolio = portfolio, - symbol = symbol, - timestamp = timestamp, - maxpos = tradeSize, - longlevels = longlevels, - minpos = -tradeSize, - shortlevels = shortlevels) -} - -#TODO weights rule that takes or calculates max position based on weights -#TODO active weights rule that moved from current positions to target positions -#TODO PortfolioAnalytics sizing -#TODO LSPM sizing - -############################################################################### -# R (http://r-project.org/) Quantitative Strategy Model Framework -# -# Copyright (c) 2009-2012 -# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich -# -# This library is distributed under the terms of the GNU Public License (GPL) -# for full details see the file COPYING -# -# $Id$ -# -############################################################################### +#' rule to base trade size on a percentage of available equity. +#' +#' This rule works with \code{\link{applyStrategy.rebalancing}} to set the +#' maximum trade size by calling \code{\link{addPosLimit}}. +#' +#' To use it, you need to specify it as (part of) a rule of type 'rebalance'. +#' note that \code{\link{applyStrategy.rebalancing}} will expect a +#' 'rebalance_on' argument to be included in the \code{arguments=list(...)} +#' of the rule definition. +#' +#' +#' +#' @param trade.percent max percentage of equity to allow the strategy to trade in this symbol +#' @param longlevels numeric number of levels +#' @param shortlevels numeric number of short levels, default longlevels +#' @param digits if not NULL(the default), will call \code{\link{round}} with specified number of digits +#' @param refprice if not NULL(the default), will divide the calculated tra +#' @param portfolio text name of the portfolio to place orders in, typically set automatically +#' @param symbol identifier of the instrument to cancel orders for, typically set automatically +#' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on, typically set automatically +#' @param \dots any other passthrough parameters +#' @seealso \code{\link{osMaxPos}} , +#' \code{\link{applyStrategy.rebalancing}}, +#' \code{\link{addPosLimit}}, +#' \code{\link{add.rule}} +#' +#' @examples +#' # example rule definition +#' \dontrun{ +#' add.rule(strategy.name, 'rulePctEquity', +#' arguments=list(rebalance_on='months', +#' trade.percent=.02, +#' refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])), +#' digits=0 +#' ), +#' type='rebalance', +#' label='rebalance') +#' } +#' @export +rulePctEquity <- function (trade.percent=.02, + ..., + longlevels=1, + shortlevels=1, + digits=NULL, + refprice=NULL, + portfolio, + symbol, + timestamp) +{ + dummy <- updatePortf(Portfolio=portfolio, + Dates=paste('::',timestamp,sep='')) + trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) + total.equity <- initEq+trading.pl + tradeSize <- total.equity * trade.percent + if(!is.null(refprice)) tradeSize <- tradeSize/refprice + if(!is.null(digits)) tradeSize<-round(tradeSize,digits) + addPosLimit(portfolio = portfolio, + symbol = symbol, + timestamp = timestamp, + maxpos = tradeSize, + longlevels = longlevels, + minpos = -tradeSize, + shortlevels = shortlevels) +} + +ruleWeights <- function (weights=NULL, + ..., + longlevels=1, + shortlevels=1, + digits=NULL, + portfolio, + symbol, + account=NULL, + timestamp) +{ + #update portfolio + dummy <- updatePortf(Portfolio=portfolio, + Dates=paste('::',timestamp,sep='')) + + #get total account equity + if(!is.null(account)){ + dummy <- updateAcct(name=account, + Dates=paste('::',timestamp,sep='')) + dummy <- updateEndEq(Account=account, + Dates=paste('::',timestamp,sep='')) + total.equity<-getEndEq(account) + } else { + trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) + total.equity <- initEq+trading.pl + } + + if(!is.null(digits)) tradeSize<-round(tradeSize,digits) + addPosLimit(portfolio = portfolio, + symbol = symbol, + timestamp = timestamp, + maxpos = tradeSize, + longlevels = longlevels, + minpos = -tradeSize, + shortlevels = shortlevels) +} + +#TODO weights rule that takes or calculates max position based on weights +#TODO active weights rule that moved from current positions to target positions +#TODO PortfolioAnalytics sizing +#TODO LSPM sizing + +############################################################################### +# R (http://r-project.org/) Quantitative Strategy Model Framework +# +# Copyright (c) 2009-2012 +# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich +# +# This library is distributed under the terms of the GNU Public License (GPL) +# for full details see the file COPYING +# +# $Id$ +# +############################################################################### Modified: pkg/quantstrat/R/strategy.R =================================================================== --- pkg/quantstrat/R/strategy.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/strategy.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -121,7 +121,7 @@ ret[[portfolio]]<-list() # this is slot [[i]] which we will use later pobj<-getPortfolio(portfolio) - symbols<-names(pobj$symbols) + symbols<- ls(pobj$symbols) sret<-list() for (symbol in symbols){ if(isTRUE(load.mktdata)) mktdata <- get(symbol) Modified: pkg/quantstrat/R/wrapup.R =================================================================== --- pkg/quantstrat/R/wrapup.R 2013-09-13 17:13:10 UTC (rev 1502) +++ pkg/quantstrat/R/wrapup.R 2013-09-13 21:37:20 UTC (rev 1503) @@ -153,7 +153,7 @@ if(showEq) cat('Ending Account Equity: ', getEndEq(Account=account,Date=Sys.time()), '\n') } if(isTRUE(chart)){ - for (symbol in names(getPortfolio(portfolio)$symbols) ){ + for (symbol in ls(getPortfolio(portfolio)$symbols) ){ dev.new() chart.Posn(Portfolio=portfolio, Symbol=symbol,...=...) } From noreply at r-forge.r-project.org Sat Sep 14 00:50:16 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 14 Sep 2013 00:50:16 +0200 (CEST) Subject: [Blotter-commits] r1504 - pkg/blotter/R Message-ID: <20130913225016.88C03185450@r-forge.r-project.org> Author: bodanker Date: 2013-09-14 00:50:16 +0200 (Sat, 14 Sep 2013) New Revision: 1504 Modified: pkg/blotter/R/updatePortf.R Log: - complete Brian's patch to get all index values from all symbols Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-09-13 21:37:20 UTC (rev 1503) +++ pkg/blotter/R/updatePortf.R 2013-09-13 22:50:16 UTC (rev 1504) @@ -32,7 +32,7 @@ # Calculate and store portfolio summary table Portfolio<-getPortfolio(pname) # refresh with an updated object #if(is.null(Dates)) Dates <- xts:::time.xts(Portfolio$symbols[[1]]$posPL) #not quite right, only using first symbol... - if(is.null(Dates)) Dates <- xts(,do.call(unlist,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) )))) + if(is.null(Dates)) Dates <- unique(do.call(c,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) ), use.names=FALSE, recursive=FALSE))) #Symbols = ls(Portfolio$symbols) Attributes = c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value', 'Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') @@ -94,7 +94,7 @@ # if(!is.timeBased(Dates)) Dates = xts:::time.xts(Portfolio$symbols[[1]][["posPL"]][Dates]) #xts(,do.call(unlist,c(lapply(symbols,index),use.names=FALSE))) - if(!is.timeBased(Dates)) Dates <- xts(,do.call(unlist,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) )))) + if(!is.timeBased(Dates)) Dates <- unique(do.call(c,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) ), use.names=FALSE, recursive=FALSE))) startDate = first(xts:::.parseISO8601(Dates))$first.time-.00001 # trim summary slot to not double count, related to bug 831 on R-Forge, and rbind new summary if( as.POSIXct(attr(Portfolio,'initDate'))>=startDate || length(Portfolio$summary)==0 ){ From noreply at r-forge.r-project.org Sat Sep 14 13:15:23 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 14 Sep 2013 13:15:23 +0200 (CEST) Subject: [Blotter-commits] r1505 - pkg/FinancialInstrument/R Message-ID: <20130914111523.BB941185D00@r-forge.r-project.org> Author: braverock Date: 2013-09-14 13:15:23 +0200 (Sat, 14 Sep 2013) New Revision: 1505 Modified: pkg/FinancialInstrument/R/build_symbols.R Log: - add an example and fix a typo Modified: pkg/FinancialInstrument/R/build_symbols.R =================================================================== --- pkg/FinancialInstrument/R/build_symbols.R 2013-09-13 22:50:16 UTC (rev 1504) +++ pkg/FinancialInstrument/R/build_symbols.R 2013-09-14 11:15:23 UTC (rev 1505) @@ -51,6 +51,9 @@ #' \code{active_months} is a numeric field indicating how many months including #' the month of the \code{start_date} the contract is available to trade. #' This number will be used as the upper limit for symbol generation. +#' +#' If \code{type} is also specified, it should be a specific instrument type, +#' e.g. 'future_series','option_series','guaranteed_spread' or 'calendar_spread' #' #' One of \code{data} or \code{file} must be populated for input data. #' @@ -62,6 +65,11 @@ #' @seealso #' \code{\link{load.instruments}} #' \code{\link{build_series_symbols}} +#' @examples +#' build_spread_symbols(data=data.frame(primary_id='CL', +#' month_sequence="F,G,H,J,K,M,N,Q,U,V,X,Z", +#' contracts_ahead="1,2,3", +#' type='calendar_spread') #' @export build_spread_symbols <- function(data=NULL,file=NULL,outputfile=NULL,start_date=Sys.Date()) { From noreply at r-forge.r-project.org Sat Sep 14 13:56:33 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 14 Sep 2013 13:56:33 +0200 (CEST) Subject: [Blotter-commits] r1506 - pkg/quantstrat/demo Message-ID: <20130914115633.72760184D0D@r-forge.r-project.org> Author: braverock Date: 2013-09-14 13:56:33 +0200 (Sat, 14 Sep 2013) New Revision: 1506 Modified: pkg/quantstrat/demo/faber.R Log: - fix return calc in demo Modified: pkg/quantstrat/demo/faber.R =================================================================== --- pkg/quantstrat/demo/faber.R 2013-09-14 11:15:23 UTC (rev 1505) +++ pkg/quantstrat/demo/faber.R 2013-09-14 11:56:33 UTC (rev 1506) @@ -153,6 +153,7 @@ getSymbols("SPY", src='yahoo', index.class=c("POSIXt","POSIXct"), from='1999-01-01') SPY<-to.monthly(SPY) SPY.ret<-Return.calculate(SPY$SPY.Close) + SPY.ret<-na.omit(SPY.ret) index(SPY.ret)<-index(ret1) dev.new() charts.PerformanceSummary(cbind(ret1$total,SPY.ret), geometric=FALSE, wealth.index=TRUE) From noreply at r-forge.r-project.org Mon Sep 16 19:24:52 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 16 Sep 2013 19:24:52 +0200 (CEST) Subject: [Blotter-commits] r1507 - in pkg/quantstrat: . R man Message-ID: <20130916172452.8635D183F49@r-forge.r-project.org> Author: opentrades Date: 2013-09-16 19:24:52 +0200 (Mon, 16 Sep 2013) New Revision: 1507 Modified: pkg/quantstrat/NAMESPACE pkg/quantstrat/R/orders.R pkg/quantstrat/R/ruleOrderProc.R pkg/quantstrat/R/ruleSignal.R pkg/quantstrat/man/add.distribution.Rd pkg/quantstrat/man/addOrder.Rd pkg/quantstrat/man/apply.paramset.Rd pkg/quantstrat/man/delete.paramset.Rd pkg/quantstrat/man/getOrders.Rd pkg/quantstrat/man/ruleSignal.Rd Log: - implemented time-in-force feature Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-09-14 11:56:33 UTC (rev 1506) +++ pkg/quantstrat/NAMESPACE 2013-09-16 17:24:52 UTC (rev 1507) @@ -1,5 +1,5 @@ +export(add.distribution.constraint) export(add.distribution) -export(add.distribution.constraint) export(add.indicator) export(add.init) export(add.rule) Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-09-14 11:56:33 UTC (rev 1506) +++ pkg/quantstrat/R/orders.R 2013-09-16 17:24:52 UTC (rev 1507) @@ -82,8 +82,8 @@ orders<-list() orders[[portfolio]]<-list() } - ordertemplate<-xts(as.matrix(t(c(0,NA,"init","long",0,"closed",as.character(as.POSIXct(initDate)),'','',0,''))),order.by=as.POSIXct(initDate), ...=...) - colnames(ordertemplate) <- c("Order.Qty","Order.Price","Order.Type","Order.Side","Order.Threshold","Order.Status","Order.StatusTime","Prefer", "Order.Set","Txn.Fees","Rule") + ordertemplate<-xts(as.matrix(t(c(0,NA,"init","long",0,"closed",as.character(as.POSIXct(initDate)),'','',0,'',''))),order.by=as.POSIXct(initDate), ...=...) + colnames(ordertemplate) <- c("Order.Qty","Order.Price","Order.Type","Order.Side","Order.Threshold","Order.Status","Order.StatusTime","Prefer", "Order.Set","Txn.Fees","Rule","Time.In.Force") if(is.null(symbols)) { pfolio<-getPortfolio(portfolio) @@ -119,13 +119,14 @@ #' @seealso addOrder #' @concept order book #' @export -getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, orderset=NULL, which.i=FALSE) +getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, orderset=NULL, which.i=FALSE, time.in.force=NULL) { #if(is.null(timespan)) stop("timespan must be an xts style timestring") # get order book orderbook <- getOrderBook(portfolio) if(!any(names(orderbook[[portfolio]]) == symbol)) stop(paste("symbol",symbol,"does not exist in portfolio",portfolio,"having symbols",names(orderbook[[portfolio]]))) - ordersubset<-orderbook[[portfolio]][[symbol]] + + ordersubset <- orderbook[[portfolio]][[symbol]] if(is.null(ordersubset)) return(NULL) @@ -142,6 +143,7 @@ (if(!is.null(ordertype)) ordersubset[,"Order.Type"]==ordertype else TRUE) & (if(!is.null(side)) ordersubset[,"Order.Side"]==side else TRUE) & (if(!is.null(orderset)) ordersubset[,"Order.Set"]==orderset else TRUE) & + (if(!is.null(time.in.force)) strptime(ordersubset[,'Time.In.Force'], format='%Y-%m-%d %H:%M:%S') Author: peter_carl Date: 2013-09-19 23:22:29 +0200 (Thu, 19 Sep 2013) New Revision: 1508 Modified: pkg/FinancialInstrument/inst/parser/parse.SP500TR.R Log: - S&P finally made this file easily available again Modified: pkg/FinancialInstrument/inst/parser/parse.SP500TR.R =================================================================== --- pkg/FinancialInstrument/inst/parser/parse.SP500TR.R 2013-09-16 17:24:52 UTC (rev 1507) +++ pkg/FinancialInstrument/inst/parser/parse.SP500TR.R 2013-09-19 21:22:29 UTC (rev 1508) @@ -5,15 +5,14 @@ # Peter Carl # Load needed packages: -require(zoo) +require(xts) require(gdata) # @TODO: Set the working directory # # Download the first sheet in the xls workbook directly from the web site: -# x = read.xls("http://www2.standardandpoors.com/spf/xls/index/MONTHLY.xls") -x = read.xls("http://www.standardandpoors.com/servlet/BlobServer?blobheadername3=MDT-Type&blobcol=urldata&blobtable=MungoBlobs&blobheadervalue2=inline%3B+filename%3DMONTHLY.xls&blobheadername2=Content-Disposition&blobheadervalue1=application%2Fexcel&blobkey=id&blobheadername1=content-type&blobwhere=1243862365806&blobheadervalue3=UTF-8") +x = read.xls("http://www.spindices.com/documents/additional-material/monthly.xlsx?force_download=true") # That gives us something like the following: # > head(x) From noreply at r-forge.r-project.org Sun Sep 22 21:05:30 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 22 Sep 2013 21:05:30 +0200 (CEST) Subject: [Blotter-commits] r1509 - in pkg/quantstrat: . R man Message-ID: <20130922190531.1A8AD185F84@r-forge.r-project.org> Author: braverock Date: 2013-09-22 21:05:29 +0200 (Sun, 22 Sep 2013) New Revision: 1509 Added: pkg/quantstrat/man/get.strategy.Rd Removed: pkg/quantstrat/man/getStrategy.Rd Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/NAMESPACE pkg/quantstrat/R/orders.R pkg/quantstrat/R/strategy.R pkg/quantstrat/man/getOrderBook.Rd Log: - create aliases for come camelCase fns to create more standardization - clean up some formatting and doc errors Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/DESCRIPTION 2013-09-22 19:05:29 UTC (rev 1509) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.7.8 +Version: 0.7.9 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: @@ -15,31 +15,8 @@ Maintainer: Brian G. Peterson Description: Specify, build, and back-test quantitative financial trading and portfolio strategies -Contributors: Yu Chen, Joe Dunn, Dirk Eddelbuettel, Jeffrey A. Ryan, Garrett - See, Jan Humme +Contributors: Yu Chen, Joe Dunn, Dirk Eddelbuettel, + Jeffrey A. Ryan, Garrett See LazyLoad: yes License: GPL-3 ByteCompile: TRUE -Collate: - 'applyStrategy.rebalancing.R' - 'chart.forward.training.R' - 'indicators.R' - 'initialize.R' - 'match.names.R' - 'orders.R' - 'osFUNs.R' - 'parameters.R' - 'paramsets.R' - 'rebalance.rules.R' - 'ruleOrderProc.R' - 'ruleRevoke.R' - 'rules.R' - 'ruleSignal.R' - 'signals.R' - 'strategy.R' - 'tradeGraphs.R' - 'utils.R' - 'walk.forward.R' - 'wrapup.R' - 'tradeOrderStats.R' - 'chart.forward.R' Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/NAMESPACE 2013-09-22 19:05:29 UTC (rev 1509) @@ -1,5 +1,5 @@ +export(add.distribution) export(add.distribution.constraint) -export(add.distribution) export(add.indicator) export(add.init) export(add.rule) @@ -11,17 +11,17 @@ export(applyParameter) export(applyRules) export(applySignals) +export(applyStrategy) export(applyStrategy.rebalancing) -export(applyStrategy) +export(chart.forward) export(chart.forward.training) -export(chart.forward) export(delete.paramset) export(enable.rule) -export(getOrderBook) +export(get.orderbook) +export(get.strategy) export(getOrders) export(getParameterTable) export(getPosLimit) -export(getStrategy) export(initOrders) export(initStrategy) export(is.strategy) Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/R/orders.R 2013-09-22 19:05:29 UTC (rev 1509) @@ -20,9 +20,13 @@ #' \item{Order.Set}{} #' \item{Txn.Fees}{} #' \item{Rule}{} -#' } +#' } +#' @aliases +#' get.orderbook +#' getOrderbook +#' @rdname getOrderBook #' @export -getOrderBook <- function(portfolio, envir=.strategy) #should symbol subsets be supported too? probably not. +get.orderbook <- getOrderBook <- function(portfolio, envir=.strategy) #should symbol subsets be supported too? probably not. { if(!grepl("order_book",portfolio)) orders<-try(get(paste("order_book",portfolio,sep='.'),envir=envir),silent=TRUE) else orders<-try(get(portfolio,envir=envir),silent=TRUE) @@ -39,7 +43,6 @@ #' @seealso getOrderBook #' @concept order book #' @export - put.orderbook <- function(portfolio.st, orderbook, envir=.strategy) { strategy.orderbook.st <- paste('order_book', portfolio.st, sep='.') @@ -47,18 +50,6 @@ assign(strategy.orderbook.st, orderbook, envir=envir) } -############################################################################### -# Blotter: Tools for transaction-oriented trading systems development -# for R (see http://r-project.org/) -# Copyright (c) 2008-2011 Peter Carl and Brian G. Peterson -# -# This library is distributed under the terms of the GNU Public License (GPL) -# for full details see the file COPYING -# -# $Id$ -# -############################################################################### - #' initialize order container #' #' This function sets up the order container by portfolio. Modified: pkg/quantstrat/R/strategy.R =================================================================== --- pkg/quantstrat/R/strategy.R 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/R/strategy.R 2013-09-22 19:05:29 UTC (rev 1509) @@ -116,51 +116,53 @@ for (portfolio in portfolios) { - # TODO call to initStrategy will go here! - if(isTRUE(initStrat)) initStrategy(strategy=strategy, portfolio, symbols, ...=...) + # call initStrategy + if(isTRUE(initStrat)) initStrategy(strategy=strategy, portfolio, symbols, ...=...) ret[[portfolio]]<-list() # this is slot [[i]] which we will use later - pobj<-getPortfolio(portfolio) - symbols<- ls(pobj$symbols) - sret<-list() - for (symbol in symbols){ - if(isTRUE(load.mktdata)) mktdata <- get(symbol) + pobj<-getPortfolio(portfolio) + symbols<- ls(pobj$symbols) + sret<-list() + for (symbol in symbols){ + if(isTRUE(load.mktdata)) mktdata <- get(symbol) + + # loop over indicators + sret$indicators <- applyIndicators(strategy=strategy , mktdata=mktdata , parameters=parameters, ... ) + + if(inherits(sret$indicators,"xts") & nrow(mktdata)==nrow(sret$indicators)){ + mktdata<-sret$indicators + } + + # loop over signal generators + sret$signals <- applySignals(strategy=strategy, mktdata=mktdata, sret$indicators, parameters=parameters, ... ) - #loop over indicators - sret$indicators <- applyIndicators(strategy=strategy , mktdata=mktdata , parameters=parameters, ... ) - #this should be taken care of by the mktdata<<-mktdata line in the apply* fn - if(inherits(sret$indicators,"xts") & nrow(mktdata)==nrow(sret$indicators)){ - mktdata<-sret$indicators - } - - #loop over signal generators - sret$signals <- applySignals(strategy=strategy, mktdata=mktdata, sret$indicators, parameters=parameters, ... ) - #this should be taken care of by the mktdata<<-mktdata line in the apply* fn - if(inherits(sret$signals,"xts") & nrow(mktdata)==nrow(sret$signals)){ - mktdata<-sret$signals - } - - #loop over rules - sret$rules<-list() - - ## only fire nonpath/pathdep when true - ## TODO make this more elegant - pd <- FALSE - for(i in 1:length(strategy$rules)){ if(length(strategy$rules[[i]])!=0){z <- strategy$rules[[i]]; if(z[[1]]$path.dep==TRUE){pd <- TRUE}}} - - sret$rules$nonpath<-applyRules(portfolio=portfolio, symbol=symbol, strategy=strategy, mktdata=mktdata, Dates=NULL, indicators=sret$indicators, signals=sret$signals, parameters=parameters, ..., path.dep=FALSE) - - ## Check for open orders - rem.orders <- suppressWarnings(getOrders(portfolio=portfolio, symbol=symbol, status="open")) #, timespan=timespan, ordertype=ordertype,which.i=TRUE) - if(NROW(rem.orders)>0){pd <- TRUE} - if(pd==TRUE){sret$rules$pathdep<-applyRules(portfolio=portfolio, symbol=symbol, strategy=strategy, mktdata=mktdata, Dates=NULL, indicators=sret$indicators, signals=sret$signals, parameters=parameters, ..., path.dep=TRUE)} - - ret[[portfolio]][[symbol]]<-sret - } + if(inherits(sret$signals,"xts") & nrow(mktdata)==nrow(sret$signals)){ + mktdata<-sret$signals + } - # TODO call to updateStrategy will go here! - if(isTRUE(updateStrat)) updateStrategy(strategy, portfolio, Symbols=symbols, ...=...) + #loop over rules + sret$rules<-list() + # only fire nonpath/pathdep when true + # TODO make this more elegant + pd <- FALSE + for(i in 1:length(strategy$rules)){ + if(length(strategy$rules[[i]])!=0){z <- strategy$rules[[i]]; if(z[[1]]$path.dep==TRUE){pd <- TRUE}} + } + + sret$rules$nonpath<-applyRules(portfolio=portfolio, symbol=symbol, strategy=strategy, mktdata=mktdata, Dates=NULL, indicators=sret$indicators, signals=sret$signals, parameters=parameters, ..., path.dep=FALSE) + + # Check for open orders + rem.orders <- suppressWarnings(getOrders(portfolio=portfolio, symbol=symbol, status="open")) #, timespan=timespan, ordertype=ordertype,which.i=TRUE) + if(NROW(rem.orders)>0){pd <- TRUE} + if(pd==TRUE){sret$rules$pathdep<-applyRules(portfolio=portfolio, symbol=symbol, strategy=strategy, mktdata=mktdata, Dates=NULL, indicators=sret$indicators, signals=sret$signals, parameters=parameters, ..., path.dep=TRUE)} + + ret[[portfolio]][[symbol]]<-sret + } + + # call updateStrategy + if(isTRUE(updateStrat)) updateStrategy(strategy, portfolio, Symbols=symbols, ...=...) + } if(verbose) return(ret) @@ -176,8 +178,12 @@ #' retrieve strategy from the container environment #' @param x string name of object to be retrieved #' @param envir the environment to retrieve the strategy object from, defaults to .strategy +#' @rdname get.strategy +#' @aliases +#' get.strategy +#' getStrategy #' @export -getStrategy <- function(x, envir=.strategy){ +get.strategy <- getStrategy <- function(x, envir=.strategy){ tmp_strat<-get(as.character(x),pos=envir, inherits=TRUE) if( inherits(tmp_strat,"try-error") | !is.strategy(tmp_strat) ) { warning(paste("Strategy",x," not found, please create it first.")) Copied: pkg/quantstrat/man/get.strategy.Rd (from rev 1499, pkg/quantstrat/man/getStrategy.Rd) =================================================================== --- pkg/quantstrat/man/get.strategy.Rd (rev 0) +++ pkg/quantstrat/man/get.strategy.Rd 2013-09-22 19:05:29 UTC (rev 1509) @@ -0,0 +1,17 @@ +\name{get.strategy} +\alias{get.strategy} +\alias{getStrategy} +\title{retrieve strategy from the container environment} +\usage{ + get.strategy(x, envir = .strategy) +} +\arguments{ + \item{x}{string name of object to be retrieved} + + \item{envir}{the environment to retrieve the strategy + object from, defaults to .strategy} +} +\description{ + retrieve strategy from the container environment +} + Modified: pkg/quantstrat/man/getOrderBook.Rd =================================================================== --- pkg/quantstrat/man/getOrderBook.Rd 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/man/getOrderBook.Rd 2013-09-22 19:05:29 UTC (rev 1509) @@ -1,8 +1,9 @@ -\name{getOrderBook} -\alias{getOrderBook} +\name{get.orderbook} +\alias{get.orderbook} +\alias{getOrderbook} \title{get the order book object} \usage{ - getOrderBook(portfolio, envir = .strategy) + get.orderbook(portfolio, envir = .strategy) } \arguments{ \item{portfolio}{text name of the portfolio the order Deleted: pkg/quantstrat/man/getStrategy.Rd =================================================================== --- pkg/quantstrat/man/getStrategy.Rd 2013-09-19 21:22:29 UTC (rev 1508) +++ pkg/quantstrat/man/getStrategy.Rd 2013-09-22 19:05:29 UTC (rev 1509) @@ -1,16 +0,0 @@ -\name{getStrategy} -\alias{getStrategy} -\title{retrieve strategy from the container environment} -\usage{ - getStrategy(x, envir = .strategy) -} -\arguments{ - \item{x}{string name of object to be retrieved} - - \item{envir}{the environment to retrieve the strategy - object from, defaults to .strategy} -} -\description{ - retrieve strategy from the container environment -} - From noreply at r-forge.r-project.org Thu Sep 26 18:18:11 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 26 Sep 2013 18:18:11 +0200 (CEST) Subject: [Blotter-commits] r1510 - pkg/quantstrat/R Message-ID: <20130926161811.E1DA2185616@r-forge.r-project.org> Author: opentrades Date: 2013-09-26 18:18:11 +0200 (Thu, 26 Sep 2013) New Revision: 1510 Modified: pkg/quantstrat/R/ruleOrderProc.R Log: - TIF temporarily disabled until I have time to fix problem with not running demos - opentrades Modified: pkg/quantstrat/R/ruleOrderProc.R =================================================================== --- pkg/quantstrat/R/ruleOrderProc.R 2013-09-22 19:05:29 UTC (rev 1509) +++ pkg/quantstrat/R/ruleOrderProc.R 2013-09-26 16:18:11 UTC (rev 1510) @@ -57,16 +57,16 @@ ordersubset <- orderbook[[portfolio]][[symbol]] ### first check time-in-force for open orders, and flag as 'expired' where appropriate - ExpiredOrders.i <- getOrders(portfolio=portfolio, symbol=symbol, status="open", time.in.force=timestamp, which.i=TRUE) - if(!is.null(ExpiredOrders.i)) - { - ordersubset[ExpiredOrders.i, "Order.Status"] = 'expired' - ordersubset[ExpiredOrders.i, "Order.StatusTime"]<-ordersubset[ExpiredOrders.i, "Time.In.Force"] +# ExpiredOrders.i <- getOrders(portfolio=portfolio, symbol=symbol, status="open", time.in.force=timestamp, which.i=TRUE) +# if(!is.null(ExpiredOrders.i)) +# { +# ordersubset[ExpiredOrders.i, "Order.Status"] = 'expired' +# ordersubset[ExpiredOrders.i, "Order.StatusTime"]<-ordersubset[ExpiredOrders.i, "Time.In.Force"] +# +# orderbook[[portfolio]][[symbol]] <- ordersubset +# assign(paste("order_book",portfolio,sep='.'),orderbook,envir=.strategy) +# } - orderbook[[portfolio]][[symbol]] <- ordersubset - assign(paste("order_book",portfolio,sep='.'),orderbook,envir=.strategy) - } - ### now retrieve open orders ### TODO calculate timespan here? OpenOrders.i<-getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timespan, ordertype=ordertype, which.i=TRUE) From noreply at r-forge.r-project.org Sun Sep 29 22:58:46 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 29 Sep 2013 22:58:46 +0200 (CEST) Subject: [Blotter-commits] r1511 - in pkg/quantstrat: . R man Message-ID: <20130929205846.DCC2518612F@r-forge.r-project.org> Author: braverock Date: 2013-09-29 22:58:46 +0200 (Sun, 29 Sep 2013) New Revision: 1511 Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/NAMESPACE pkg/quantstrat/R/orders.R pkg/quantstrat/R/ruleOrderProc.R pkg/quantstrat/man/getOrders.Rd Log: - fix time in force - minor doc updates - fix indents in ruleOrderProc.R Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2013-09-26 16:18:11 UTC (rev 1510) +++ pkg/quantstrat/DESCRIPTION 2013-09-29 20:58:46 UTC (rev 1511) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.7.9 +Version: 0.7.10 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-09-26 16:18:11 UTC (rev 1510) +++ pkg/quantstrat/NAMESPACE 2013-09-29 20:58:46 UTC (rev 1511) @@ -13,12 +13,14 @@ export(applySignals) export(applyStrategy) export(applyStrategy.rebalancing) +export(applyStrategy.rebalancing.training) export(chart.forward) export(chart.forward.training) export(delete.paramset) export(enable.rule) export(get.orderbook) export(get.strategy) +export(getOrderBook) export(getOrders) export(getParameterTable) export(getPosLimit) Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-09-26 16:18:11 UTC (rev 1510) +++ pkg/quantstrat/R/orders.R 2013-09-29 20:58:46 UTC (rev 1511) @@ -25,7 +25,8 @@ #' get.orderbook #' getOrderbook #' @rdname getOrderBook -#' @export +#' @export get.orderbook +#' @export getOrderBook get.orderbook <- getOrderBook <- function(portfolio, envir=.strategy) #should symbol subsets be supported too? probably not. { if(!grepl("order_book",portfolio)) orders<-try(get(paste("order_book",portfolio,sep='.'),envir=envir),silent=TRUE) @@ -110,7 +111,7 @@ #' @seealso addOrder #' @concept order book #' @export -getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, orderset=NULL, which.i=FALSE, time.in.force=NULL) +getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, orderset=NULL, which.i=FALSE) { #if(is.null(timespan)) stop("timespan must be an xts style timestring") # get order book @@ -134,7 +135,6 @@ (if(!is.null(ordertype)) ordersubset[,"Order.Type"]==ordertype else TRUE) & (if(!is.null(side)) ordersubset[,"Order.Side"]==side else TRUE) & (if(!is.null(orderset)) ordersubset[,"Order.Set"]==orderset else TRUE) & - (if(!is.null(time.in.force)) strptime(ordersubset[,'Time.In.Force'], format='%Y-%m-%d %H:%M:%S')=1)){ + return(NULL) + } else { - ### first check time-in-force for open orders, and flag as 'expired' where appropriate -# ExpiredOrders.i <- getOrders(portfolio=portfolio, symbol=symbol, status="open", time.in.force=timestamp, which.i=TRUE) -# if(!is.null(ExpiredOrders.i)) -# { -# ordersubset[ExpiredOrders.i, "Order.Status"] = 'expired' -# ordersubset[ExpiredOrders.i, "Order.StatusTime"]<-ordersubset[ExpiredOrders.i, "Time.In.Force"] -# -# orderbook[[portfolio]][[symbol]] <- ordersubset -# assign(paste("order_book",portfolio,sep='.'),orderbook,envir=.strategy) -# } - - ### now retrieve open orders - ### TODO calculate timespan here? - OpenOrders.i<-getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timespan, ordertype=ordertype, which.i=TRUE) - - if(hasArg(prefer)) prefer=match.call(expand.dots=TRUE)$prefer - else prefer = NULL - - # check for open orders - if (!(length(OpenOrders.i)>=1)){ - return(NULL) - } else { - - mktdataTimestamp <- mktdata[timestamp] - # only keep the last observation per time stamp - if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp) - isOHLCmktdata <- is.OHLC(mktdata) - isBBOmktdata <- is.BBO(mktdata) - for (ii in OpenOrders.i ) + mktdataTimestamp <- mktdata[timestamp] + # only keep the last observation per time stamp + if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp) + isOHLCmktdata <- is.OHLC(mktdata) + isBBOmktdata <- is.BBO(mktdata) + + for (ii in OpenOrders.i ) + { + if(ordersubset[ii, "Order.Status"] != "open") # need to check this bc side effects may have changed order.status in this loop + next() + + txnprice=NULL + + txnfees=ordersubset[ii,"Txn.Fees"] + + orderPrefer=ordersubset[ii, "Prefer"] + if(!orderPrefer=="") prefer=orderPrefer + + orderPrice <- as.numeric(ordersubset[ii,"Order.Price"]) + + orderQty <- ordersubset[ii,"Order.Qty"] + if(orderQty %in% c('all','trigger')) + { + # this has to be an exit or risk order, so: + orderQty=-1*getPosQty(Portfolio=portfolio,Symbol=symbol,Date=timestamp) + orderside<-ordersubset[ii, "Order.Side"] + if(((orderQty>0 && orderside=='long') || (orderQty<0 && orderside=='short'))) { - if(ordersubset[ii, "Order.Status"] != "open") # need to check this bc sideeffects may have changed order.status in this loop - next() - - txnprice=NULL - - txnfees=ordersubset[ii,"Txn.Fees"] - - orderPrefer=ordersubset[ii, "Prefer"] - if(!orderPrefer=="") prefer=orderPrefer - - orderPrice <- as.numeric(ordersubset[ii,"Order.Price"]) - - orderQty <- ordersubset[ii,"Order.Qty"] - if(orderQty %in% c('all','trigger')) - { - # this has to be an exit or risk order, so: - orderQty=-1*getPosQty(Portfolio=portfolio,Symbol=symbol,Date=timestamp) - orderside<-ordersubset[ii, "Order.Side"] - if(((orderQty>0 && orderside=='long') || (orderQty<0 && orderside=='short'))) - { - # this condition may occur if (for example) a signal triggers an 'increase LONG pos' and 'close all SHORT pos' simultaneously - # hence this is legal condition, and we must 0 the orderQty to reject the order - - orderQty = 0 - } - } - orderQty<-as.numeric(orderQty) - - orderThreshold <- as.numeric(ordersubset[ii,"Order.Threshold"]) - # mktdataTimestamp <- mktdata[timestamp] - #FIXME Should we only keep the last observation per time stamp? - #if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp) - - orderType <- ordersubset[ii,"Order.Type"] - - if(hasArg(allowMagicalThinking)) allowMagicalThinking=match.call(expand.dots=TRUE)$allowMagicalThinking - else allowMagicalThinking = FALSE - - freq = periodicity(mktdata) - #switch on frequency - switch(orderType, - market = { - switch(freq$scale, - yearly = , - quarterly = , - monthly = { - txntime=as.character(index(ordersubset[ii,])) # transacts on this bar, e.g. in the intraday cross, or leading into the end of month, quarter, etc. - # txntime=as.character(timestamp) # use this if you wanted to transact on the close of the next bar - # txnprice=as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) - txnprice = orderPrice - }, - daily = { - if(isTRUE(allowMagicalThinking)){ - txntime=as.character(index(ordersubset[ii,])) # transacts on this bar, e.g. in the intraday cross, or leading into the end of month, quarter, etc. - #txnprice=as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) - txnprice = orderPrice - } else { - txntime = timestamp - txnprice = as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) #filled at now-prevailing 'price' - } - }, #end daily - { - txntime = timestamp - if (isBBOmktdata) { - #An ordertype of market will *almost* trump pricemethod here. orderPrice was determined using pricemethod. - #but, for buy orders you'll be filled at either orderPrice or the current mkt ask -- whichever is worse. - #and, for sell orders you'll be filled at either orderPrice or the current mkt bid -- whichever is worse. - if(orderQty > 0){ # positive quantity 'buy' - #fill at max(orderPrice,newMktAsk price) - txnprice = max(orderPrice, as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])) - } else { # negative quantity 'sell' - txnprice = min(orderPrice, as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])) #presumes unique timestamp - } - #e.g. if pricemethod was opside, it sent a buy order at mktAsk. fill at greater of that ask, and current ask - } else txnprice = as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) #filled at 'price' - }) # end switch on frequency - }, - limit= , - stoplimit =, - iceberg = { - if (!isBBOmktdata) { - if( orderType == 'iceberg'){ - stop("iceberg orders only supported for BBO data") - } - # check to see if price moved through the limit - if((orderQty > 0 && orderType != 'stoplimit') || (orderQty < 0 && (orderType=='stoplimit'))) { - # buy limit, or sell stoplimit - if( (has.Lo(mktdata) && orderPrice > as.numeric(Lo(mktdataTimestamp))) || - (!has.Lo(mktdata) && orderPrice > as.numeric(getPrice(mktdataTimestamp, prefer=prefer)))) - { - txnprice = min(orderPrice, Hi(mktdataTimestamp)) - txntime = timestamp - } else next() # price did not move through my order, should go to next order - } else if((orderQty < 0 && orderType != 'stoplimit') || (orderQty > 0 && (orderType=='stoplimit'))) { - # sell limit or buy stoplimit - if ( (has.Hi(mktdata) && orderPrice < as.numeric(Hi(mktdataTimestamp))) || - (!has.Hi(mktdata) && orderPrice < as.numeric(getPrice(mktdataTimestamp,prefer=prefer))) ) - { - txnprice = max(orderPrice, Lo(mktdataTimestamp)) - txntime = timestamp - } else next() # price did not move through my order, should go to next order - } else { - warning('ignoring order with quantity of zero') - next() - } - } else if(isBBOmktdata){ - # check side/qty - if(orderQty > 0){ # positive quantity 'buy' - if (orderType == 'stoplimit') { - if(orderPrice <= as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])){ - # mktprice moved above our stop buy price - txnprice = orderPrice #assume we got filled at our stop price - #txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1]) #presumes unique timestamps - txntime = timestamp - } else next() - } else { - if(orderPrice >= as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])){ - # price we're willing to pay is higher than the offer price, so execute at the prevailing price - #txnprice = orderPrice - txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1]) #presumes unique timestamps - txntime = timestamp - } else next() - } - } else { # negative quantity 'sell' - if (orderType == 'stoplimit') { - if(orderPrice >= as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])){ - # mktprice moved below our stop sell price - txnprice = orderPrice #assumption is that we're filled at our stop price - #txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1]) #presumes unique timestamp - txntime = timestamp - } else next() - } else { - if(orderPrice <= as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])){ - # we're willing to sell at a better price than the bid, so execute at the prevailing price - # txnprice = orderPrice - txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1]) #presumes unique timestamp - txntime = timestamp - } else next() - } - } - - - if( orderType == 'iceberg'){ - #we've transacted, so the old order was closed, put in a new one - neworder<-addOrder(portfolio=portfolio, + # this condition may occur if (for example) a signal triggers an 'increase LONG pos' and 'close all SHORT pos' simultaneously + # hence this is legal condition, and we must 0 the orderQty to reject the order + + orderQty = 0 + } + } + orderQty<-as.numeric(orderQty) + + orderThreshold <- as.numeric(ordersubset[ii,"Order.Threshold"]) + # mktdataTimestamp <- mktdata[timestamp] + #FIXME Should we only keep the last observation per time stamp? + #if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp) + + orderType <- ordersubset[ii,"Order.Type"] + + if(hasArg(allowMagicalThinking)) allowMagicalThinking=match.call(expand.dots=TRUE)$allowMagicalThinking + else allowMagicalThinking = FALSE + + freq = periodicity(mktdata) + #switch on frequency + switch(orderType, + market = { + switch(freq$scale, + yearly = , + quarterly = , + monthly = { + txntime=as.character(index(ordersubset[ii,])) # transacts on this bar, e.g. in the intraday cross, or leading into the end of month, quarter, etc. + # txntime=as.character(timestamp) # use this if you wanted to transact on the close of the next bar + # txnprice=as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) + txnprice = orderPrice + }, + daily = { + if(isTRUE(allowMagicalThinking)){ + txntime=as.character(index(ordersubset[ii,])) # transacts on this bar, e.g. in the intraday cross, or leading into the end of month, quarter, etc. + #txnprice=as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) + txnprice = orderPrice + } else { + txntime = timestamp + txnprice = as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) #filled at now-prevailing 'price' + } + }, #end daily + { + txntime = timestamp + if (isBBOmktdata) { + #An ordertype of market will *almost* trump pricemethod here. orderPrice was determined using pricemethod. + #but, for buy orders you'll be filled at either orderPrice or the current mkt ask -- whichever is worse. + #and, for sell orders you'll be filled at either orderPrice or the current mkt bid -- whichever is worse. + if(orderQty > 0){ # positive quantity 'buy' + #fill at max(orderPrice,newMktAsk price) + txnprice = max(orderPrice, as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])) + } else { # negative quantity 'sell' + txnprice = min(orderPrice, as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])) #presumes unique timestamp + } + #e.g. if pricemethod was opside, it sent a buy order at mktAsk. fill at greater of that ask, and current ask + } else txnprice = as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]) #filled at 'price' + } + ) # end switch on frequency + }, + limit= , + stoplimit =, + iceberg = { + if (!isBBOmktdata) { + if( orderType == 'iceberg'){ + stop("iceberg orders only supported for BBO data") + } + # check to see if price moved through the limit + if((orderQty > 0 && orderType != 'stoplimit') || (orderQty < 0 && (orderType=='stoplimit'))) { + # buy limit, or sell stoplimit + if( (has.Lo(mktdata) && orderPrice > as.numeric(Lo(mktdataTimestamp))) || + (!has.Lo(mktdata) && orderPrice > as.numeric(getPrice(mktdataTimestamp, prefer=prefer)))) + { + txnprice = min(orderPrice, Hi(mktdataTimestamp)) + txntime = timestamp + } else next() # price did not move through my order, should go to next order + } else if((orderQty < 0 && orderType != 'stoplimit') || (orderQty > 0 && (orderType=='stoplimit'))) { + # sell limit or buy stoplimit + if ( (has.Hi(mktdata) && orderPrice < as.numeric(Hi(mktdataTimestamp))) || + (!has.Hi(mktdata) && orderPrice < as.numeric(getPrice(mktdataTimestamp,prefer=prefer))) ) + { + txnprice = max(orderPrice, Lo(mktdataTimestamp)) + txntime = timestamp + } else next() # price did not move through my order, should go to next order + } else { + warning('ignoring order with quantity of zero') + next() + } + } else if(isBBOmktdata){ + # check side/qty + if(orderQty > 0){ # positive quantity 'buy' + if (orderType == 'stoplimit') { + if(orderPrice <= as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])){ + # mktprice moved above our stop buy price + txnprice = orderPrice #assume we got filled at our stop price + #txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1]) #presumes unique timestamps + txntime = timestamp + } else next() + } else { + if(orderPrice >= as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1])){ + # price we're willing to pay is higher than the offer price, so execute at the prevailing price + #txnprice = orderPrice + txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='ask')[,1]) #presumes unique timestamps + txntime = timestamp + } else next() + } + } else { # negative quantity 'sell' + if (orderType == 'stoplimit') { + if(orderPrice >= as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])){ + # mktprice moved below our stop sell price + txnprice = orderPrice #assumption is that we're filled at our stop price + #txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1]) #presumes unique timestamp + txntime = timestamp + } else next() + } else { + if(orderPrice <= as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1])){ + # we're willing to sell at a better price than the bid, so execute at the prevailing price + # txnprice = orderPrice + txnprice = as.numeric(getPrice(mktdataTimestamp,prefer='bid')[,1]) #presumes unique timestamp + txntime = timestamp + } else next() + } + } + + + if( orderType == 'iceberg'){ + #we've transacted, so the old order was closed, put in a new one + neworder<-addOrder(portfolio=portfolio, + symbol=symbol, + timestamp=timestamp, + qty=orderQty, + price=as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1]), + ordertype=orderType, + side=ordersubset[ii,"Order.Side"], + threshold=orderThreshold, + status="open", + replace=FALSE, return=TRUE, + ,...=..., TxnFees=txnfees) + + ordersubset<-rbind(ordersubset, neworder) + + ordersubset[ii,"Order.Status"]<-'replaced' + ordersubset[ii,"Order.StatusTime"]<-format(timestamp, "%Y-%m-%d %H:%M:%S") + next() + } + } + }, + stoptrailing = { + if(isBBOmktdata) + { + + order.side <- ordersubset[ii, "Order.Side"] + mvstop <- FALSE + absOrderThreshold <- abs(orderThreshold) + # +++++++++ stop order price - buy + # ~~~~~~~~~ market price + # --------- stop order price - sell + if(orderQty > 0) { # positive quantity 'buy' + prefer <- 'ask' + mktPrice <- as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1]) + # check to see if price moved through the limit + if(mktPrice >= orderPrice) { # buy when price >= stop + txnprice <- mktPrice + txntime <- timestamp + } + # move stop if price < stop - thresh + else { + mvstop <- orderPrice - absOrderThreshold > mktPrice + new.order.price <- min(orderPrice, mktPrice + absOrderThreshold) + #new.order.price <- mktPrice + absOrderThreshold + } + } else { # negative quantity 'sell' + prefer <- 'bid' + mktPrice <- as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1]) + # check to see if price moved through the limit + if(mktPrice <= orderPrice) { # sell when price <= stop + txnprice <- mktPrice + txntime <- timestamp + } + # move stop if price > stop + thresh + else { + mvstop <- orderPrice + absOrderThreshold < mktPrice + new.order.price <- max(orderPrice, mktPrice - absOrderThreshold) + #new.order.price <- mktPrice - absOrderThreshold + } + } + if( isTRUE(mvstop) ){ + # if ordersubset[ii, "Order.Qty"] was character, we must recover it + new.order.qty <- ordersubset[ii, "Order.Qty"] + if(!is.na(suppressWarnings(as.numeric(new.order.qty)))) + new.order.qty <- as.numeric(new.order.qty) + + neworder<-addOrder(portfolio=portfolio, + symbol=symbol, + timestamp=timestamp, + qty=new.order.qty, + price=new.order.price-orderThreshold, + ordertype=orderType, + prefer=prefer, + side=order.side, + threshold=orderThreshold, + status="open", + replace=FALSE, return=TRUE, + orderset=ordersubset[ii,"Order.Set"], + label=ordersubset[ii,"Rule"], + ,...=..., TxnFees=txnfees) + + ordersubset<-rbind(ordersubset, neworder) + + ordersubset[ii,"Order.Status"]<-'replaced' + ordersubset[ii,"Order.StatusTime"]<-format(timestamp, "%Y-%m-%d %H:%M:%S") + next() + } + # else next + } + else if(isOHLCmktdata) + { + # check to see if price moved through the limit + + order.side <- ordersubset[ii, "Order.Side"] + + if(order.side == 'long' && as.numeric(Lo(mktdataTimestamp)) < orderPrice + || order.side == 'short' && as.numeric(Hi(mktdataTimestamp)) > orderPrice) + { + txnprice <- orderPrice + txntime <- timestamp + } + else + { + # do we need to change the trailing stop? + + order.threshold <- as.numeric(ordersubset[ii, "Order.Threshold"]) + + if(order.side == 'long') + new.order.price <- max(orderPrice, as.numeric(Hi(mktdataTimestamp)) + order.threshold) + if(order.side == 'short') + new.order.price <- min(orderPrice, as.numeric(Lo(mktdataTimestamp)) + order.threshold) + + if(new.order.price != orderPrice) + { + # adjust trailing stop + + order.qty <- ordersubset[ii, "Order.Qty"] # if orderQty='all' we must recover it + + neworder<-addOrder(portfolio=portfolio, symbol=symbol, timestamp=timestamp, - qty=orderQty, - price=as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1]), + qty=order.qty, + price=new.order.price - order.threshold, ordertype=orderType, - side=ordersubset[ii,"Order.Side"], - threshold=orderThreshold, + side=order.side, + threshold=order.threshold, status="open", replace=FALSE, return=TRUE, + orderset=ordersubset[ii,"Order.Set"], + label=ordersubset[ii,"Rule"], ,...=..., TxnFees=txnfees) - - ordersubset<-rbind(ordersubset, neworder) - - ordersubset[ii,"Order.Status"]<-'replaced' - ordersubset[ii,"Order.StatusTime"]<-format(timestamp, "%Y-%m-%d %H:%M:%S") - next() - } - } - }, - stoptrailing = { - if(isBBOmktdata) - { - - order.side <- ordersubset[ii, "Order.Side"] - mvstop <- FALSE - absOrderThreshold <- abs(orderThreshold) - # +++++++++ stop order price - buy - # ~~~~~~~~~ market price - # --------- stop order price - sell - if(orderQty > 0) { # positive quantity 'buy' - prefer <- 'ask' - mktPrice <- as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1]) - # check to see if price moved through the limit - if(mktPrice >= orderPrice) { # buy when price >= stop - txnprice <- mktPrice - txntime <- timestamp - } - # move stop if price < stop - thresh [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/blotter -r 1511 From noreply at r-forge.r-project.org Sun Sep 29 23:02:00 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 29 Sep 2013 23:02:00 +0200 (CEST) Subject: [Blotter-commits] r1512 - pkg/quantstrat Message-ID: <20130929210200.9F63D18612F@r-forge.r-project.org> Author: braverock Date: 2013-09-29 23:02:00 +0200 (Sun, 29 Sep 2013) New Revision: 1512 Modified: pkg/quantstrat/NAMESPACE Log: - remove uncommitted fn Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-09-29 20:58:46 UTC (rev 1511) +++ pkg/quantstrat/NAMESPACE 2013-09-29 21:02:00 UTC (rev 1512) @@ -13,7 +13,6 @@ export(applySignals) export(applyStrategy) export(applyStrategy.rebalancing) -export(applyStrategy.rebalancing.training) export(chart.forward) export(chart.forward.training) export(delete.paramset)