From noreply at r-forge.r-project.org Tue Oct 1 01:25:13 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 1 Oct 2013 01:25:13 +0200 (CEST) Subject: [Blotter-commits] r1513 - pkg/quantstrat Message-ID: <20130930232513.3CF99186057@r-forge.r-project.org> Author: braverock Date: 2013-10-01 01:25:12 +0200 (Tue, 01 Oct 2013) New Revision: 1513 Modified: pkg/quantstrat/.Rbuildignore Log: = add RStudio regex Modified: pkg/quantstrat/.Rbuildignore =================================================================== --- pkg/quantstrat/.Rbuildignore 2013-09-29 21:02:00 UTC (rev 1512) +++ pkg/quantstrat/.Rbuildignore 2013-09-30 23:25:12 UTC (rev 1513) @@ -1,3 +1,5 @@ sandbox generatechangelog\.sh ChangeLog\.1\.0\.0 +^.*\.Rproj$ +^\.Rproj\.user$ From noreply at r-forge.r-project.org Tue Oct 1 21:58:39 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 1 Oct 2013 21:58:39 +0200 (CEST) Subject: [Blotter-commits] r1514 - pkg/quantstrat/R Message-ID: <20131001195839.93772186017@r-forge.r-project.org> Author: erastus Date: 2013-10-01 21:58:39 +0200 (Tue, 01 Oct 2013) New Revision: 1514 Modified: pkg/quantstrat/R/parameters.R Log: - fixed parameters.R portfolio environment subsetting issue Modified: pkg/quantstrat/R/parameters.R =================================================================== --- pkg/quantstrat/R/parameters.R 2013-09-30 23:25:12 UTC (rev 1513) +++ pkg/quantstrat/R/parameters.R 2013-10-01 19:58:39 UTC (rev 1514) @@ -399,7 +399,11 @@ initialPortf<-getPortfolio(portfolios) symbols<-ls(initialPortf$symbols) - initDate<-time(first(initialPortf$symbols[[1]]$posPL)) + + # TODO: we likely want to search for first date, not (arbitrarily?) + # choose the first symbol + firstsymbol<-first(symbols) + initDate<-time(first(initialPortf$symbols[[firstsymbol]]$posPL)) limits<-list() for(symbol in ls(initialPortf$symbols)) From noreply at r-forge.r-project.org Thu Oct 3 10:11:21 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 3 Oct 2013 10:11:21 +0200 (CEST) Subject: [Blotter-commits] r1515 - pkg/quantstrat/R pkg/quantstrat/demo pkg/quantstrat/inst/extdata www www/data www/data/ES Message-ID: <20131003081122.05156184985@r-forge.r-project.org> Author: erastus Date: 2013-10-03 10:11:20 +0200 (Thu, 03 Oct 2013) New Revision: 1515 Added: pkg/quantstrat/inst/extdata/luxor.RData www/data/ www/data/ES/ www/data/ES/2011.01.02.ES.rda www/data/ES/2011.01.03.ES.rda www/data/ES/2011.01.04.ES.rda www/data/ES/2011.01.05.ES.rda www/data/ES/2011.01.06.ES.rda www/data/ES/2011.01.07.ES.rda www/data/ES/2011.01.09.ES.rda www/data/ES/2011.01.10.ES.rda www/data/ES/2011.01.11.ES.rda www/data/ES/2011.01.12.ES.rda www/data/ES/2011.01.13.ES.rda www/data/ES/2011.01.14.ES.rda www/data/ES/2011.01.16.ES.rda www/data/ES/2011.01.17.ES.rda www/data/ES/2011.01.18.ES.rda www/data/ES/2011.01.19.ES.rda www/data/ES/2011.01.20.ES.rda www/data/ES/2011.01.21.ES.rda www/data/ES/2011.01.23.ES.rda www/data/ES/2011.01.24.ES.rda www/data/ES/2011.01.25.ES.rda www/data/ES/2011.01.26.ES.rda www/data/ES/2011.01.27.ES.rda www/data/ES/2011.01.28.ES.rda www/data/ES/2011.01.30.ES.rda www/data/ES/2011.01.31.ES.rda Modified: pkg/quantstrat/R/walk.forward.R pkg/quantstrat/demo/luxor.1.strategy.basic.R pkg/quantstrat/demo/luxor.2.add.paramsets.R pkg/quantstrat/demo/luxor.3.paramset.sma.R pkg/quantstrat/demo/luxor.4.paramset.timespan.R pkg/quantstrat/demo/luxor.5.strategy.ordersets.R pkg/quantstrat/demo/luxor.6.paramset.stoploss.R pkg/quantstrat/demo/luxor.6.paramset.stoptrailing.R pkg/quantstrat/demo/luxor.6.paramset.takeprofit.R pkg/quantstrat/demo/luxor.7.exit+risk.R pkg/quantstrat/demo/luxor.sample.tradeGraphs.sma.R pkg/quantstrat/demo/luxor.sample.tradeGraphs.timespan.R pkg/quantstrat/demo/pair_trade.R Log: - luxor source/load path wrangling, moved ES data for forthcoming load()ing via http, other small fixes Modified: pkg/quantstrat/R/walk.forward.R =================================================================== --- pkg/quantstrat/R/walk.forward.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/R/walk.forward.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -69,7 +69,7 @@ results <- list() # assuming that timespans for all portfolio symbols are same, so ok to use 1st symbol to calculate end points - symbol.st <- names(portfolio$symbols)[1] + symbol.st <- first(ls(portfolio$symbols)) symbol <- get(symbol.st) ep <- endpoints(symbol, on=period) Modified: pkg/quantstrat/demo/luxor.1.strategy.basic.R =================================================================== --- pkg/quantstrat/demo/luxor.1.strategy.basic.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.1.strategy.basic.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -8,6 +8,10 @@ # # Paragraph 3.2: luxor with slippage and transaction costs +require(quantstrat) + +require(quantstrat) + ##### PLACE DEMO AND TEST DATES HERE ################# # #if(isTRUE(options('in_test')$in_test)) @@ -19,11 +23,11 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) .fast = 10 .slow = 30 -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### blotter Modified: pkg/quantstrat/demo/luxor.2.add.paramsets.R =================================================================== --- pkg/quantstrat/demo/luxor.2.add.paramsets.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.2.add.paramsets.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -19,7 +19,7 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) ### Modified: pkg/quantstrat/demo/luxor.3.paramset.sma.R =================================================================== --- pkg/quantstrat/demo/luxor.3.paramset.sma.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.3.paramset.sma.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -9,9 +9,10 @@ # Paragraph 3.3: luxor SMA paramset optimization ### +require(quantstrat) -source('luxor.include.R') -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### blotter @@ -25,7 +26,9 @@ load.strategy(strategy.st) ### doMC - +if (!"doMC" %in% installed.packages()[,1]) { + install.packages("doMC") +} require(doMC) registerDoMC(cores=8) Modified: pkg/quantstrat/demo/luxor.4.paramset.timespan.R =================================================================== --- pkg/quantstrat/demo/luxor.4.paramset.timespan.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.4.paramset.timespan.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -10,9 +10,11 @@ stop('#### DEMO BROKEN - BEING FIXED ###') -source('luxor.include.R') -source('luxor.getSymbols.R') +require(quantstrat) +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) + ### blotter initPortf(portfolio.st, symbols='GBPUSD', initDate=initDate, currency='USD') @@ -25,7 +27,9 @@ load.strategy(strategy.st) ### doMC - +if (!"doMC" %in% installed.packages()[,1]) { + install.packages("doMC") +} require(doMC) registerDoMC(cores=8) Modified: pkg/quantstrat/demo/luxor.5.strategy.ordersets.R =================================================================== --- pkg/quantstrat/demo/luxor.5.strategy.ordersets.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.5.strategy.ordersets.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -21,7 +21,7 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) ### define strategy Modified: pkg/quantstrat/demo/luxor.6.paramset.stoploss.R =================================================================== --- pkg/quantstrat/demo/luxor.6.paramset.stoploss.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.6.paramset.stoploss.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -21,8 +21,8 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### @@ -48,10 +48,12 @@ #enable.rule('luxor', 'chain', 'TakeProfit') ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules - require(foreach) #registerDoSEQ() +if (!"doMC" %in% installed.packages()[,1]) { + install.packages("doMC") +} require(doMC) registerDoMC(cores=8) Modified: pkg/quantstrat/demo/luxor.6.paramset.stoptrailing.R =================================================================== --- pkg/quantstrat/demo/luxor.6.paramset.stoptrailing.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.6.paramset.stoptrailing.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -21,8 +21,8 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### @@ -48,10 +48,12 @@ #enable.rule('luxor', 'chain', 'TakeProfit') ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules - require(foreach) #registerDoSEQ() +if (!"doMC" %in% installed.packages()[,1]) { + install.packages("doMC") +} require(doMC) registerDoMC(cores=2) Modified: pkg/quantstrat/demo/luxor.6.paramset.takeprofit.R =================================================================== --- pkg/quantstrat/demo/luxor.6.paramset.takeprofit.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.6.paramset.takeprofit.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -21,8 +21,8 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.include.R') -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### @@ -48,10 +48,12 @@ enable.rule('luxor', 'chain', 'TakeProfit') ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules - require(foreach) #registerDoSEQ() +if (!"doMC" %in% installed.packages()[,1]) { + install.packages("doMC") +} require(doMC) registerDoMC(cores=8) Modified: pkg/quantstrat/demo/luxor.7.exit+risk.R =================================================================== --- pkg/quantstrat/demo/luxor.7.exit+risk.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.7.exit+risk.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -8,8 +8,10 @@ # # Paragraph 3.5: determination of appropriate exit and risk management -source('luxor.include.R') +require(quantstrat) +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) + ##### PLACE DEMO AND TEST DATES HERE ################# # #if(isTRUE(options('in_test')$in_test)) @@ -21,7 +23,7 @@ # {initDate="1999-12-31" # endDate=Sys.Date()} -source('luxor.getSymbols.R') +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) ### blotter Modified: pkg/quantstrat/demo/luxor.sample.tradeGraphs.sma.R =================================================================== --- pkg/quantstrat/demo/luxor.sample.tradeGraphs.sma.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.sample.tradeGraphs.sma.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -12,7 +12,10 @@ ### load 'stats' back into .GlobalEnv -load('../data/luxor.parameters.1-10.30-55.RData') +load(paste0( + path.package('quantstrat'), + '/data/luxor.parameters.2-10.30-55.RData') +) ### show trade graphs from stats Modified: pkg/quantstrat/demo/luxor.sample.tradeGraphs.timespan.R =================================================================== --- pkg/quantstrat/demo/luxor.sample.tradeGraphs.timespan.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/luxor.sample.tradeGraphs.timespan.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -10,7 +10,10 @@ require(quantstrat) -load('../data/luxor.timespan.24x24.2002-2008.RData') +load(paste0( + path.package('quantstrat'), + '/data/luxor.timespan.24x24.2002-2008.RData') +) names(stats)[names(stats)=='testPackListPRL[[k]]$parameters']<-'timespan' Modified: pkg/quantstrat/demo/pair_trade.R =================================================================== --- pkg/quantstrat/demo/pair_trade.R 2013-10-01 19:58:39 UTC (rev 1514) +++ pkg/quantstrat/demo/pair_trade.R 2013-10-03 08:11:20 UTC (rev 1515) @@ -18,16 +18,14 @@ # The Qty of Stock A that it buys (sells) = MaxPos / lvls # The Qty of Stock B that is sells (buys) = MaxPos * Ratio / lvls +require(quantstrat) + suppressWarnings(rm("order_book.pair1",pos=.strategy)) suppressWarnings(rm("account.pairs", "portfolio.pair1", pos=.blotter)) suppressWarnings(rm("initDate", "endDate", "startDate", "initEq", "SD", "N", "symb1", "symb2", "portfolio1.st", "account.st", "pairStrat", "out1")) -require(quantstrat) - - - ##### PLACE DEMO AND TEST DATES HERE ################# # #if(isTRUE(options('in_test')$in_test)) Added: pkg/quantstrat/inst/extdata/luxor.RData =================================================================== (Binary files differ) Property changes on: pkg/quantstrat/inst/extdata/luxor.RData ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.02.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.02.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.03.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.03.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.04.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.04.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.05.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.05.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.06.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.06.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.07.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.07.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.09.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.09.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.10.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.10.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.11.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.11.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.12.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.12.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.13.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.13.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.14.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.14.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.16.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.16.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.17.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.17.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.18.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.18.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.19.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.19.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.20.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.20.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.21.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.21.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.23.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.23.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.24.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.24.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.25.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.25.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.26.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.26.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.27.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.27.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.28.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.28.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.30.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.30.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: www/data/ES/2011.01.31.ES.rda =================================================================== (Binary files differ) Property changes on: www/data/ES/2011.01.31.ES.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream From noreply at r-forge.r-project.org Thu Oct 3 22:09:08 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 3 Oct 2013 22:09:08 +0200 (CEST) Subject: [Blotter-commits] r1516 - pkg/quantstrat/R Message-ID: <20131003200908.E475A185DF8@r-forge.r-project.org> Author: braverock Date: 2013-10-03 22:09:08 +0200 (Thu, 03 Oct 2013) New Revision: 1516 Modified: pkg/quantstrat/R/applyStrategy.rebalancing.R pkg/quantstrat/R/orders.R pkg/quantstrat/R/osFUNs.R pkg/quantstrat/R/rebalance.rules.R pkg/quantstrat/R/ruleOrderProc.R pkg/quantstrat/R/ruleSignal.R Log: - changes to be more robust to multiple columns returned by getPrice - updates to fix rebalancing code Modified: pkg/quantstrat/R/applyStrategy.rebalancing.R =================================================================== --- pkg/quantstrat/R/applyStrategy.rebalancing.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/applyStrategy.rebalancing.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -130,7 +130,8 @@ #now we need to do the endpoints loop. for(i in 2:length(pindex)){ - #the proper endpoints for each symbol will vary, so we need to get them separately, and subset each one + #the proper endpoints for each symbol will vary, so we need to get + #them separately, and subset each one for (symbol in symbols){ #sret<-ret[[portfolio]][[symbol]] mktdata<-get(symbol,pos=st) @@ -138,11 +139,20 @@ md_subset<-mktdata[as.POSIXct(index(mktdata))>pindex[i-1]&as.POSIXct(index(mktdata))<=pindex[i]] if(nrow(md_subset)<1) { next() - } else{ + } else { #applyRules to this subset for this instrument - #sret$rules$pathdep<-rbind(sret$rules$pathdep, - applyRules(portfolio=portfolio, symbol=symbol, strategy=s, mktdata=md_subset, Dates=NULL, indicators=sret$indicators, signals=sret$signals, parameters=parameters, ..., path.dep=TRUE) - #) + sret$rules$pathdep<-rbind(sret$rules$pathdep, + applyRules(portfolio=portfolio, + symbol=symbol, + strategy=s, + mktdata=md_subset, + Dates=NULL, + indicators=sret$indicators, + signals=sret$signals, + parameters=parameters, + ..., + path.dep=TRUE) + ) } #ret[[portfolio]][[symbol]]<-sret Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/orders.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -10,16 +10,16 @@ #' #' \describe{ #' \item{Order.Qty}{} -#' \item{Order.Price}{} -#' \item{Order.Type}{} -#' \item{Order.Side}{} -#' \item{Order.Threshold}{} -#' \item{Order.Status}{} -#' \item{Order.StatusTime}{} -#' \item{Prefer}{} -#' \item{Order.Set}{} -#' \item{Txn.Fees}{} -#' \item{Rule}{} +#' \item{Order.Price}{} +#' \item{Order.Type}{} +#' \item{Order.Side}{} +#' \item{Order.Threshold}{} +#' \item{Order.Status}{} +#' \item{Order.StatusTime}{} +#' \item{Prefer}{} +#' \item{Order.Set}{} +#' \item{Txn.Fees}{} +#' \item{Rule}{} #' } #' @aliases #' get.orderbook @@ -271,8 +271,8 @@ ..., TxnFees=0, label='', - time.in.force='' - ) + time.in.force='' +) { # get order book #orderbook <- getOrderBook(portfolio) @@ -371,7 +371,8 @@ time.in.force <- timestamp + time.in.force time.in.force <- format(time.in.force, "%Y-%m-%d %H:%M:%0S") - } + #TODO FIXME this line probably needs to be sensitive to the index of the market data, Date vs POSIXct + } } #set up the other parameters Modified: pkg/quantstrat/R/osFUNs.R =================================================================== --- pkg/quantstrat/R/osFUNs.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/osFUNs.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -50,9 +50,16 @@ addPosLimit <- function (portfolio, symbol, timestamp, maxpos, longlevels = 1, minpos = -maxpos, shortlevels = longlevels) { portf <- getPortfolio(portfolio) + #catch error where maxpos/minpos have length greater than 1 + if(length(maxpos)>1) maxpos <- maxpos[,1] + if(length(minpos)>1) minpos <- minpos[,1] newrow <- xts(cbind(maxpos, longlevels, minpos, shortlevels), order.by = as.POSIXct(timestamp)) - colnames(newrow) <- c("MaxPos", "LongLevels", "MinPos", "ShortLevels") - + tc <- try(colnames(newrow) <- c("MaxPos", "LongLevels", "MinPos", "ShortLevels")) +# if(inherits(tc, 'try-error')) { +# print(symbol) +# print(newrow) +# browser() +# } if (is.null(portf$symbols[[symbol]]$PosLimit)) { portf$symbols[[symbol]]$PosLimit <- newrow } else { Modified: pkg/quantstrat/R/rebalance.rules.R =================================================================== --- pkg/quantstrat/R/rebalance.rules.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/rebalance.rules.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -30,7 +30,7 @@ #' add.rule(strategy.name, 'rulePctEquity', #' arguments=list(rebalance_on='months', #' trade.percent=.02, -#' refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])), +#' refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])[,1]), #' digits=0 #' ), #' type='rebalance', @@ -52,6 +52,7 @@ trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) total.equity <- initEq+trading.pl tradeSize <- total.equity * trade.percent + if(length(refprice)>1) refprice <- refprice[,1] if(!is.null(refprice)) tradeSize <- tradeSize/refprice if(!is.null(digits)) tradeSize<-round(tradeSize,digits) addPosLimit(portfolio = portfolio, Modified: pkg/quantstrat/R/ruleOrderProc.R =================================================================== --- pkg/quantstrat/R/ruleOrderProc.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/ruleOrderProc.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -176,7 +176,7 @@ 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)))) + (!has.Lo(mktdata) && orderPrice > as.numeric(getPrice(mktdataTimestamp, prefer=prefer)[,1]))) { txnprice = min(orderPrice, Hi(mktdataTimestamp)) txntime = timestamp @@ -184,7 +184,7 @@ } 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))) ) + (!has.Hi(mktdata) && orderPrice < as.numeric(getPrice(mktdataTimestamp,prefer=prefer)[,1])) ) { txnprice = max(orderPrice, Lo(mktdataTimestamp)) txntime = timestamp Modified: pkg/quantstrat/R/ruleSignal.R =================================================================== --- pkg/quantstrat/R/ruleSignal.R 2013-10-03 08:11:20 UTC (rev 1515) +++ pkg/quantstrat/R/ruleSignal.R 2013-10-03 20:09:08 UTC (rev 1516) @@ -140,7 +140,7 @@ else prefer='bid' # we're selling, so give it to them for what they're bidding } - orderprice <- try(getPrice(x=mktdata, prefer=prefer))[timestamp] + orderprice <- try(getPrice(x=mktdata, prefer=prefer)[,1][timestamp]) }, passive =, work =, @@ -151,7 +151,7 @@ else prefer='ask' # we're selling, so work the ask price } - orderprice <- try(getPrice(x=mktdata, prefer=prefer))[timestamp] + orderprice <- try(getPrice(x=mktdata, prefer=prefer)[,1][timestamp]) }, maker = { if(hasArg(price) & length(match.call(expand.dots=TRUE)$price)>1) { @@ -159,9 +159,9 @@ orderprice <- try(match.call(expand.dots=TRUE)$price) } else { if(!is.null(threshold)) { - baseprice<- last(getPrice(x=mktdata)[timestamp]) # this should get either the last trade price or the Close + baseprice<- last(getPrice(x=mktdata)[,1][timestamp]) # this should get either the last trade price or the Close if(hasArg(tmult) & isTRUE(match.call(expand.dots=TRUE)$tmult)) { - baseprice<- last(getPrice(x=mktdata)[timestamp]) # this should get either the last trade price or the Close + baseprice<- last(getPrice(x=mktdata)[,1][timestamp]) # this should get either the last trade price or the Close # threshold is a multiplier of current price if (length(threshold)>1){ orderprice <- baseprice * threshold # assume the user has set proper threshold multipliers for each side From noreply at r-forge.r-project.org Thu Oct 3 22:10:10 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 3 Oct 2013 22:10:10 +0200 (CEST) Subject: [Blotter-commits] r1517 - pkg/quantstrat/demo Message-ID: <20131003201011.018C41851A4@r-forge.r-project.org> Author: braverock Date: 2013-10-03 22:10:10 +0200 (Thu, 03 Oct 2013) New Revision: 1517 Modified: pkg/quantstrat/demo/faber_rebal.R Log: - updates to only pass one column prices/pos on deeer in the code Modified: pkg/quantstrat/demo/faber_rebal.R =================================================================== --- pkg/quantstrat/demo/faber_rebal.R 2013-10-03 20:09:08 UTC (rev 1516) +++ pkg/quantstrat/demo/faber_rebal.R 2013-10-03 20:10:10 UTC (rev 1517) @@ -94,7 +94,7 @@ # set intial position limits posval<-initEq/length(symbols) for(symbol in symbols){ - pos<-round((posval/first(getPrice(get(symbol)))),-2) + pos<-round((posval/first(getPrice(get(symbol)))[,1]),-2) addPosLimit('faber',symbol,initDate, maxpos=pos,minpos=-pos) } print("setup completed") @@ -121,7 +121,7 @@ add.rule('faber', 'rulePctEquity', arguments=list(rebalance_on='quarters', trade.percent=1/length(symbols), - refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])), + refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')][,1])), digits=0 ), type='rebalance', From noreply at r-forge.r-project.org Tue Oct 8 16:49:07 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 8 Oct 2013 16:49:07 +0200 (CEST) Subject: [Blotter-commits] r1518 - pkg/blotter/R Message-ID: <20131008144907.D0D741860EA@r-forge.r-project.org> Author: bodanker Date: 2013-10-08 16:49:07 +0200 (Tue, 08 Oct 2013) New Revision: 1518 Modified: pkg/blotter/R/getBySymbol.R pkg/blotter/R/updatePortf.R Log: - Patch Dates==NULL handling Modified: pkg/blotter/R/getBySymbol.R =================================================================== --- pkg/blotter/R/getBySymbol.R 2013-10-03 20:10:10 UTC (rev 1517) +++ pkg/blotter/R/getBySymbol.R 2013-10-08 14:49:07 UTC (rev 1518) @@ -18,7 +18,8 @@ # FUNCTION if(all(is.null(Dates)) || all(is.na(Dates))) # if no date is specified, get all available dates - Dates = xts:::time.xts(Portfolio$symbols[[1]]$posPL) + Dates <- unique(do.call(c,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]])), use.names=FALSE, recursive=FALSE))) + # else Dates = xts:::time.xts(Portfolio$symbols[[1]]$posPL[Dates]) if(!is.null(attr(Portfolio,'currency')) & native==FALSE) { p.ccy.str<-attr(Portfolio,'currency') Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-10-03 20:10:10 UTC (rev 1517) +++ pkg/blotter/R/updatePortf.R 2013-10-08 14:49:07 UTC (rev 1518) @@ -31,8 +31,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 <- unique(do.call(c,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]][Dates]) ), use.names=FALSE, recursive=FALSE))) + if(is.null(Dates)) Dates <- unique(do.call(c,c(lapply(Portfolio$symbols, function(x) index(x[["posPL"]])), 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') From noreply at r-forge.r-project.org Tue Oct 8 20:12:10 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 8 Oct 2013 20:12:10 +0200 (CEST) Subject: [Blotter-commits] r1519 - in pkg/blotter: R man Message-ID: <20131008181210.C7DB41863AF@r-forge.r-project.org> Author: braverock Date: 2013-10-08 20:12:10 +0200 (Tue, 08 Oct 2013) New Revision: 1519 Added: pkg/blotter/man/addAcctTxn.Rd pkg/blotter/man/put.account.Rd pkg/blotter/man/put.portfolio.Rd Removed: pkg/blotter/man/addTxns.Rd Modified: pkg/blotter/R/addPortfInstr.R pkg/blotter/R/addTxn.R pkg/blotter/R/updateAcct.R pkg/blotter/R/updateEndEq.R pkg/blotter/R/updatePortf.R pkg/blotter/R/updatePosPL.R pkg/blotter/man/PortfReturns.Rd pkg/blotter/man/addTxn.Rd pkg/blotter/man/initAcct.Rd pkg/blotter/man/initPortf.Rd Log: - remove assign's of portfolio and account objects, these are in an environment, and updated in place - update roxygen docs Modified: pkg/blotter/R/addPortfInstr.R =================================================================== --- pkg/blotter/R/addPortfInstr.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/addPortfInstr.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -19,8 +19,8 @@ portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = 0) portfolio$symbols[[instrument]][[paste('posPL',currency,sep='.')]] = portfolio$symbols[[instrument]]$posPL } - - assign(paste("portfolio",as.character(pname),sep='.'),portfolio,envir=.blotter) + #portfolio is already an environment, it's been updated in place + #assign(paste("portfolio",as.character(pname),sep='.'),portfolio,envir=.blotter) } ############################################################################### Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/addTxn.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -12,7 +12,7 @@ #' name of a function) in which case the function is #' evaluated to determine the fee amount. #' -#' The \code{pennyPerShare} function provides a simple +#' The \code{\link{pennyPerShare}} function provides a simple #' example of a transaction cost function. #' #' Transactions which would cross the position through zero @@ -38,15 +38,18 @@ #' @param ConMult Contract/instrument multiplier for the Symbol if it is not defined in an instrument specification #' @param verbose If TRUE (default) the function prints the elements of the transaction in a line to the screen, e.g., "2007-01-08 IBM 50 @@ 77.6". Suppress using FALSE. #' @param eps value to add to force unique indices +#' @param TxnData An xts object containing all required txn fields (for addTxns) #' @note #' The addTxn function will eventually also handle other transaction types, #' such as adjustments for corporate actions or expire/assign for options. +#' See \code{\link{addDiv}} #' +#' TODO figure out if we can fully vectorize the addTxns function to make it faster #' @seealso \code{\link{addTxns}}, \code{\link{pennyPerShare}}, \code{\link{initPortf}} -#' @author Peter Carl +#' @author Peter Carl, Brian G. Peterson #' @export addTxn <- function(Portfolio, Symbol, TxnDate, TxnQty, TxnPrice, ..., TxnFees=0, ConMult=NULL, verbose=TRUE, eps=1e-06) -{ # @author Peter Carl +{ pname <- Portfolio PrevPosQty = getPosQty(pname, Symbol, TxnDate) @@ -76,11 +79,11 @@ } } - #If there is no table for the symbol then create a new one - if (is.null(Portfolio$symbols[[Symbol]])){ - addPortfInstr(Portfolio=pname, symbols=Symbol) - Portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) - } + #If there is no table for the symbol then create a new one + if (is.null(Portfolio$symbols[[Symbol]])){ + addPortfInstr(Portfolio=pname, symbols=Symbol) + Portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) + } # FUNCTION @@ -112,13 +115,13 @@ # Calculate any realized profit or loss (net of fees) from the transaction GrossTxnRealizedPL = TxnQty * ConMult * (PrevPosAvgCost - TxnAvgCost) - # if the previous position is zero, RealizedPL = 0 - # if previous position is positive and position is larger, RealizedPL =0 - # if previous position is negative and position is smaller, RealizedPL =0 - if(abs(PrevPosQty) < abs(PosQty) | (PrevPosQty = 0)) - GrossTxnRealizedPL = 0 + # if the previous position is zero, RealizedPL = 0 + # if previous position is positive and position is larger, RealizedPL =0 + # if previous position is negative and position is smaller, RealizedPL =0 + if(abs(PrevPosQty) < abs(PosQty) | (PrevPosQty = 0)) + GrossTxnRealizedPL = 0 - NetTxnRealizedPL = GrossTxnRealizedPL + txnfees + NetTxnRealizedPL = GrossTxnRealizedPL + txnfees # Store the transaction and calculations NewTxn = xts(t(c(TxnQty, TxnPrice, TxnValue, TxnAvgCost, PosQty, PosAvgCost, GrossTxnRealizedPL, txnfees, NetTxnRealizedPL, ConMult)), order.by=TxnDate) @@ -126,11 +129,12 @@ Portfolio$symbols[[Symbol]]$txn<-rbind(Portfolio$symbols[[Symbol]]$txn, NewTxn) if(verbose) -# print(paste(TxnDate, Symbol, TxnQty, "@",TxnPrice, sep=" ")) - print(paste(format(TxnDate, "%Y-%m-%d %H:%M:%S"), Symbol, TxnQty, "@",TxnPrice, sep=" ")) - #print(Portfolio$symbols[[Symbol]]$txn) + # print(paste(TxnDate, Symbol, TxnQty, "@",TxnPrice, sep=" ")) + print(paste(format(TxnDate, "%Y-%m-%d %H:%M:%S"), Symbol, TxnQty, "@",TxnPrice, sep=" ")) + #print(Portfolio$symbols[[Symbol]]$txn) - assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) + #portfolio is already an environment, it's been updated in place + #assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) } #' Example TxnFee cost function @@ -141,17 +145,9 @@ return(abs(TxnQty) * -0.01) } -#' Add multiple transactions to a portfolio -#' @param Portfolio A portfolio name that points to a portfolio object structured with \code{\link{initPortf}} -#' @param Symbol An instrument identifier for a symbol included in the portfolio, e.g., "IBM" -#' @param TxnData An xts object containing all required txn fields -#' @param \dots Any other passthrough parameters -#' @param verbose If TRUE (default) the function prints the elements of the transaction in a line to the screen, e.g., "2007-01-08 IBM 50 @@ 77.6". Suppress using FALSE. -#' @param ConMult Contract or instrument multiplier for the Symbol if it is not defined in an instrument specification -#' @seealso \code{\link{addTxn}}, \code{\link{initPortf}} -#' @note -#' TODO figure out if we can fully vectorize this function to make it faster -addTxns<- function(Portfolio, Symbol, TxnData , verbose=TRUE, ..., ConMult=NULL) +#' @rdname addTxn +#' @export +addTxns<- function(Portfolio, Symbol, TxnData , verbose=FALSE, ..., ConMult=NULL) { pname<-Portfolio Portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) @@ -176,7 +172,7 @@ TxnPrice <- as.numeric(TxnData[row,'Price']) # If TxnFees are to be used, it must be a column in TxnData TxnFees <- if (any(grepl("TxnFees", colnames(TxnData)))) { - as.numeric(TxnData[row, "TxnFees"]) + as.numeric(TxnData[row, "TxnFees"]) } else 0 #TxnFees <- ifelse( is.function(TxnFees), TxnFees(TxnQty, TxnPrice), TxnFees) TxnValue <- .calcTxnValue(TxnQty, TxnPrice, TxnFees, ConMult) @@ -184,8 +180,8 @@ #PrevPosQty <- getPosQty(pname, Symbol, index(TxnData[row,])) PosQty <- PrevPosQty+TxnQty PosAvgCost <- .calcPosAvgCost(PrevPosQty, PrevPosAvgCost, 0, PosQty, ConMult) # lag this over the data? - GrossTxnRealizedPL = TxnQty * ConMult * (PrevPosAvgCost - TxnAvgCost) - NetTxnRealizedPL = GrossTxnRealizedPL - TxnFees + GrossTxnRealizedPL = TxnQty * ConMult * (PrevPosAvgCost - TxnAvgCost) + NetTxnRealizedPL = GrossTxnRealizedPL - TxnFees PrevPosQty <- PosQty PrevPosAvgCost <- PosAvgCost @@ -211,8 +207,9 @@ Portfolio$symbols[[Symbol]]$txn<-rbind(Portfolio$symbols[[Symbol]]$txn,NewTxns) if(verbose) print(NewTxns) - - assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) + + #portfolio is already an environment, it's been updated in place + # assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) } #' Add cash dividend transactions to a portfolio. @@ -281,7 +278,8 @@ print(paste(TxnDate, Symbol, "Dividend", DivPerShare, "on", PrevPosQty, "shares:", -TxnValue, sep=" ")) #print(Portfolio$symbols[[Symbol]]$txn) - assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) + #portfolio is already an environment, it's been updated in place + #assign(paste("portfolio",pname,sep='.'),Portfolio,envir=.blotter) } ############################################################################### # Blotter: Tools for transaction-oriented trading systems development Modified: pkg/blotter/R/updateAcct.R =================================================================== --- pkg/blotter/R/updateAcct.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/updateAcct.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -148,8 +148,9 @@ summary[is.na(summary)] <- 0 # replace any NA's with zero Account$summary <- rbind(Account$summary, summary) # This function does not calculate End.Eq - - assign(paste("account",name,sep='.'),Account, envir=.blotter) + + #account is already an environment, it's been updated in place + #assign(paste("account",name,sep='.'),Account, envir=.blotter) return(name) #not sure this is a good idea } Modified: pkg/blotter/R/updateEndEq.R =================================================================== --- pkg/blotter/R/updateEndEq.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/updateEndEq.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -34,7 +34,8 @@ EndCapital = PrevEndEq + cumsum(Additions + Withdrawals + NetPerformance) Account$summary$End.Eq[Dates] <- EndCapital - assign(paste("account",aname,sep='.'),Account, envir=.blotter) + #account is already an environment, it's been updated in place + #assign(paste("account",aname,sep='.'),Account, envir=.blotter) return(aname) #not sure this is a good idea } Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/updatePortf.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -101,8 +101,9 @@ }else{ Portfolio$summary<-rbind(Portfolio$summary[paste('::',startDate,sep='')],summary) } - # assign Portfolio to environment - assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) + + #portfolio is already an environment, it's been updated in place + #assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) return(pname) #not sure this is a good idea } Modified: pkg/blotter/R/updatePosPL.R =================================================================== --- pkg/blotter/R/updatePosPL.R 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/R/updatePosPL.R 2013-10-08 18:12:10 UTC (rev 1519) @@ -219,8 +219,8 @@ #stick it in posPL.ccy Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]]<-rbind(Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]],TmpPeriods) - # assign Portfolio to environment - assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) + #portfolio is already an environment, it's been updated in place + #assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) } ############################################################################### Modified: pkg/blotter/man/PortfReturns.Rd =================================================================== --- pkg/blotter/man/PortfReturns.Rd 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/man/PortfReturns.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -3,7 +3,8 @@ \title{Calculate portfolio instrument returns} \usage{ PortfReturns(Account, method = c("contribution"), ..., - Dates = NULL, Portfolios = NULL) + Dates = NULL, Portfolios = NULL, + period = c("daily", "none")) } \arguments{ \item{Account}{string name of the account to generate @@ -20,6 +21,8 @@ \item{Portfolios}{concatenated string vector for portfolio names to retrieve returns on, default NULL (all portfolios)} + + \item{period}{one of daily} } \description{ This function (for now) calculates return on initial Added: pkg/blotter/man/addAcctTxn.Rd =================================================================== --- pkg/blotter/man/addAcctTxn.Rd (rev 0) +++ pkg/blotter/man/addAcctTxn.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -0,0 +1,61 @@ +\name{addAcctTxn} +\alias{addAcctTxn} +\title{Add capital account transactions, such as capital additions and withdrawals or interest income (expense)} +\usage{ + addAcctTxn(Account, TxnDate, + TxnType = c("Additions", "Withdrawals", "Interest"), + Amount, ..., verbose = TRUE) +} +\arguments{ + \item{name}{Account name, as string} + + \item{TxnDate}{transaction date as ISO 8601, e.g., + '2008-09-01' or '2010-01-05 09:54:23.12345'} + + \item{TxnType}{string indicating the type of account + transaction, only "Addition", "Withdrawal", or "Interest" + are currently supported} + + \item{amount}{As of now, the currency of the transaction + MUST MATCH the currency of the Account. Patches + welcome.} + + \item{\dots}{any other passthrough parameters} + + \item{verbose}{If TRUE (default) the function prints the + elements of the transaction in a line to the screen, + e.g., "2007-01-08 Withdrawal 15,012,235". Suppress using + FALSE.} +} +\description{ + For the specified Account, take in the date, amount, and + type of transaction and append it to the correct list in + the account object +} +\details{ + Adds capital transactions to a rudimentary transactions + table in the Account object. This may be useful when + tracking the denominator of returns when there are + changes to the account's capital or significant interest + income. In the Account$summary table, there are several + placeholder columns that mimic the CFTC's 13-column + report. Columns of interest here are "Additions", + "Withdrawals", and "Interest". Transactions added with + this function will be added into the appropriate one of + three slots in the Account object (Account$additions, + Account$withdrawals, or Account$Interest), which contains + an xts object of individual transactions with a date and + amount. The \code{\link{updateAcct}} function will read + the transactions from each list in turn, aggregate them + by the specified date scope, and slot them into the + \code{Account$summary} table as it's built. + \code{\link{UpdateEndEq}} should then just work. +} +\author{ + Peter Carl +} +\seealso{ + \code{\link{initAcct}}, \code{\link{updateAcct}}, + \code{\link{updateEndEq}} +} + Modified: pkg/blotter/man/addTxn.Rd =================================================================== --- pkg/blotter/man/addTxn.Rd 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/man/addTxn.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -1,10 +1,14 @@ \name{addTxn} \alias{addTxn} +\alias{addTxns} \title{Add transactions to a portfolio.} \usage{ addTxn(Portfolio, Symbol, TxnDate, TxnQty, TxnPrice, ..., TxnFees = 0, ConMult = NULL, verbose = TRUE, - eps = 0.000001) + eps = 1e-06) + + addTxns(Portfolio, Symbol, TxnData, verbose = FALSE, ..., + ConMult = NULL) } \arguments{ \item{Portfolio}{A portfolio name that points to a @@ -36,6 +40,9 @@ e.g., "2007-01-08 IBM 50 @ 77.6". Suppress using FALSE.} \item{eps}{value to add to force unique indices} + + \item{TxnData}{An xts object containing all required txn + fields (for addTxns)} } \description{ When a trade or adjustment is made to the Portfolio, the @@ -52,8 +59,8 @@ name of a function) in which case the function is evaluated to determine the fee amount. - The \code{pennyPerShare} function provides a simple - example of a transaction cost function. + The \code{\link{pennyPerShare}} function provides a + simple example of a transaction cost function. Transactions which would cross the position through zero will be split into two transactions, one to flatten the @@ -71,10 +78,14 @@ \note{ The addTxn function will eventually also handle other transaction types, such as adjustments for corporate - actions or expire/assign for options. + actions or expire/assign for options. See + \code{\link{addDiv}} + + TODO figure out if we can fully vectorize the addTxns + function to make it faster } \author{ - Peter Carl + Peter Carl, Brian G. Peterson } \seealso{ \code{\link{addTxns}}, \code{\link{pennyPerShare}}, Deleted: pkg/blotter/man/addTxns.Rd =================================================================== --- pkg/blotter/man/addTxns.Rd 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/man/addTxns.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -1,38 +0,0 @@ -\name{addTxns} -\alias{addTxns} -\title{Add multiple transactions to a portfolio} -\usage{ - addTxns(Portfolio, Symbol, TxnData, verbose = TRUE, ..., - ConMult = NULL) -} -\arguments{ - \item{Portfolio}{A portfolio name that points to a - portfolio object structured with \code{\link{initPortf}}} - - \item{Symbol}{An instrument identifier for a symbol - included in the portfolio, e.g., "IBM"} - - \item{TxnData}{An xts object containing all required txn - fields} - - \item{\dots}{Any other passthrough parameters} - - \item{verbose}{If TRUE (default) the function prints the - elements of the transaction in a line to the screen, - e.g., "2007-01-08 IBM 50 @ 77.6". Suppress using FALSE.} - - \item{ConMult}{Contract or instrument multiplier for the - Symbol if it is not defined in an instrument - specification} -} -\description{ - Add multiple transactions to a portfolio -} -\note{ - TODO figure out if we can fully vectorize this function - to make it faster -} -\seealso{ - \code{\link{addTxn}}, \code{\link{initPortf}} -} - Modified: pkg/blotter/man/initAcct.Rd =================================================================== --- pkg/blotter/man/initAcct.Rd 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/man/initAcct.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -48,7 +48,7 @@ function. To get to the CFTC thirteen columns add: Gross.Realized, - Commission, Net.Realized, Int.Income, Ch.Unrealized, + Commission, Net.Realized, Interest, Ch.Unrealized, Advisory.Fees, Wealth.Index Again, no need to add Wealth.Index. Eventually, these additional columns will be useful. Gross.Realized will be calculated as (Net) Modified: pkg/blotter/man/initPortf.Rd =================================================================== --- pkg/blotter/man/initPortf.Rd 2013-10-08 14:49:07 UTC (rev 1518) +++ pkg/blotter/man/initPortf.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -32,7 +32,7 @@ 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. + \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 Added: pkg/blotter/man/put.account.Rd =================================================================== --- pkg/blotter/man/put.account.Rd (rev 0) +++ pkg/blotter/man/put.account.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -0,0 +1,18 @@ +\name{put.account} +\alias{put.account} +\title{put a account object in .blotter env} +\usage{ + put.account(account.st, account, envir = .blotter) +} +\arguments{ + \item{account.st}{string identifying account} + + \item{account}{account object} + + \item{envir}{the environment to save the account object + in, defaults to .blotter} +} +\description{ + put a account object in .blotter env +} + Added: pkg/blotter/man/put.portfolio.Rd =================================================================== --- pkg/blotter/man/put.portfolio.Rd (rev 0) +++ pkg/blotter/man/put.portfolio.Rd 2013-10-08 18:12:10 UTC (rev 1519) @@ -0,0 +1,18 @@ +\name{put.portfolio} +\alias{put.portfolio} +\title{put a portfolio object in .blotter env} +\usage{ + put.portfolio(portfolio.st, portfolio, envir = .blotter) +} +\arguments{ + \item{portfolio.st}{string identifying portfolio} + + \item{portfolio}{portfolio object} + + \item{envir}{the environment to save the portfolio object + in, defaults to .blotter} +} +\description{ + put a portfolio object in .blotter env +} + From noreply at r-forge.r-project.org Tue Oct 8 20:55:45 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 8 Oct 2013 20:55:45 +0200 (CEST) Subject: [Blotter-commits] r1520 - pkg/blotter/R Message-ID: <20131008185545.6C5371863AF@r-forge.r-project.org> Author: bodanker Date: 2013-10-08 20:55:45 +0200 (Tue, 08 Oct 2013) New Revision: 1520 Modified: pkg/blotter/R/updatePortf.R Log: - Some speed improvements Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-10-08 18:12:10 UTC (rev 1519) +++ pkg/blotter/R/updatePortf.R 2013-10-08 18:55:45 UTC (rev 1520) @@ -51,10 +51,12 @@ } 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 + Long.Value = { tmat = table + tmat[tmat < 0] <- 0 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 + Short.Value = { tmat = table + tmat[tmat > 0] <- 0 result = xts(rowSums(tmat, na.rm=TRUE), order.by=index(table)) }, Net.Value = { result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) } @@ -94,7 +96,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 <- 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 + startDate = first(Dates)-.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 From noreply at r-forge.r-project.org Wed Oct 9 00:01:26 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 9 Oct 2013 00:01:26 +0200 (CEST) Subject: [Blotter-commits] r1521 - in pkg/blotter: R man Message-ID: <20131008220126.D63D4185CF8@r-forge.r-project.org> Author: bodanker Date: 2013-10-09 00:01:24 +0200 (Wed, 09 Oct 2013) New Revision: 1521 Modified: pkg/blotter/R/addTxn.R pkg/blotter/man/addTxn.Rd Log: - Fix addTxns and add a little documentation Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-10-08 18:55:45 UTC (rev 1520) +++ pkg/blotter/R/addTxn.R 2013-10-08 22:01:24 UTC (rev 1521) @@ -27,6 +27,12 @@ #' mirrors many execution platforms and brokerage #' requirements in particular asset classes where the side #' of a trade needs to be specified with the order. +#' +#' The \code{addTxns} function allows you to add multiple +#' transactions to the portfolio, which is much faster than +#' adding them one at a time. The \code{TxnData} object must +#' have "TxnQty" and "TxnPrice" columns, while the "TxnFees" +#' column is optional. #' #' @param Portfolio A portfolio name that points to a portfolio object structured with \code{initPortf()} #' @param Symbol An instrument identifier for a symbol included in the portfolio, e.g., "IBM" @@ -168,8 +174,8 @@ PrevPosAvgCost <- .getPosAvgCost(pname, Symbol, index(TxnData[row,])) } #TODO create vectorized versions of all these functions so we don't have to loop - TxnQty <- as.numeric(TxnData[row,'Quantity']) - TxnPrice <- as.numeric(TxnData[row,'Price']) + TxnQty <- as.numeric(TxnData[row,'TxnQty']) + TxnPrice <- as.numeric(TxnData[row,'TxnPrice']) # If TxnFees are to be used, it must be a column in TxnData TxnFees <- if (any(grepl("TxnFees", colnames(TxnData)))) { as.numeric(TxnData[row, "TxnFees"]) Modified: pkg/blotter/man/addTxn.Rd =================================================================== --- pkg/blotter/man/addTxn.Rd 2013-10-08 18:55:45 UTC (rev 1520) +++ pkg/blotter/man/addTxn.Rd 2013-10-08 22:01:24 UTC (rev 1521) @@ -74,6 +74,12 @@ mirrors many execution platforms and brokerage requirements in particular asset classes where the side of a trade needs to be specified with the order. + + The \code{addTxns} function allows you to add multiple + transactions to the portfolio, which is much faster than + adding them one at a time. The \code{TxnData} object must + have "TxnQty" and "TxnPrice" columns, while the "TxnFees" + column is optional. } \note{ The addTxn function will eventually also handle other From noreply at r-forge.r-project.org Wed Oct 9 17:54:44 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 9 Oct 2013 17:54:44 +0200 (CEST) Subject: [Blotter-commits] r1522 - in pkg/blotter: . R src Message-ID: <20131009155444.9BC4F185328@r-forge.r-project.org> Author: bodanker Date: 2013-10-09 17:54:44 +0200 (Wed, 09 Oct 2013) New Revision: 1522 Added: pkg/blotter/src/ pkg/blotter/src/calcPosAvgCost.c Modified: pkg/blotter/NAMESPACE pkg/blotter/R/addTxn.R pkg/blotter/R/calcPosAvgCost.R Log: - Vectorized addTxns and created vectorized .calcPosAvgCost_C Modified: pkg/blotter/NAMESPACE =================================================================== --- pkg/blotter/NAMESPACE 2013-10-08 22:01:24 UTC (rev 1521) +++ pkg/blotter/NAMESPACE 2013-10-09 15:54:44 UTC (rev 1522) @@ -1,3 +1,4 @@ +useDynLib(blotter) export(PortfReturns) export(addDiv) export(addPortfInstr) Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-10-08 22:01:24 UTC (rev 1521) +++ pkg/blotter/R/addTxn.R 2013-10-09 15:54:44 UTC (rev 1522) @@ -168,50 +168,36 @@ } } - for (row in 1:nrow(TxnData)) { - if(row==1) { - PrevPosQty <- getPosQty(pname, Symbol, index(TxnData[row,])) - PrevPosAvgCost <- .getPosAvgCost(pname, Symbol, index(TxnData[row,])) - } - #TODO create vectorized versions of all these functions so we don't have to loop - TxnQty <- as.numeric(TxnData[row,'TxnQty']) - TxnPrice <- as.numeric(TxnData[row,'TxnPrice']) - # If TxnFees are to be used, it must be a column in TxnData - TxnFees <- if (any(grepl("TxnFees", colnames(TxnData)))) { - as.numeric(TxnData[row, "TxnFees"]) - } else 0 - #TxnFees <- ifelse( is.function(TxnFees), TxnFees(TxnQty, TxnPrice), TxnFees) - TxnValue <- .calcTxnValue(TxnQty, TxnPrice, TxnFees, ConMult) - TxnAvgCost <- .calcTxnAvgCost(TxnValue, TxnQty, ConMult) - #PrevPosQty <- getPosQty(pname, Symbol, index(TxnData[row,])) - PosQty <- PrevPosQty+TxnQty - PosAvgCost <- .calcPosAvgCost(PrevPosQty, PrevPosAvgCost, 0, PosQty, ConMult) # lag this over the data? - GrossTxnRealizedPL = TxnQty * ConMult * (PrevPosAvgCost - TxnAvgCost) - NetTxnRealizedPL = GrossTxnRealizedPL - TxnFees - PrevPosQty <- PosQty - PrevPosAvgCost <- PosAvgCost - - NewTxn = xts(t(c(TxnQty, - TxnPrice, - TxnValue, - TxnAvgCost, - PosQty, - PosAvgCost, - GrossTxnRealizedPL, - TxnFees, - NetTxnRealizedPL, - ConMult)), - order.by=index(TxnData[row,])) + # initialize new transaction object + NewTxns <- xts(matrix(NA_real_, nrow(TxnData), 10L), index(TxnData)) + colnames(NewTxns) <- c('Txn.Qty', 'Txn.Price', 'Txn.Value', 'Txn.Avg.Cost', 'Pos.Qty', 'Pos.Avg.Cost', 'Gross.Txn.Realized.PL', 'Txn.Fees', 'Net.Txn.Realized.PL', 'Con.Mult') - if(row==1){ - NewTxns <- NewTxn - colnames(NewTxns) = c('Txn.Qty', 'Txn.Price', 'Txn.Value', 'Txn.Avg.Cost', 'Pos.Qty', 'Pos.Avg.Cost', 'Gross.Txn.Realized.PL', 'Txn.Fees', 'Net.Txn.Realized.PL', 'Con.Mult') - } else { - NewTxns<-rbind(NewTxns, NewTxn) - } + NewTxns$Txn.Qty <- as.numeric(TxnData$TxnQty) + NewTxns$Txn.Price <- as.numeric(TxnData$TxnPrice) + if("TxnFees" %in% colnames(TxnData)) { + NewTxns$Txn.Fees <- as.numeric(TxnData$TxnFees) + } else { + NewTxns$Txn.Fees <- 0 } - Portfolio$symbols[[Symbol]]$txn<-rbind(Portfolio$symbols[[Symbol]]$txn,NewTxns) + NewTxns$Txn.Value <- .calcTxnValue(NewTxns$Txn.Qty, NewTxns$Txn.Price, NewTxns$Txn.Fees, ConMult) + NewTxns$Txn.Avg.Cost <- .calcTxnAvgCost(NewTxns$Txn.Value, NewTxns$Txn.Qty, ConMult) + # intermediate objects to aid in vectorization; only first element is non-zero + initPosQty <- initPosAvgCost <- numeric(nrow(TxnData)) + initPosQty[1] <- getPosQty(pname, Symbol, start(TxnData)) + initPosAvgCost[1] <- .getPosAvgCost(pname, Symbol, start(TxnData)) + # cumulative sum of transaction qty + initial position qty + NewTxns$Pos.Qty <- cumsum(initPosQty + NewTxns$Txn.Qty) + # only pass non-zero initial position qty and average cost + NewTxns$Pos.Avg.Cost <- .calcPosAvgCost_C(initPosQty[1], initPosAvgCost[1], NewTxns$Txn.Value, NewTxns$Pos.Qty, ConMult) + # need lagged position average cost + lagPosAvgCost <- c(initPosAvgCost[1], NewTxns$Pos.Avg.Cost[-nrow(NewTxns)]) + NewTxns$Gross.Txn.Realized.PL <- NewTxns$Txn.Qty * ConMult * (lagPosAvgCost - NewTxns$Txn.Avg.Cost) + NewTxns$Net.Txn.Realized.PL <- NewTxns$Gross.Txn.Realized.PL - NewTxns$Txn.Fees + NewTxns$Con.Mult <- ConMult + # update portfolio with new transactions + Portfolio$symbols[[Symbol]]$txn <- rbind(Portfolio$symbols[[Symbol]]$txn, NewTxns) + if(verbose) print(NewTxns) #portfolio is already an environment, it's been updated in place Modified: pkg/blotter/R/calcPosAvgCost.R =================================================================== --- pkg/blotter/R/calcPosAvgCost.R 2013-10-08 22:01:24 UTC (rev 1521) +++ pkg/blotter/R/calcPosAvgCost.R 2013-10-09 15:54:44 UTC (rev 1522) @@ -22,6 +22,9 @@ return(PosAvgCost) } +.calcPosAvgCost_C <- function(PrevPosQty, PrevPosAvgCost, TxnValue, PosQty, ConMult=1) + .Call("calcPosAvgCost", PrevPosQty, PrevPosAvgCost, TxnValue, PosQty, ConMult, PACKAGE="blotter") + ############################################################################### # Blotter: Tools for transaction-oriented trading systems development # for R (see http://r-project.org/) Added: pkg/blotter/src/calcPosAvgCost.c =================================================================== --- pkg/blotter/src/calcPosAvgCost.c (rev 0) +++ pkg/blotter/src/calcPosAvgCost.c 2013-10-09 15:54:44 UTC (rev 1522) @@ -0,0 +1,56 @@ +#include +#include + +SEXP calcPosAvgCost (SEXP PrevPosQty, SEXP PrevPosAvgCost, SEXP TxnValue, SEXP PosQty, SEXP ConMult) +{ + /* "vectorized" version of .calcPosAvgCost for use in addTxns + * Author: Joshua Ulrich + */ + int i, P=0; + if(length(TxnValue) != length(PosQty)) + error("TxnValue and PosQty must be the same length"); + + double d_PrevPosQty = asReal(PrevPosQty); + double d_PrevPosAvgCost = asReal(PrevPosAvgCost); + PROTECT(TxnValue = coerceVector(TxnValue, REALSXP)); P++; + double *d_TxnValue = REAL(TxnValue); + PROTECT(PosQty = coerceVector(PosQty, REALSXP)); P++; + double *d_PosQty = REAL(PosQty); + double d_ConMult = asReal(ConMult); + + int n = length(PosQty); + + SEXP PosAvgCost; + PROTECT(PosAvgCost = allocVector(REALSXP, n)); P++; + double *d_PosAvgCost = REAL(PosAvgCost); + + for(i = 0; i < n; i++) { + if(d_PosQty[i] == 0.0) { + d_PosAvgCost[i] = 0.0; + } else + if(abs(d_PrevPosQty) > abs(d_PosQty[i])){ + /* position is decreasing, pos avg cost for the open position remains the same */ + d_PosAvgCost[i] = d_PrevPosAvgCost; + } else { + if(d_PrevPosAvgCost<0) + d_TxnValue[i]= -1.0 * d_TxnValue[i]; /* fix bug with negative average cost */ + d_PosAvgCost[i] = (d_PrevPosQty * d_PrevPosAvgCost * d_ConMult + d_TxnValue[i])/(d_PosQty[i]*d_ConMult); + } + d_PrevPosQty <- d_PosQty[i]; + d_PrevPosAvgCost <- d_PosAvgCost[i]; + } + UNPROTECT(P); + return(PosAvgCost); +} + +/*############################################################################ +# 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: calcPosAvgCost.c 1051 2012-06-15 15:39:44Z braverock $ +# +#############################################################################*/ From noreply at r-forge.r-project.org Wed Oct 9 22:07:02 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 9 Oct 2013 22:07:02 +0200 (CEST) Subject: [Blotter-commits] r1523 - in pkg/blotter: . R Message-ID: <20131009200702.8DECA1863D6@r-forge.r-project.org> Author: braverock Date: 2013-10-09 22:07:02 +0200 (Wed, 09 Oct 2013) New Revision: 1523 Modified: pkg/blotter/DESCRIPTION pkg/blotter/R/updateAcct.R pkg/blotter/R/updateEndEq.R Log: - roll back r1519, Account is not an environment (yet) Modified: pkg/blotter/DESCRIPTION =================================================================== --- pkg/blotter/DESCRIPTION 2013-10-09 15:54:44 UTC (rev 1522) +++ pkg/blotter/DESCRIPTION 2013-10-09 20:07:02 UTC (rev 1523) @@ -2,7 +2,7 @@ Type: Package Title: Tools for transaction-oriented trading systems development. -Version: 0.8.15 +Version: 0.8.16 Date: $Date$ Author: Peter Carl, Brian G. Peterson Maintainer: Brian G. Peterson Modified: pkg/blotter/R/updateAcct.R =================================================================== --- pkg/blotter/R/updateAcct.R 2013-10-09 15:54:44 UTC (rev 1522) +++ pkg/blotter/R/updateAcct.R 2013-10-09 20:07:02 UTC (rev 1523) @@ -150,7 +150,7 @@ # This function does not calculate End.Eq #account is already an environment, it's been updated in place - #assign(paste("account",name,sep='.'),Account, envir=.blotter) + assign(paste("account",name,sep='.'),Account, envir=.blotter) return(name) #not sure this is a good idea } Modified: pkg/blotter/R/updateEndEq.R =================================================================== --- pkg/blotter/R/updateEndEq.R 2013-10-09 15:54:44 UTC (rev 1522) +++ pkg/blotter/R/updateEndEq.R 2013-10-09 20:07:02 UTC (rev 1523) @@ -35,7 +35,7 @@ Account$summary$End.Eq[Dates] <- EndCapital #account is already an environment, it's been updated in place - #assign(paste("account",aname,sep='.'),Account, envir=.blotter) + assign(paste("account",aname,sep='.'),Account, envir=.blotter) return(aname) #not sure this is a good idea } From noreply at r-forge.r-project.org Fri Oct 11 21:43:26 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 11 Oct 2013 21:43:26 +0200 (CEST) Subject: [Blotter-commits] r1524 - pkg/quantstrat/R Message-ID: <20131011194326.EC6E4184E23@r-forge.r-project.org> Author: bodanker Date: 2013-10-11 21:43:26 +0200 (Fri, 11 Oct 2013) New Revision: 1524 Modified: pkg/quantstrat/R/indicators.R pkg/quantstrat/R/initialize.R pkg/quantstrat/R/rules.R pkg/quantstrat/R/signals.R pkg/quantstrat/R/utils.R pkg/quantstrat/R/wrapup.R Log: - Condense argument matching into a single function Modified: pkg/quantstrat/R/indicators.R =================================================================== --- pkg/quantstrat/R/indicators.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/indicators.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -148,12 +148,6 @@ stop ("You must supply an object of type 'strategy'.") } ret <- NULL - nargs <-list(...) - if(length(nargs)==0) nargs=NULL - if (length('...')==0 | is.null('...')) { - #rm('...') - nargs=NULL - } # First, delete any colums in mktdata that correspond to indicators we're about # to (re)calculate and cbind. @@ -165,14 +159,6 @@ for (indicator in strategy$indicators){ if(!is.function(get(indicator$name))){ if(!is.function(get(paste("sig",indicator$name,sep='.')))){ - # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } - - message(paste("Skipping indicator",indicator$name,"because there is no function by that name to call")) next() } else { @@ -182,36 +168,16 @@ if(!isTRUE(indicator$enabled)) next() - # see 'S Programming p. 67 for this matching - fun<-match.fun(indicator$name) - .formals <- formals(fun) - onames <- names(.formals) + # replace default function arguments with indicator$arguments + .formals <- formals(indicator$name) + .formals <- modify.args(.formals, indicator$arguments, dots=TRUE) + # now add arguments from parameters + .formals <- modify.args(.formals, parameters) + # now add dots + .formals <- modify.args(.formals, list(...)) - pm <- pmatch(names(indicator$arguments), onames, nomatch = 0L) - names(indicator$arguments[pm > 0L]) <- onames[pm] - .formals[pm] <- indicator$arguments[pm > 0L] - if (any(pm == 0L)){ - warning(paste("some arguments stored for",indicator$name,"do not match")) - .formals<-c(.formals,indicator$arguments[pm==0L]) - } - - # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } + tmp_val <- do.call(indicator$name, .formals) - #now add arguments from dots - if (length(nargs)) { - pm <- pmatch(names(nargs), onames, nomatch = 0L) - names(nargs[pm > 0L]) <- onames[pm] - .formals[pm] <- nargs[pm > 0L] - } - .formals$... <- NULL - - tmp_val<-do.call(fun,.formals) - #add label if(is.null(colnames(tmp_val))) colnames(tmp_val) <- seq(ncol(tmp_val)) Modified: pkg/quantstrat/R/initialize.R =================================================================== --- pkg/quantstrat/R/initialize.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/initialize.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -94,36 +94,16 @@ if(!isTRUE(init_o$enabled)) next() - # see 'S Programming p. 67 for this matching - fun<-match.fun(init_o$name) - - .formals <- formals(fun) - onames <- names(.formals) - - pm <- pmatch(names(init_o$arguments), onames, nomatch = 0L) - #if (any(pm == 0L)) - # warning(paste("some arguments stored for",init_o$name,"do not match")) - names(init_o$arguments[pm > 0L]) <- onames[pm] - .formals[pm] <- init_o$arguments[pm > 0L] - + # replace default function arguments with init_o$arguments + .formals <- formals(init_o$name) + .formals <- modify.args(.formals, init_o$arguments, dots=TRUE) # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } + .formals <- modify.args(.formals, parameters) + # now add dots + .formals <- modify.args(.formals, list(...)) - #now add dots - dargs<-list(...) - if (length(dargs)) { - pm <- pmatch(names(dargs), onames, nomatch = 0L) - names(dargs[pm > 0L]) <- onames[pm] - .formals[pm] <- dargs[pm > 0L] - } - .formals$... <- NULL - - do.call(fun,.formals) - } + do.call(init_o$name, .formals) + } } #' add arbitrary initialization functions to a strategy Modified: pkg/quantstrat/R/rules.R =================================================================== --- pkg/quantstrat/R/rules.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/rules.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -281,12 +281,6 @@ stop ("You must supply an object of type 'strategy'.") } ret <- NULL - nargs <-list(...) - if(length(nargs)==0) nargs=NULL - if (length('...')==0 | is.null('...')) { - rm('...') - nargs=NULL - } Dates=unique(index(mktdata)) @@ -691,47 +685,23 @@ # check to see if we should run in this timespan if(!is.null(rule$timespan) && nrow(mktdata[timestamp][rule$timespan])==0) next() - # see 'S Programming' p. 67 for this matching - if(is.function(rule$name)) fun <- rule$name - else fun<-match.fun(rule$name) - - nargs <-list(...) - if(length(nargs)==0) nargs=NULL - if (length('...')==0 | is.null('...')) { - rm('...') - nargs=NULL - } - - .formals <- formals(fun) - - onames <- names(.formals) + # modify a few things rule$arguments$timestamp = timestamp rule$arguments$ruletype = ruletype rule$arguments$label = rule$label - pm <- pmatch(names(rule$arguments), onames, nomatch = 0L) - # if (any(pm == 0L)) message(paste("some arguments stored for",rule$name,"do not match")) - names(rule$arguments[pm > 0L]) <- onames[pm] - .formals[pm] <- rule$arguments[pm > 0L] - + + # replace default function arguments with rule$arguments + .formals <- formals(rule$name) + .formals <- modify.args(.formals, rule$arguments, dots=TRUE) # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } + .formals <- modify.args(.formals, parameters) + # now add dots + .formals <- modify.args(.formals, list(...)) - #now add dots - if (length(nargs)) { - pm <- pmatch(names(nargs), onames, nomatch = 0L) - names(nargs[pm > 0L]) <- onames[pm] - .formals[pm] <- nargs[pm > 0L] - } - .formals$... <- NULL - # any rule-specific prefer-parameters should override global prefer parameter if(!is.null(rule$arguments$prefer)) .formals$prefer = rule$arguments$prefer - tmp_val<-do.call(fun,.formals) + tmp_val <- do.call(rule$name, .formals) # print(paste('tmp_val ==', tmp_val)) } #end rules loop Modified: pkg/quantstrat/R/signals.R =================================================================== --- pkg/quantstrat/R/signals.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/signals.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -84,12 +84,6 @@ stop ("You must supply an object of type 'strategy'.") } ret <- NULL - nargs <-list(...) - if(length(nargs)==0) nargs=NULL - if (length('...')==0 | is.null('...')) { - rm('...') - nargs=NULL - } for (signal in strategy$signals){ #TODO check to see if they've already been calculated @@ -105,35 +99,16 @@ if(!isTRUE(signal$enabled)) next() - # see 'S Programming p. 67 for this matching - fun<-match.fun(signal$name) + # replace default function arguments with signal$arguments + .formals <- formals(signal$name) + .formals <- modify.args(.formals, signal$arguments, dots=TRUE) + # now add arguments from parameters + .formals <- modify.args(.formals, parameters) + # now add dots + .formals <- modify.args(.formals, list(...)) - .formals <- formals(fun) - onames <- names(.formals) - - pm <- pmatch(names(signal$arguments), onames, nomatch = 0L) - #if (any(pm == 0L)) - # warning(paste("some arguments stored for",signal$name,"do not match")) - names(signal$arguments[pm > 0L]) <- onames[pm] - .formals[pm] <- signal$arguments[pm > 0L] + tmp_val <- do.call(signal$name, .formals) - # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } - - #now add dots - if (length(nargs)) { - pm <- pmatch(names(nargs), onames, nomatch = 0L) - names(nargs[pm > 0L]) <- onames[pm] - .formals[pm] <- nargs[pm > 0L] - } - .formals$... <- NULL - - tmp_val<-do.call(fun,.formals) - #add label if(is.null(colnames(tmp_val))) colnames(tmp_val) <- seq(ncol(tmp_val)) Modified: pkg/quantstrat/R/utils.R =================================================================== --- pkg/quantstrat/R/utils.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/utils.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -52,3 +52,47 @@ } } +modify.args <- function(formals, arglist, dots=FALSE) +{ + # see 'S Programming' p. 67 for this matching + + # nothing to do if arglist is empty; return formals + if(!length(arglist)) + return(formals) + + argnames <- names(arglist) + if(!is.list(arglist) && !is.null(argnames) && !any(argnames == "")) + stop("'arglist' must be a *named* list, with no names == \"\"") + + .formals <- formals + onames <- names(.formals) + + pm <- pmatch(argnames, onames, nomatch = 0L) + #if(any(pm == 0L)) + # message(paste("some arguments stored for", fun, "do not match")) + names(arglist[pm > 0L]) <- onames[pm] + .formals[pm] <- arglist[pm > 0L] + + # include all elements from arglist if function formals contain '...' + if(dots && !is.null(.formals$...)) { + dotnames <- names(arglist[pm == 0L]) + .formals[dotnames] <- arglist[dotnames] + .formals$... <- NULL + } + + .formals +} + +############################################################################### +# R (http://r-project.org/) Quantitative Strategy Model Framework +# +# Copyright (c) 2009-2012 +# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, +# Jeffrey Ryan, Joshua Ulrich, and Garrett See +# +# This library is distributed under the terms of the GNU Public License (GPL) +# for full details see the file COPYING +# +# $Id: rules.R 1452 2013-05-04 22:39:39Z opentrades $ +# +############################################################################### Modified: pkg/quantstrat/R/wrapup.R =================================================================== --- pkg/quantstrat/R/wrapup.R 2013-10-09 20:07:02 UTC (rev 1523) +++ pkg/quantstrat/R/wrapup.R 2013-10-11 19:43:26 UTC (rev 1524) @@ -109,35 +109,15 @@ if(!isTRUE(wrapup_o$enabled)) next() - # see 'S Programming p. 67 for this matching - fun<-match.fun(wrapup_o$name) - - .formals <- formals(fun) - onames <- names(.formals) - - pm <- pmatch(names(wrapup_o$arguments), onames, nomatch = 0L) - #if (any(pm == 0L)) - # warning(paste("some arguments stored for",wrapup_o$name,"do not match")) - names(wrapup_o$arguments[pm > 0L]) <- onames[pm] - .formals[pm] <- wrapup_o$arguments[pm > 0L] - + # replace default function arguments wrapup_o$arguments + .formals <- formals(wrapup_o$name) + .formals <- modify.args(.formals, wrapup_o$arguments, dots=TRUE) # now add arguments from parameters - if(length(parameters)){ - pm <- pmatch(names(parameters), onames, nomatch = 0L) - names(parameters[pm > 0L]) <- onames[pm] - .formals[pm] <- parameters[pm > 0L] - } + .formals <- modify.args(.formals, parameters) + # now add dots + .formals <- modify.args(.formals, list(...)) - #now add dots - dargs<-list(...) - if (length(dargs)) { - pm <- pmatch(names(dargs), onames, nomatch = 0L) - names(dargs[pm > 0L]) <- onames[pm] - .formals[pm] <- dargs[pm > 0L] - } - .formals$... <- NULL - - out[[wrapup_o$name]]<-do.call(fun,.formals) + out[[wrapup_o$name]] <- do.call(wrapup_o$name, .formals) } } From noreply at r-forge.r-project.org Mon Oct 14 18:02:08 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Oct 2013 18:02:08 +0200 (CEST) Subject: [Blotter-commits] r1525 - in pkg/blotter: . R man Message-ID: <20131014160209.04059185475@r-forge.r-project.org> Author: braverock Date: 2013-10-14 18:02:08 +0200 (Mon, 14 Oct 2013) New Revision: 1525 Modified: pkg/blotter/DESCRIPTION pkg/blotter/NAMESPACE pkg/blotter/R/AcctReturns.R pkg/blotter/R/PortfReturns.R pkg/blotter/R/addAcctTxn.R pkg/blotter/R/addPortfInstr.R pkg/blotter/R/addTxn.R pkg/blotter/R/calcPortfWgt.R pkg/blotter/R/calcPosAvgCost.R pkg/blotter/R/calcTxnAvgCost.R pkg/blotter/R/calcTxnValue.R pkg/blotter/R/chart.ME.R pkg/blotter/R/chart.Posn.R pkg/blotter/R/chart.Reconcile.R pkg/blotter/R/chart.Spread.R pkg/blotter/R/extractTests.R pkg/blotter/R/getAccount.R pkg/blotter/R/getByPortf.R pkg/blotter/R/getBySymbol.R pkg/blotter/R/getEndEq.R pkg/blotter/R/getPortfAcct.R pkg/blotter/R/getPortfolio.R pkg/blotter/R/getPos.R pkg/blotter/R/getPosAvgCost.R pkg/blotter/R/getPosQty.R pkg/blotter/R/getTxn.R pkg/blotter/R/initAcct.R pkg/blotter/R/initPortf.R pkg/blotter/R/initPosPL.R pkg/blotter/R/initSummary.R pkg/blotter/R/initTxn.R pkg/blotter/R/perTradeStats.R pkg/blotter/R/put.account.R pkg/blotter/R/put.portfolio.R pkg/blotter/R/tradeStats.R pkg/blotter/R/updateAcct.R pkg/blotter/R/updateEndEq.R pkg/blotter/R/updatePortf.R pkg/blotter/R/updatePosPL.R pkg/blotter/man/getPortfolio.Rd Log: - split getPortfolio into public and internal functions to avoid accidental environment damage - update svn propset on .R files for Date Author Id tags Modified: pkg/blotter/DESCRIPTION =================================================================== --- pkg/blotter/DESCRIPTION 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/DESCRIPTION 2013-10-14 16:02:08 UTC (rev 1525) @@ -2,7 +2,7 @@ Type: Package Title: Tools for transaction-oriented trading systems development. -Version: 0.8.16 +Version: 0.8.17 Date: $Date$ Author: Peter Carl, Brian G. Peterson Maintainer: Brian G. Peterson @@ -10,7 +10,7 @@ instruments, transactions, portfolios and accounts for trading systems and simulation. Provides portfolio support for multi-asset class and multi-currency - portfolios. Still in development. + portfolios. Actively maintained and developed. License: GPL LazyLoad: yes Depends: Modified: pkg/blotter/NAMESPACE =================================================================== --- pkg/blotter/NAMESPACE 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/NAMESPACE 2013-10-14 16:02:08 UTC (rev 1525) @@ -1,9 +1,11 @@ -useDynLib(blotter) +export(.getPortfolio) +export(AcctReturns) export(PortfReturns) +export(addAcctTxn) export(addDiv) export(addPortfInstr) export(addTxn) -export(addAcctTxn) +export(addTxns) export(calcPortfWgt) export(chart.ME) export(chart.Posn) Property changes on: pkg/blotter/R/AcctReturns.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Property changes on: pkg/blotter/R/PortfReturns.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Property changes on: pkg/blotter/R/addAcctTxn.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Modified: pkg/blotter/R/addPortfInstr.R =================================================================== --- pkg/blotter/R/addPortfInstr.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/addPortfInstr.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -8,19 +8,17 @@ #' @export addPortfInstr <- function(Portfolio,symbols,...) { - pname<-Portfolio - portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) - if(inherits(Portfolio,"try-error")) - stop(paste("Portfolio",pname," not found, use initPortf() to create a new portfolio")) - initDate <- attr(portfolio, "initDate") - currency <- attr(portfolio, "currency") - for(instrument in symbols){ - portfolio$symbols[[instrument]]$txn = .initTxn(initDate = initDate, initPosQty = 0) - portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = 0) - portfolio$symbols[[instrument]][[paste('posPL',currency,sep='.')]] = portfolio$symbols[[instrument]]$posPL - } - #portfolio is already an environment, it's been updated in place - #assign(paste("portfolio",as.character(pname),sep='.'),portfolio,envir=.blotter) + pname<-Portfolio + portfolio<-getPortfolio(pname) + initDate <- attr(portfolio, "initDate") + currency <- attr(portfolio, "currency") + for(instrument in symbols){ + portfolio$symbols[[instrument]]$txn = .initTxn(initDate = initDate, initPosQty = 0) + portfolio$symbols[[instrument]]$posPL = .initPosPL(initDate = initDate, initPosQty = 0) + portfolio$symbols[[instrument]][[paste('posPL',currency,sep='.')]] = portfolio$symbols[[instrument]]$posPL + } + #portfolio is already an environment, it's been updated in place + #assign(paste("portfolio",as.character(pname),sep='.'),portfolio,envir=.blotter) } ############################################################################### Property changes on: pkg/blotter/R/addPortfInstr.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/addTxn.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -53,7 +53,8 @@ #' TODO figure out if we can fully vectorize the addTxns function to make it faster #' @seealso \code{\link{addTxns}}, \code{\link{pennyPerShare}}, \code{\link{initPortf}} #' @author Peter Carl, Brian G. Peterson -#' @export +#' @export addTxn +#' @export addTxns addTxn <- function(Portfolio, Symbol, TxnDate, TxnQty, TxnPrice, ..., TxnFees=0, ConMult=NULL, verbose=TRUE, eps=1e-06) { Property changes on: pkg/blotter/R/addTxn.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/calcPortfWgt.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/calcPosAvgCost.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/calcTxnAvgCost.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/calcTxnValue.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/chart.ME.R ___________________________________________________________________ Modified: svn:keywords - Id Author Date + Date Author Id Property changes on: pkg/blotter/R/chart.Posn.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Modified: pkg/blotter/R/chart.Reconcile.R =================================================================== --- pkg/blotter/R/chart.Reconcile.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/chart.Reconcile.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -167,6 +167,6 @@ # This library is distributed under the terms of the GNU Public License (GPL) # for full details see the file COPYING # -# $Id: chart.Posn.R 531 2011-01-14 16:42:23Z llevenson $ +# $Id$ # ############################################################################### Property changes on: pkg/blotter/R/chart.Reconcile.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Property changes on: pkg/blotter/R/chart.Spread.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Property changes on: pkg/blotter/R/extractTests.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Property changes on: pkg/blotter/R/getAccount.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Property changes on: pkg/blotter/R/getByPortf.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getBySymbol.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getEndEq.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getPortfAcct.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Modified: pkg/blotter/R/getPortfolio.R =================================================================== --- pkg/blotter/R/getPortfolio.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/getPortfolio.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -1,22 +1,49 @@ #' get a portfolio object +#' +#' Get a portfolio object conssting of either a nested list (\code{getPortfolio}) +#' or a pointer to the portfolio in the \code{.blotter} environment (\code{.getPortfolio}) +#' +#' Portfolios in blotter are stored as a set of nested, hashed, environments. +#' +#' The \code{getPortfolio} function returns a nested list. If you are unsure, use this function. +#' +#' The \code{.getPortfolio} function returns a pointer to the actual environment. +#' Environments in R are passed by reference, and are not copied by the \code{<-} +#' assignment operator. Any changes made to the environment returned by +#' \code{.getPortfolio} are global. You have been warned. +#' #' @param Portfolio string identifying portfolio #' @param Dates dates subset, not yet supported #' @param envir the environment to retrieve the portfolio from, defaults to .blotter -#' @export -getPortfolio <- function(Portfolio, Dates=NULL, envir=.blotter) #should symbol subsets be supported too? probably not. +#' +#' @seealso \code{\link{initPortf}}, \code{\link{updatePortf}} +#' @export getPortfolio +#' @export .getPortfolio +getPortfolio <- function(Portfolio, Dates=NULL, envir=.blotter) +{ + pname<-Portfolio + oport<- .getPortfolio(Portfolio, envir=envir) + port <- as.list.environment(oport) + port$symbols<-list() + port$symbols <- lapply(oport$symbols, as.list.environment) + + if(!is.null(Dates)){ + message("date subsetting not yet supported") + #TODO add date subsetting in getPortfolio + } + + return(port) +} + +#' @rdname getPortfolio +.getPortfolio <- function(Portfolio, envir=.blotter) { # @author Brian Peterson pname<-Portfolio if(!grepl("portfolio\\.",pname)) Portfolio<-suppressWarnings(try(get(paste("portfolio",pname,sep='.'),envir=envir),silent=TRUE)) else Portfolio<-suppressWarnings(try(get(pname,envir=envir),silent=TRUE)) if(inherits(Portfolio,"try-error")) stop(paste("Portfolio",pname," not found, use initPortf() to create a new portfolio")) - if(!inherits(Portfolio,"portfolio")) stop("Portfolio",pname,"passed is not the name of a portfolio object.") - - if(!is.null(Dates)){ - message("date subsetting not yet supported") - #TODO add date subsetting in getPortfolio - } - + if(!inherits(Portfolio,"portfolio")) stop("Portfolio",pname,"passed is not the name of a portfolio object.") return(Portfolio) } Property changes on: pkg/blotter/R/getPortfolio.R ___________________________________________________________________ Modified: svn:keywords - Revision Id Date Author + Date Author Id Modified: pkg/blotter/R/getPos.R =================================================================== --- pkg/blotter/R/getPos.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/getPos.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -10,7 +10,7 @@ #' @export getPos <- function(Portfolio, Symbol, Date, Columns=c('Pos.Qty','Pos.Avg.Cost'),n=1) { # @author Peter Carl - Portfolio<-getPortfolio(Portfolio) + Portfolio<-.getPortfolio(Portfolio) # FUNCTION PosData = Portfolio$symbols[[Symbol]]$txn #toDate = paste('::', Date, sep="") Property changes on: pkg/blotter/R/getPos.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getPosAvgCost.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getPosQty.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/getTxn.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/initAcct.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/initPortf.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/initPosPL.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Modified: pkg/blotter/R/initSummary.R =================================================================== --- pkg/blotter/R/initSummary.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/initSummary.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -18,6 +18,6 @@ # This library is distributed under the terms of the GNU Public License (GPL) # for full details see the file COPYING # -# $Id: initTxn.R 306 2010-03-26 21:19:51Z peter_carl $ +# $Id$ # ############################################################################### Property changes on: pkg/blotter/R/initSummary.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Property changes on: pkg/blotter/R/initTxn.R ___________________________________________________________________ Modified: svn:keywords - Id Revision Date Author + Date Author Id Property changes on: pkg/blotter/R/perTradeStats.R ___________________________________________________________________ Modified: svn:keywords - Id Author Date + Date Author Id Modified: pkg/blotter/R/put.account.R =================================================================== --- pkg/blotter/R/put.account.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/put.account.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -19,6 +19,6 @@ # This library is distributed under the terms of the GNU Public License (GPL) # for full details see the file COPYING # -# $Id: getPortfolio.R 742 2011-08-25 21:12:43Z braverock $ +# $Id$ # ############################################################################### Property changes on: pkg/blotter/R/put.account.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Modified: pkg/blotter/R/put.portfolio.R =================================================================== --- pkg/blotter/R/put.portfolio.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/put.portfolio.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -19,6 +19,6 @@ # This library is distributed under the terms of the GNU Public License (GPL) # for full details see the file COPYING # -# $Id: getPortfolio.R 742 2011-08-25 21:12:43Z braverock $ +# $Id$ # ############################################################################### Property changes on: pkg/blotter/R/put.portfolio.R ___________________________________________________________________ Added: svn:keywords + Date Author Id Modified: pkg/blotter/R/tradeStats.R =================================================================== --- pkg/blotter/R/tradeStats.R 2013-10-11 19:43:26 UTC (rev 1524) +++ pkg/blotter/R/tradeStats.R 2013-10-14 16:02:08 UTC (rev 1525) @@ -1,442 +1,432 @@ - -#' calculate statistics on transactions and P&L for a symbol or symbols in a portfolio or portfolios -#' -#' This function calculates trade-level statistics on a symbol or symbols within a portfolio or portfolios. -#' -#' Every book on trading, broker report on an analytical trading system, -#' or blog post seems to have a slightly different idea of what trade statistics -#' are necessary, and how they should be displayed. We choose not to make -#' value judgments of this type, aiming rather for inclusiveness with -#' post-processing for display. -#' -#' The output of this function is a \code{\link{data.frame}} with named columns for each statistic. -#' Each row is a single portfolio+symbol combination. Values are returned in full precision. -#' It is likely that the output of this function will have more than you wish -#' to display in all conditions, but it should be suitable for reshaping for display. -#' Building summary reports from this data.frame may be easily accomplished using -#' something like \code{textplot} or \code{\link{data.frame}}, with rounding, -#' fancy formatting, etc. as your needs dictate. -#' -#' If you have additional trade statistics you want added here, please share. -#' We find it unlikely that any transaction-level statistics that can be -#' calculated independently of strategy rules could be considered proprietary. -#' -#' Special Thanks for contributions to this function from: -#' \describe{ -#' \item{Josh Ulrich}{ for adding multiple-portfolio support, fixing bugs, and improving readability of the code } -#' \item{Klemen Koselj}{ for median stats, num trades, and win/loss ratios } -#' \item{Mark Knecht}{ for suggesting Profit Factor and largest winner/largest loser } -#' } -#' -#' WARNING: we're not sure this function is stable/complete yet. If you're using it, please give us feedback! -#' -#' @aliases dailyStats -#' @seealso \code{\link{chart.ME}} for a chart of MAE and MFE derived from trades, -#' and \code{\link{perTradeStats}} for detailed statistics on a per-trade basis -#' @param Portfolios portfolio string -#' @param Symbols character vector of symbol strings, default NULL -#' @param use for determines whether numbers are calculated from transactions or round-trip trades (for tradeStats) or equity curve (for dailyStats) -#' @author Lance Levenson, Brian Peterson -#' @export -#' @importFrom zoo as.Date -#' @return -#' a \code{data.frame} containing: -#' -#' \describe{ -#' \item{Portfolio}{ name of the portfolio} -#' \item{Symbol}{ symbol name } -#' \item{Num.Txns}{ number of transactions produced by \code{\link{addTxn}} } -#' \item{Num.Trades}{ number of \emph{flat to flat} trades performed } -#' \item{Net.Trading.PL}{ } -#' \item{Avg.Trade.PL}{ mean trading P&L per trade } -#' \item{Med.Trade.PL}{ median trading P&L per trade} -#' \item{Largest.Winner}{ largest winning trade } -#' \item{Largest.Loser}{ largest losing trade } -#' \item{Gross.Profits}{ gross (pre-fee) trade profits } -#' \item{Gross.Losses}{ gross trade losses } -#' \item{Std.Dev.Trade.PL}{ standard deviation of trade P&L } -#' \item{Percent.Positive}{ percent of trades that end positive } -#' \item{Percent.Negative}{ percent of trades that end negative } -#' \item{Profit.Factor}{ absolute value ration of gross profits over gross losses } -#' \item{Avg.Win.Trade}{ mean P&L of profitabloe trades } -#' \item{Med.Win.Trade}{ median P&L of profitable trades } -#' \item{Avg.Losing.Trade}{ mean P&L of losing trades } -#' \item{Med.Losing.Trade}{ median P&L of losing trades } -#' \item{Avg.Daily.PL}{mean daily realized P&L on days there were transactions, see \code{\link{dailyStats}} for all days } -#' \item{Med.Daily.PL}{ median daily P&L } -#' \item{Std.Dev.Daily.PL}{ standard deviation of daily P&L } -#' \item{Max.Drawdown}{ max drawdown } -#' \item{Avg.WinLoss.Ratio}{ ratio of mean winning over mean losing trade } -#' \item{Med.WinLoss.Ratio}{ ratio of median winning trade over mean losing trade } -#' \item{Max.Equity}{ maximum account equity } -#' \item{Min.Equity}{ minimum account equity } -#' } -#' @note -#' TODO document each statistic included in this function, with equations -#' -#' TODO add more stats, potentially -#' PerformanceAnalytics: skewness, kurtosis, upside/downside semidieviation, Sharpe/Sortino -#' -#' mean absolute deviation stats -#' -#' more Tharpe/Kestner/Tradestation stats, e.g. -#' K-factor -#' RINA Index -#' Percent time in the market -#' Buy and hold return -#' -#' Josh has suggested adding \%-return based stats too -tradeStats <- function(Portfolios, Symbols,use=c('txns','trades')) -{ - ret <- NULL - use <- use[1] #use the first(default) value only if user hasn't specified - for (Portfolio in Portfolios){ - ## Error Handling Borrowed from getPortfolio - pname <- Portfolio - if (!grepl("portfolio\\.", pname)) - Portfolio <- try(get(paste("portfolio", pname, sep = "."), envir = .blotter), silent=TRUE) - else Portfolio <- try(get(pname, envir = .blotter), silent=TRUE) - if (inherits(Portfolio, "try-error")) - stop(paste("Portfolio", pname, " not found, use initPortf() to create a new portfolio")) - if (!inherits(Portfolio, "portfolio")) - stop("Portfolio", pname, "passed is not the name of a portfolio object.") - - - - ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- ls(Portfolio$symbols) - else symbols <- Symbols - - ## Trade Statistics - for (symbol in symbols){ - txn <- Portfolio$symbols[[symbol]]$txn - posPL <- Portfolio$symbols[[symbol]]$posPL - posPL <- posPL[-1,] - - PL.gt0 <- txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL > 0] - PL.lt0 <- txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL < 0] - PL.ne0 <- txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL != 0] - - if(length(PL.ne0) == 0) - { - # apply.daily will crash - next - } - - DailyPL <- apply.daily(PL.ne0,sum) - AvgDailyPL <- mean(DailyPL) - MedDailyPL <- median(DailyPL) - StdDailyPL <- sd(as.numeric(as.vector(DailyPL))) - - switch(use, - txns = { - #moved above for daily stats for now - }, - trades = { - trades <- perTradeStats(pname,symbol) - PL.gt0 <- trades$Net.Trading.PL[trades$Net.Trading.PL > 0] - PL.lt0 <- trades$Net.Trading.PL[trades$Net.Trading.PL < 0] - PL.ne0 <- trades$Net.Trading.PL[trades$Net.Trading.PL != 0] - } - ) - if(!length(PL.ne0)>0)next() - - GrossProfits <- sum(PL.gt0) - GrossLosses <- sum(PL.lt0) - ProfitFactor <- abs(GrossProfits/GrossLosses) - - AvgTradePL <- mean(PL.ne0) - MedTradePL <- median(PL.ne0) - StdTradePL <- sd(as.numeric(as.vector(PL.ne0))) - - NumberOfTxns <- nrow(txn)-1 - NumberOfTrades <- length(PL.ne0) - - PercentPositive <- (length(PL.gt0)/length(PL.ne0))*100 - PercentNegative <- (length(PL.lt0)/length(PL.ne0))*100 - - MaxWin <- max(txn$Net.Txn.Realized.PL) - MaxLoss <- min(txn$Net.Txn.Realized.PL) - - AvgWinTrade <- mean(PL.gt0) - MedWinTrade <- median(PL.gt0) - AvgLossTrade <- mean(PL.lt0) - MedLossTrade <- median(PL.lt0) - - AvgWinLoss <- AvgWinTrade/-AvgLossTrade - MedWinLoss <- MedWinTrade/-MedLossTrade - - Equity <- cumsum(posPL$Net.Trading.PL) - if(!nrow(Equity)){ - warning('No Equity rows for',symbol) - next() - } - TotalNetProfit <- last(Equity) - if(is.na(TotalNetProfit)) { - warning('TotalNetProfit NA for',symbol) - next() - } - Equity.max <- cummax(Equity) - MaxEquity <- max(Equity) - MinEquity <- min(Equity) - EndEquity <- last(Equity) - names(EndEquity) <-'End.Equity' - if(EndEquity!=TotalNetProfit && last(txn$Pos.Qty)==0) { - warning('Total Net Profit for',symbol,'from transactions',TotalNetProfit,'and cumulative P&L from the Equity Curve', EndEquity, 'do not match. This can happen in long/short portfolios.') - message('Total Net Profit for',symbol,'from transactions',TotalNetProfit,'and cumulative P&L from the Equity Curve', EndEquity, 'do not match. This can happen in long/short portfolios.') - - }# if we're flat, these numbers should agree - #TODO we should back out position value if we've got an open position and double check here.... - - MaxDrawdown <- -max(Equity.max - Equity) - ProfitToMaxDraw <- -TotalNetProfit / MaxDrawdown - names(ProfitToMaxDraw) <- 'Profit.To.Max.Draw' - - #TODO add skewness, kurtosis, and positive/negative semideviation if PerfA is available. - - tmpret <- data.frame(Portfolio=pname, - Symbol = symbol, - Num.Txns = NumberOfTxns, - Num.Trades = NumberOfTrades, - Total.Net.Profit = TotalNetProfit, - Avg.Trade.PL = AvgTradePL, - Med.Trade.PL = MedTradePL, - Largest.Winner = MaxWin, - Largest.Loser = MaxLoss, - Gross.Profits = GrossProfits, - Gross.Losses = GrossLosses, - Std.Dev.Trade.PL = StdTradePL, - Percent.Positive = PercentPositive, - Percent.Negative = PercentNegative, - Profit.Factor = ProfitFactor, - Avg.Win.Trade = AvgWinTrade, - Med.Win.Trade = MedWinTrade, - Avg.Losing.Trade = AvgLossTrade, - Med.Losing.Trade = MedLossTrade, - Avg.Daily.PL = AvgDailyPL, - Med.Daily.PL = MedDailyPL, - Std.Dev.Daily.PL = StdDailyPL, - Max.Drawdown = MaxDrawdown, - Profit.To.Max.Draw = ProfitToMaxDraw, - Avg.WinLoss.Ratio = AvgWinLoss, - Med.WinLoss.Ratio = MedWinLoss, - Max.Equity = MaxEquity, - Min.Equity = MinEquity, - End.Equity = EndEquity) - rownames(tmpret) <- symbol - ret <- rbind(ret,tmpret) - } # end symbol loop - } # end portfolio loop - return(ret) -} - -#' generate daily Transaction Realized or Equity Curve P&L by instrument -#' -#' designed to collate information for high frequency portfolios -#' -#' @aliases dailyEqPL -#' @param Portfolios portfolio string -#' @param Symbols character vector of symbol strings -#' @param drop.time remove time component of POSIX datestamp (if any), default TRUE -#' @author Brian G. Peterson -#' @seealso tradeStats -#' @export -dailyTxnPL <- function(Portfolios, Symbols, drop.time=TRUE) -{ - ret <- NULL - for (Portfolio in Portfolios){ - ## Error Handling Borrowed from getPortfolio - pname <- Portfolio - if (!grepl("portfolio\\.", pname)) - Portfolio <- try(get(paste("portfolio", pname, sep = "."), envir = .blotter), silent=TRUE) - else Portfolio <- try(get(pname, envir = .blotter), silent=TRUE) - if (inherits(Portfolio, "try-error")) - stop(paste("Portfolio", pname, " not found, use initPortf() to create a new portfolio")) - if (!inherits(Portfolio, "portfolio")) - stop("Portfolio", pname, "passed is not the name of a portfolio object.") - - - - ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- ls(Portfolio$symbols) - else symbols <- Symbols - - ## Trade Statistics - for (symbol in symbols){ - txn <- Portfolio$symbols[[symbol]]$txn - txn <- txn[-1,] # remove initialization row - - PL.ne0 <- txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL != 0] - if(!nrow(PL.ne0)){ - warning('No P&L rows for',symbol) - next() - } - DailyPL <- apply.daily(PL.ne0,sum) - colnames(DailyPL) <- paste(symbol,'DailyTxnPL',sep='.') - if(is.null(ret)) ret=DailyPL else ret<-cbind(ret,DailyPL) - - } # end symbol loop - } # end portfolio loop - ret <- apply.daily(ret,colSums,na.rm=TRUE) - if(drop.time) index(ret) <- as.Date(index(ret)) - return(ret) -} - -#' @rdname dailyTxnPL -#' @export -dailyEqPL <- function(Portfolios, Symbols, drop.time=TRUE) -{ - ret <- NULL - for (Portfolio in Portfolios){ - ## Error Handling Borrowed from getPortfolio - pname <- Portfolio - if (!grepl("portfolio\\.", pname)) - Portfolio <- try(get(paste("portfolio", pname, sep = "."), envir = .blotter), silent=TRUE) - else Portfolio <- try(get(pname, envir = .blotter), silent=TRUE) - if (inherits(Portfolio, "try-error")) - stop(paste("Portfolio", pname, " not found, use initPortf() to create a new portfolio")) - if (!inherits(Portfolio, "portfolio")) - stop("Portfolio", pname, "passed is not the name of a portfolio object.") - - - - ## FIXME: need a way to define symbols for each portfolio - if(missing(Symbols)) symbols <- ls(Portfolio$symbols) - else symbols <- Symbols - - ## Trade Statistics - for (symbol in symbols){ - posPL <- Portfolio$symbols[[symbol]]$posPL - posPL <- posPL[-1,] # remove initialization row - - Equity <- cumsum(posPL$Net.Trading.PL) - if(!nrow(Equity)){ - warning('No P&L rows for',symbol) - next() - } - - #DailyPL <- apply.daily(Equity,last) - DailyPL <- apply.daily(posPL$Net.Trading.PL,colSums) - colnames(DailyPL) <- paste(symbol,'DailyEndEq',sep='.') - if(is.null(ret)) ret=DailyPL else ret<-cbind(ret,DailyPL) - - } # end symbol loop - } # end portfolio loop - ret <- apply.daily(ret,colSums,na.rm=TRUE) - if(drop.time) index(ret) <- as.Date(index(ret)) - return(ret) -} - -#' @rdname tradeStats -#' @export -dailyStats <- function(Portfolios,use=c('equity','txns')) -{ - use=use[1] #take the first value if the user didn't specify - switch (use, - Eq = , Equity =, cumPL = { - dailyPL <- dailyEqPL(Portfolios) - }, - Txns =, Trades = { - dailyPL <- dailyTxnPL(Portfolios) - } - ) - - dailyFUN <- function (x){ - x<-t(t(x)) - PL.gt0 <- x[x > 0] - PL.lt0 <- x[x < 0] - PL.ne0 <- x[x != 0] - - TotalNetProfit <- sum(x) - - GrossProfits <- sum(PL.gt0) - GrossLosses <- sum(PL.lt0) - ProfitFactor <- abs(GrossProfits/GrossLosses) - - AvgDayPL <- as.numeric(mean(PL.ne0)) - MedDayPL <- as.numeric(median(PL.ne0)) - StdDayPL <- as.numeric(sd(PL.ne0)) - - #NumberOfDays <- nrow(txn) - WinDays <- length(PL.gt0) - LossDays <- length(PL.lt0) - PercentPositive <- (length(PL.gt0)/length(PL.ne0))*100 - PercentNegative <- (length(PL.lt0)/length(PL.ne0))*100 - - MaxWin <- max(x) - MaxLoss <- min(x) - - AvgWinDay <- as.numeric(mean(PL.gt0)) - MedWinDay <- as.numeric(median(PL.gt0)) - AvgLossDay <- as.numeric(mean(PL.lt0)) - MedLossDay <- as.numeric(median(PL.lt0)) - - AvgWinLoss <- AvgWinDay/-AvgLossDay - MedWinLoss <- MedWinDay/-MedLossDay - - AvgDailyPL <- as.numeric(mean(PL.ne0)) - MedDailyPL <- as.numeric(median(PL.ne0)) - StdDailyPL <- as.numeric(sd(PL.ne0)) - - Equity <- cumsum(x) - Equity.max <- cummax(Equity) - MaxEquity <- max(Equity) - MinEquity <- min(Equity) - EndEquity <- as.numeric(last(Equity)) - MaxDrawdown <- -max(Equity.max - Equity) - ProfitToMaxDraw <- -TotalNetProfit / MaxDrawdown - - tmpret <- data.frame( - Total.Net.Profit = TotalNetProfit, - Total.Days = WinDays+LossDays, - Winning.Days = WinDays, - Losing.Days = LossDays, - Avg.Day.PL = AvgDayPL, - Med.Day.PL = MedDayPL, - Largest.Winner = MaxWin, - Largest.Loser = MaxLoss, - Gross.Profits = GrossProfits, - Gross.Losses = GrossLosses, - Std.Dev.Daily.PL = StdDayPL, [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/blotter -r 1525 From noreply at r-forge.r-project.org Mon Oct 14 18:12:04 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Oct 2013 18:12:04 +0200 (CEST) Subject: [Blotter-commits] r1526 - pkg/quantstrat/R Message-ID: <20131014161204.5FD8C185F3A@r-forge.r-project.org> Author: braverock Date: 2013-10-14 18:12:03 +0200 (Mon, 14 Oct 2013) New Revision: 1526 Modified: pkg/quantstrat/R/osFUNs.R Log: - update addPosLimit to work iwth new .getPortfolio internal fn Modified: pkg/quantstrat/R/osFUNs.R =================================================================== --- pkg/quantstrat/R/osFUNs.R 2013-10-14 16:02:08 UTC (rev 1525) +++ pkg/quantstrat/R/osFUNs.R 2013-10-14 16:12:03 UTC (rev 1526) @@ -49,7 +49,7 @@ #' @export addPosLimit <- function (portfolio, symbol, timestamp, maxpos, longlevels = 1, minpos = -maxpos, shortlevels = longlevels) { - portf <- getPortfolio(portfolio) + portf <- .getPortfolio(portfolio) #catch error where maxpos/minpos have length greater than 1 if(length(maxpos)>1) maxpos <- maxpos[,1] if(length(minpos)>1) minpos <- minpos[,1] From noreply at r-forge.r-project.org Mon Oct 14 19:39:24 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Oct 2013 19:39:24 +0200 (CEST) Subject: [Blotter-commits] r1527 - in pkg/quantstrat: . R man Message-ID: <20131014173924.E000B183BC3@r-forge.r-project.org> Author: braverock Date: 2013-10-14 19:39:24 +0200 (Mon, 14 Oct 2013) New Revision: 1527 Added: pkg/quantstrat/man/add.distribution.constraint.Rd Modified: pkg/quantstrat/DESCRIPTION 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/utils.R pkg/quantstrat/R/walk.forward.R Log: - clean up use of getPortfolio/.getPortfolio, as appropriate Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/DESCRIPTION 2013-10-14 17:39:24 UTC (rev 1527) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.7.10 +Version: 0.7.11 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: Modified: pkg/quantstrat/R/orders.R =================================================================== --- pkg/quantstrat/R/orders.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/orders.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -78,7 +78,7 @@ 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) + pfolio<-.getPortfolio(portfolio) symbols<-ls(pfolio$symbols) } if(!is.null(symbols)){ Modified: pkg/quantstrat/R/parameters.R =================================================================== --- pkg/quantstrat/R/parameters.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/parameters.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -397,7 +397,7 @@ { #need to create combination of distribution values in each slot of the parameterPool - initialPortf<-getPortfolio(portfolios) + initialPortf<-.getPortfolio(portfolios) symbols<-ls(initialPortf$symbols) # TODO: we likely want to search for first date, not (arbitrarily?) Modified: pkg/quantstrat/R/paramsets.R =================================================================== --- pkg/quantstrat/R/paramsets.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/paramsets.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -47,7 +47,7 @@ { #must.have.args(match.call(), c('portfolio.st', 'cloned.portfolio.st')) - portfolio <- getPortfolio(portfolio.st) + portfolio <- .getPortfolio(portfolio.st) if(strip.history==TRUE) { @@ -366,7 +366,7 @@ if(!is.null(audit)) must.be.environment(audit) - portfolio <- getPortfolio(portfolio.st) + portfolio <- .getPortfolio(portfolio.st) account <- getAccount(account.st) orderbook <- getOrderBook(portfolio.st) Modified: pkg/quantstrat/R/rebalance.rules.R =================================================================== --- pkg/quantstrat/R/rebalance.rules.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/rebalance.rules.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -49,7 +49,7 @@ { dummy <- updatePortf(Portfolio=portfolio, Dates=paste('::',timestamp,sep='')) - trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) + trading.pl <- sum(.getPortfolio(portfolio)$summary$Net.Trading.PL) total.equity <- initEq+trading.pl tradeSize <- total.equity * trade.percent if(length(refprice)>1) refprice <- refprice[,1] @@ -86,7 +86,7 @@ Dates=paste('::',timestamp,sep='')) total.equity<-getEndEq(account) } else { - trading.pl <- sum(getPortfolio(portfolio)$summary$Net.Trading.PL) + trading.pl <- sum(.getPortfolio(portfolio)$summary$Net.Trading.PL) total.equity <- initEq+trading.pl } Modified: pkg/quantstrat/R/strategy.R =================================================================== --- pkg/quantstrat/R/strategy.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/strategy.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -120,7 +120,7 @@ if(isTRUE(initStrat)) initStrategy(strategy=strategy, portfolio, symbols, ...=...) ret[[portfolio]]<-list() # this is slot [[i]] which we will use later - pobj<-getPortfolio(portfolio) + pobj<-.getPortfolio(portfolio) symbols<- ls(pobj$symbols) sret<-list() for (symbol in symbols){ Modified: pkg/quantstrat/R/utils.R =================================================================== --- pkg/quantstrat/R/utils.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/utils.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -45,7 +45,7 @@ { if(!is.portfolio(portfolio)) { - portfolio<-try(getPortfolio(portfolio)) + portfolio<-try(.getPortfolio(portfolio)) if(inherits(portfolio,"try-error")) stop(paste(portfolio, ': not a portfolio')) Modified: pkg/quantstrat/R/walk.forward.R =================================================================== --- pkg/quantstrat/R/walk.forward.R 2013-10-14 16:12:03 UTC (rev 1526) +++ pkg/quantstrat/R/walk.forward.R 2013-10-14 17:39:24 UTC (rev 1527) @@ -64,7 +64,7 @@ strategy <- must.be.strategy(strategy.st) must.be.paramset(strategy, paramset.label) - portfolio <- getPortfolio(portfolio.st) + portfolio <- .getPortfolio(portfolio.st) results <- list() Added: pkg/quantstrat/man/add.distribution.constraint.Rd =================================================================== --- pkg/quantstrat/man/add.distribution.constraint.Rd (rev 0) +++ pkg/quantstrat/man/add.distribution.constraint.Rd 2013-10-14 17:39:24 UTC (rev 1527) @@ -0,0 +1,44 @@ +\name{add.distribution.constraint} +\alias{add.distribution.constraint} +\title{Adds a constraint on 2 distributions within a paramset} +\usage{ + add.distribution.constraint(strategy, paramset.label, + distribution.label.1, distribution.label.2, operator, + label, store = TRUE) +} +\arguments{ + \item{strategy}{the name of the strategy object to add + the constraint to} + + \item{paramset.label}{a label uniquely identifying the + paramset within the strategy} + + \item{distribution.label.1}{a label identifying the first + distribution} + + \item{distribution.label.2}{a label identifying the + second distribution} + + \item{operator}{an operator specifying the relational + constraint between the 2 distributions} + + \item{label}{a label uniquely identifying the constraint + within the paramset} + + \item{store}{indicates whether to store the strategy in + the .strategy environment} +} +\description{ + Creates a constraint on 2 distributions in a paramset, + i.e. a restriction limiting the allowed combinations from + the ranges for distribution 1 and distribution 2. +} +\author{ + Jan Humme +} +\seealso{ + \code{\link{add.distribution}}, + \code{\link{delete.paramset}}, + \code{\link{apply.paramset}} +} + From noreply at r-forge.r-project.org Mon Oct 14 20:54:56 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Oct 2013 20:54:56 +0200 (CEST) Subject: [Blotter-commits] r1528 - in pkg/blotter: . R Message-ID: <20131014185456.B11151849F3@r-forge.r-project.org> Author: braverock Date: 2013-10-14 20:54:56 +0200 (Mon, 14 Oct 2013) New Revision: 1528 Modified: pkg/blotter/ pkg/blotter/.project pkg/blotter/R/updateAcct.R Log: - fix updateAcct to work with new portfolio environments Property changes on: pkg/blotter ___________________________________________________________________ Added: svn:ignore + .Rproj.user .Rhistory .RData Modified: pkg/blotter/.project =================================================================== --- pkg/blotter/.project 2013-10-14 17:39:24 UTC (rev 1527) +++ pkg/blotter/.project 2013-10-14 18:54:56 UTC (rev 1528) @@ -17,6 +17,5 @@ de.walware.statet.base.StatetNature de.walware.statet.r.RNature - de.walware.statet.r.RPkgNature Modified: pkg/blotter/R/updateAcct.R =================================================================== --- pkg/blotter/R/updateAcct.R 2013-10-14 17:39:24 UTC (rev 1527) +++ pkg/blotter/R/updateAcct.R 2013-10-14 18:54:56 UTC (rev 1528) @@ -14,7 +14,8 @@ Portfolios = names(Account$portfolios) - if(is.null(Dates)) Dates<-index(getPortfolio(Portfolios[1])$summary)[-1] + port<-.getPortfolio(Portfolios[1]) + if(is.null(Dates)) Dates <- unique(do.call(c,c(lapply(port$symbols, function(x) index(x[["posPL"]])), use.names=FALSE, recursive=FALSE))) #trim to only time prior to Dates if(last(index(Account$summary))>.parseISO8601(Dates)$first.time){ @@ -27,7 +28,7 @@ # Append the portfolio summary data to the portfolio slot for(pname in Portfolios){ - Portfolio = getPortfolio(pname) + Portfolio = .getPortfolio(pname) if(!is.null(attr(Portfolio,'currency'))) { p.ccy.str<-attr(Portfolio,'currency') } From noreply at r-forge.r-project.org Tue Oct 15 19:31:07 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Oct 2013 19:31:07 +0200 (CEST) Subject: [Blotter-commits] r1529 - pkg/FinancialInstrument/inst/parser Message-ID: <20131015173107.6F3C21850E0@r-forge.r-project.org> Author: peter_carl Date: 2013-10-15 19:31:06 +0200 (Tue, 15 Oct 2013) New Revision: 1529 Removed: pkg/FinancialInstrument/inst/parser/download.pitrader.R Log: - free data no longer offered by vendor Deleted: pkg/FinancialInstrument/inst/parser/download.pitrader.R =================================================================== --- pkg/FinancialInstrument/inst/parser/download.pitrader.R 2013-10-14 18:54:56 UTC (rev 1528) +++ pkg/FinancialInstrument/inst/parser/download.pitrader.R 2013-10-15 17:31:06 UTC (rev 1529) @@ -1,116 +0,0 @@ -# Script for managing the download of data from -# http://pitrading.com/free_market_data.htm -# including some long series of continuous futures contracts - -# This script requires the following directory structure: -# filesroot [directory set in the script below] -# Each symbol's processed csv files are stored in sub-directories -# named for each symbol, e.g., ~/Data/EOD\ Global\ Indexes/XMI.IDX. -# These directories and files will be created and updated by this script. -# filesroot/.incoming -# New or updated zip files should be placed here for processing. -# This is also the working directory for the processing done in -# this script. Unzipped csv files are redirected here for processing. -# Temporary files are stored here before being appended to the symbol -# file csv in the appropriate directory - -filesroot = "/home/peter/Data/pitrading" - -start_t<-Sys.time() - -# Create and set the working directory if it doesn't exist -if (!file.exists(paste(filesroot, "/.incoming", sep=""))) - dir.create(paste(filesroot, "/.incoming", sep=""), mode="0777") -setwd(paste(filesroot, "/.incoming", sep="")) - -# Does the archive directory structure exist? -if (!file.exists("../.archive")){ - dir.create("../.archive", mode="0777") - dir.create("../.archive/zip_files", mode="0777") -} -if (!file.exists("../.archive/zip_files")) - dir.create("../.archive/zip_files", mode="0777") - -# Use wget so that we don't need a list of files to work from -system("wget -r -l1 -H -t1 -nd -N -np -A.zip http://pitrading.com/free_market_data.htm") - -# -r -H -l1 -np These options tell wget to download recursively. -# That means it goes to a URL, downloads the page there, then follows -# every link it finds. The -H tells the app to span domains, meaning -# it should follow links that point away from the page. And the -l1 -# (a lowercase L with a numeral one) means to only go one level deep; -# that is, don't follow links on the linked site. It will take each -# link from the list of pages, and download it. The -np switch stands -# for "no parent", which instructs wget to never follow a link up to a -# parent directory. -# -# We don't, however, want all the links -- just those that point to -# zip files we haven't yet seen. Including -A.zip tells wget to only -# download files that end with the .zip extension. And -N turns on -# timestamping, which means wget won't download something with the same -# name unless it's newer. -# -# To keep things clean, we'll add -nd, which makes the app save every -# thing it finds in one directory, rather than mirroring the directory -# structure of linked sites. - -# Unzip the files to text files -system("unzip \\*.zip") -system("mv *.zip ../.archive/zip_files/") - -# What files did we download? -files = list.files() - -# Each file contains the full history for the symbol, so we just need to -# move the file into the correct base directory. We don't need to do any -# data parsing. -pisymbols = vector() -for(i in 1:length(files)) { - # generate a list of symbols from the files we downloaded - filename.txt <- files[i] - pisymbols[i] <- substr(filename.txt, 1, nchar(filename.txt) - 4) -} - -# The extra ".CC" appended to each symbol to indicate that the data is for a -# "continuous contract" rather than a futures contract to be used as a root. -# We're modifying the symbols used so that they don't conflict with actual -# futures contracts. -for(pisymbol in pisymbols) { - # check to make sure directories exist for each - dir.create(paste("../", pisymbol, ".CC", sep=""), showWarnings = FALSE, - recursive = FALSE, mode = "0777") - # move files into appropriate directory - system(paste("mv ", pisymbol, ".txt", " ../", pisymbol, ".CC/", pisymbol, ".CC.csv", sep="")) -} - -end_t<-Sys.time() -print(c("Elapsed time: ",end_t-start_t)) -print(paste("Processed ", length(pisymbols), " symbols.", sep="")) - -# The following currencies need to be created first: -# require(FinancialInstrument) -# currency("USD") -# currency("JPY") -# currency("AUD") -# currency("CHF") -# currency("GBP") -# currency("MXN") -# currency("EUR") -# currency("CAD") - -# We need to have a csv file that describes the metadata -# for all the symbols. Remember to change the symbol to append ".CC" to each. -# load.instruments(paste(filesroot, "/.scripts/instr.pitrading.csv", sep="")) - -# Dates in files are formatted as "%m/%d/%Y". -# Now, whenever you log in you need to register the instruments. This -# might be a line you put into .Rprofile so that it happens automatically: -# require(quantmod) # this requires a development build after revision 560 or so. -# setSymbolLookup.FI(base_dir=filesroot, split_method='common', storage_method='csv', src='csv', extension='csv', format='%m/%d/%Y') - -# Now you should be able to: -# > getSymbols("INX.CC") -# [1] "INX.CC" -# > chart_Series(INX.CC) -# > head(INX.CC) - From noreply at r-forge.r-project.org Tue Oct 15 20:15:40 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Oct 2013 20:15:40 +0200 (CEST) Subject: [Blotter-commits] r1530 - pkg/quantstrat/demo Message-ID: <20131015181540.EE902180888@r-forge.r-project.org> Author: braverock Date: 2013-10-15 20:15:40 +0200 (Tue, 15 Oct 2013) New Revision: 1530 Modified: pkg/quantstrat/demo/faber.R Log: - remove unecessary na.omit from demo Modified: pkg/quantstrat/demo/faber.R =================================================================== --- pkg/quantstrat/demo/faber.R 2013-10-15 17:31:06 UTC (rev 1529) +++ pkg/quantstrat/demo/faber.R 2013-10-15 18:15:40 UTC (rev 1530) @@ -153,7 +153,6 @@ 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 Thu Oct 17 01:59:14 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 01:59:14 +0200 (CEST) Subject: [Blotter-commits] r1531 - pkg/blotter Message-ID: <20131016235915.0339F1856F6@r-forge.r-project.org> Author: bodanker Date: 2013-10-17 01:59:14 +0200 (Thu, 17 Oct 2013) New Revision: 1531 Modified: pkg/blotter/NAMESPACE Log: - Put useDynLib(blotter) back in NAMESPACE (accidentally removed in r1525) Modified: pkg/blotter/NAMESPACE =================================================================== --- pkg/blotter/NAMESPACE 2013-10-15 18:15:40 UTC (rev 1530) +++ pkg/blotter/NAMESPACE 2013-10-16 23:59:14 UTC (rev 1531) @@ -1,3 +1,4 @@ +useDynLib(blotter) export(.getPortfolio) export(AcctReturns) export(PortfReturns) From noreply at r-forge.r-project.org Thu Oct 17 02:02:07 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 02:02:07 +0200 (CEST) Subject: [Blotter-commits] r1532 - in pkg/blotter: R data man Message-ID: <20131017000207.D4F7E185F54@r-forge.r-project.org> Author: bodanker Date: 2013-10-17 02:02:07 +0200 (Thu, 17 Oct 2013) New Revision: 1532 Modified: pkg/blotter/R/addTxn.R pkg/blotter/data/amzn.rda pkg/blotter/man/addTxn.Rd Log: - Fix colnames in amzn.trades object - Remove "TODO vectorize addTxns" from ?addTxn Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-10-16 23:59:14 UTC (rev 1531) +++ pkg/blotter/R/addTxn.R 2013-10-17 00:02:07 UTC (rev 1532) @@ -50,7 +50,6 @@ #' such as adjustments for corporate actions or expire/assign for options. #' See \code{\link{addDiv}} #' -#' TODO figure out if we can fully vectorize the addTxns function to make it faster #' @seealso \code{\link{addTxns}}, \code{\link{pennyPerShare}}, \code{\link{initPortf}} #' @author Peter Carl, Brian G. Peterson #' @export addTxn Modified: pkg/blotter/data/amzn.rda =================================================================== (Binary files differ) Modified: pkg/blotter/man/addTxn.Rd =================================================================== --- pkg/blotter/man/addTxn.Rd 2013-10-16 23:59:14 UTC (rev 1531) +++ pkg/blotter/man/addTxn.Rd 2013-10-17 00:02:07 UTC (rev 1532) @@ -86,9 +86,6 @@ transaction types, such as adjustments for corporate actions or expire/assign for options. See \code{\link{addDiv}} - - TODO figure out if we can fully vectorize the addTxns - function to make it faster } \author{ Peter Carl, Brian G. Peterson From noreply at r-forge.r-project.org Thu Oct 17 15:04:14 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 15:04:14 +0200 (CEST) Subject: [Blotter-commits] r1533 - pkg/quantstrat/R Message-ID: <20131017130414.78E701813D4@r-forge.r-project.org> Author: bodanker Date: 2013-10-17 15:04:13 +0200 (Thu, 17 Oct 2013) New Revision: 1533 Modified: pkg/quantstrat/R/indicators.R pkg/quantstrat/R/initialize.R pkg/quantstrat/R/rules.R pkg/quantstrat/R/signals.R pkg/quantstrat/R/utils.R pkg/quantstrat/R/wrapup.R Log: - Update modify.args to avoid evaluating '...', which causes a deparsed mktdata object to be part of the call created by do.call - Update calls to modify.args to use '...' directly instead of list(...) Modified: pkg/quantstrat/R/indicators.R =================================================================== --- pkg/quantstrat/R/indicators.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/indicators.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -174,7 +174,7 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, list(...)) + .formals <- modify.args(.formals, ...) tmp_val <- do.call(indicator$name, .formals) Modified: pkg/quantstrat/R/initialize.R =================================================================== --- pkg/quantstrat/R/initialize.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/initialize.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -100,7 +100,7 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, list(...)) + .formals <- modify.args(.formals, ...) do.call(init_o$name, .formals) } Modified: pkg/quantstrat/R/rules.R =================================================================== --- pkg/quantstrat/R/rules.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/rules.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -696,12 +696,13 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, list(...)) + .formals <- modify.args(.formals, ...) # any rule-specific prefer-parameters should override global prefer parameter if(!is.null(rule$arguments$prefer)) .formals$prefer = rule$arguments$prefer - tmp_val <- do.call(rule$name, .formals) + # evaluate rule in applyRules' environment + tmp_val <- do.call(rule$name, .formals, envir=parent.frame(2)) # print(paste('tmp_val ==', tmp_val)) } #end rules loop Modified: pkg/quantstrat/R/signals.R =================================================================== --- pkg/quantstrat/R/signals.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/signals.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -105,7 +105,7 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, list(...)) + .formals <- modify.args(.formals, ...) tmp_val <- do.call(signal$name, .formals) Modified: pkg/quantstrat/R/utils.R =================================================================== --- pkg/quantstrat/R/utils.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/utils.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -52,8 +52,15 @@ } } -modify.args <- function(formals, arglist, dots=FALSE) +modify.args <- function(formals, arglist, ..., dots=FALSE) { + # avoid evaluating '...' to make things faster + dots.names <- eval(substitute(alist(...))) + + if(missing(arglist)) + arglist <- NULL + arglist <- c(arglist, dots.names) + # see 'S Programming' p. 67 for this matching # nothing to do if arglist is empty; return formals Modified: pkg/quantstrat/R/wrapup.R =================================================================== --- pkg/quantstrat/R/wrapup.R 2013-10-17 00:02:07 UTC (rev 1532) +++ pkg/quantstrat/R/wrapup.R 2013-10-17 13:04:13 UTC (rev 1533) @@ -115,7 +115,7 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, list(...)) + .formals <- modify.args(.formals, ...) out[[wrapup_o$name]] <- do.call(wrapup_o$name, .formals) } From noreply at r-forge.r-project.org Thu Oct 17 16:25:16 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 16:25:16 +0200 (CEST) Subject: [Blotter-commits] r1534 - pkg/blotter/R Message-ID: <20131017142516.CCA51183DE7@r-forge.r-project.org> Author: braverock Date: 2013-10-17 16:25:16 +0200 (Thu, 17 Oct 2013) New Revision: 1534 Modified: pkg/blotter/R/calcPosAvgCost.R Log: - add @useDynLib roxygen tag Modified: pkg/blotter/R/calcPosAvgCost.R =================================================================== --- pkg/blotter/R/calcPosAvgCost.R 2013-10-17 13:04:13 UTC (rev 1533) +++ pkg/blotter/R/calcPosAvgCost.R 2013-10-17 14:25:16 UTC (rev 1534) @@ -6,6 +6,7 @@ #' @param TxnValue total value of the transaction, including fees #' @param PosQty total units (shares) of the resulting position #' @param ConMult multiplier from instrument data +#' @useDynLib blotter #' @rdname calcPosAvgCost .calcPosAvgCost <- function(PrevPosQty, PrevPosAvgCost, TxnValue, PosQty, ConMult=1) { # @author Peter Carl From noreply at r-forge.r-project.org Thu Oct 17 19:35:54 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 19:35:54 +0200 (CEST) Subject: [Blotter-commits] r1535 - pkg/blotter/R Message-ID: <20131017173554.5A04C1859B9@r-forge.r-project.org> Author: bodanker Date: 2013-10-17 19:35:53 +0200 (Thu, 17 Oct 2013) New Revision: 1535 Modified: pkg/blotter/R/perTradeStats.R Log: - Fix trade start/end identification (based on qty, not value) Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-10-17 14:25:16 UTC (rev 1534) +++ pkg/blotter/R/perTradeStats.R 2013-10-17 17:35:53 UTC (rev 1535) @@ -56,8 +56,8 @@ trades <- list() # identify start and end for each trade, where end means flat position - trades$Start <- index(posPL[which(posPL$Pos.Value!=0 & lag(posPL$Pos.Value)==0),]) - trades$End <- index(posPL[which(posPL$Pos.Value==0 & lag(posPL$Pos.Value)!=0),]) + trades$Start <- index(posPL[which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0),]) + trades$End <- index(posPL[which(posPL$Pos.Qty==0 & lag(posPL$Pos.Qty)!=0),]) # if the last trade is still open, adjust depending on whether wants open trades or not if(length(trades$Start)>length(trades$End)) From noreply at r-forge.r-project.org Thu Oct 17 20:35:15 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 20:35:15 +0200 (CEST) Subject: [Blotter-commits] r1536 - pkg/blotter/R Message-ID: <20131017183515.673BF186001@r-forge.r-project.org> Author: bodanker Date: 2013-10-17 20:35:15 +0200 (Thu, 17 Oct 2013) New Revision: 1536 Modified: pkg/blotter/R/updatePosPL.R Log: - Speed improvements (same as r1520; remove xts:::.parseISO8601 call) Modified: pkg/blotter/R/updatePosPL.R =================================================================== --- pkg/blotter/R/updatePosPL.R 2013-10-17 17:35:53 UTC (rev 1535) +++ pkg/blotter/R/updatePosPL.R 2013-10-17 18:35:15 UTC (rev 1536) @@ -45,8 +45,8 @@ if(ncol(prices)>1) prices=getPrice(Prices,Symbol) # line up Prices dates with Dates set/index/span passed in. - startDate = first(xts:::.parseISO8601(Dates))$first.time-1 #does this need to be a smaller/larger delta for millisecond data? - endDate = last(xts:::.parseISO8601(Dates))$last.time + startDate = first(Dates)-.00001 #does this need to be a smaller/larger delta for millisecond data? + endDate = last(Dates) if(is.na(endDate)) endDate<-NULL dateRange = paste(startDate,endDate,sep='::') From noreply at r-forge.r-project.org Thu Oct 17 21:02:10 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 21:02:10 +0200 (CEST) Subject: [Blotter-commits] r1537 - pkg/blotter Message-ID: <20131017190210.A7F4C185EC9@r-forge.r-project.org> Author: edd Date: 2013-10-17 21:02:10 +0200 (Thu, 17 Oct 2013) New Revision: 1537 Added: pkg/blotter/.Rbuildignore Log: added .Rbuildignore to ignore R/.vimrc from tarball Added: pkg/blotter/.Rbuildignore =================================================================== --- pkg/blotter/.Rbuildignore (rev 0) +++ pkg/blotter/.Rbuildignore 2013-10-17 19:02:10 UTC (rev 1537) @@ -0,0 +1 @@ +R/.vimrc From noreply at r-forge.r-project.org Thu Oct 17 21:05:26 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 21:05:26 +0200 (CEST) Subject: [Blotter-commits] r1538 - pkg/quantstrat/demo Message-ID: <20131017190527.02B9F185EC9@r-forge.r-project.org> Author: opentrades Date: 2013-10-17 21:05:26 +0200 (Thu, 17 Oct 2013) New Revision: 1538 Modified: pkg/quantstrat/demo/luxor.include.R Log: - now removing lingering portfolio, account, strategy and order book objects from .blotter and .strategy environments before running any luxor demo Modified: pkg/quantstrat/demo/luxor.include.R =================================================================== --- pkg/quantstrat/demo/luxor.include.R 2013-10-17 19:02:10 UTC (rev 1537) +++ pkg/quantstrat/demo/luxor.include.R 2013-10-17 19:05:26 UTC (rev 1538) @@ -18,7 +18,7 @@ strategy.st = 'luxor' portfolio.st = 'forex' -account.st = 'IB1' +account.st = 'IB' ### @@ -63,3 +63,5 @@ .stoptrailing <- 0.8/100 .takeprofit <- 2.0/100 +suppressWarnings(rm(list = c(paste("account", account.st, sep='.'), paste("portfolio", portfolio.st, sep='.')), pos=.blotter)) +suppressWarnings(rm(list = c(strategy.st, paste("order_book", portfolio.st, sep='.')), pos=.strategy)) From noreply at r-forge.r-project.org Thu Oct 17 21:21:57 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 21:21:57 +0200 (CEST) Subject: [Blotter-commits] r1539 - pkg/blotter/src Message-ID: <20131017192157.70A2C1859B9@r-forge.r-project.org> Author: edd Date: 2013-10-17 21:21:57 +0200 (Thu, 17 Oct 2013) New Revision: 1539 Modified: pkg/blotter/src/calcPosAvgCost.c Log: copy and pasto fixed Modified: pkg/blotter/src/calcPosAvgCost.c =================================================================== --- pkg/blotter/src/calcPosAvgCost.c 2013-10-17 19:05:26 UTC (rev 1538) +++ pkg/blotter/src/calcPosAvgCost.c 2013-10-17 19:21:57 UTC (rev 1539) @@ -36,8 +36,8 @@ d_TxnValue[i]= -1.0 * d_TxnValue[i]; /* fix bug with negative average cost */ d_PosAvgCost[i] = (d_PrevPosQty * d_PrevPosAvgCost * d_ConMult + d_TxnValue[i])/(d_PosQty[i]*d_ConMult); } - d_PrevPosQty <- d_PosQty[i]; - d_PrevPosAvgCost <- d_PosAvgCost[i]; + d_PrevPosQty = d_PosQty[i]; + d_PrevPosAvgCost = d_PosAvgCost[i]; } UNPROTECT(P); return(PosAvgCost); From noreply at r-forge.r-project.org Thu Oct 17 21:50:22 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 17 Oct 2013 21:50:22 +0200 (CEST) Subject: [Blotter-commits] r1540 - pkg/blotter/R Message-ID: <20131017195022.C3785185A00@r-forge.r-project.org> Author: opentrades Date: 2013-10-17 21:50:22 +0200 (Thu, 17 Oct 2013) New Revision: 1540 Modified: pkg/blotter/R/perTradeStats.R Log: - changed getPortfolio() call to .getPortfolio() Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-10-17 19:21:57 UTC (rev 1539) +++ pkg/blotter/R/perTradeStats.R 2013-10-17 19:50:22 UTC (rev 1540) @@ -44,7 +44,7 @@ #' and \code{\link{tradeStats}} for a summary view of the performance #' @export perTradeStats <- function(Portfolio, Symbol, includeOpenTrade=TRUE, ...) { - portf <- getPortfolio(Portfolio) + portf <- .getPortfolio(Portfolio) if(missing(Symbol)) Symbol <- ls(portf$symbols)[[1]] From noreply at r-forge.r-project.org Fri Oct 18 16:16:07 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 18 Oct 2013 16:16:07 +0200 (CEST) Subject: [Blotter-commits] r1541 - in pkg/blotter: R man Message-ID: <20131018141607.3A09A1859F7@r-forge.r-project.org> Author: bodanker Date: 2013-10-18 16:16:06 +0200 (Fri, 18 Oct 2013) New Revision: 1541 Modified: pkg/blotter/R/perTradeStats.R pkg/blotter/man/perTradeStats.Rd Log: - Add flat-to-reduced trade definition to perTradeStats Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-10-17 19:50:22 UTC (rev 1540) +++ pkg/blotter/R/perTradeStats.R 2013-10-18 14:16:06 UTC (rev 1541) @@ -17,6 +17,7 @@ #' @param Portfolio string identifying the portfolio #' @param Symbol string identifying the symbol to examin trades for. If missing, the first symbol found in the \code{Portfolio} portfolio will be used #' @param includeOpenTrade whether to process only finished trades, or the last trade if it is still open, default TRUE +#' @param tradeDef string to determine which definition of 'trade' to use. Currently "flat.to.flat" (the default) and "flat.to.reduced" are implemented. #' @param \dots any other passthrough parameters #' @author Brian G. Peterson, Jan Humme #' @references Tomasini, E. and Jaekle, U. \emph{Trading Systems - A new approach to system development and portfolio optimisation} (ISBN 978-1-905641-79-6) @@ -43,22 +44,43 @@ #' @seealso \code{\link{chart.ME}} for a chart of MAE and MFE derived from this function, #' and \code{\link{tradeStats}} for a summary view of the performance #' @export -perTradeStats <- function(Portfolio, Symbol, includeOpenTrade=TRUE, ...) { +perTradeStats <- function(Portfolio, Symbol, includeOpenTrade=TRUE, tradeDef="flat.to.flat", ...) { + portf <- .getPortfolio(Portfolio) - if(missing(Symbol)) Symbol <- ls(portf$symbols)[[1]] posPL <- portf$symbols[[Symbol]]$posPL instr <- getInstrument(Symbol) tick_value <- instr$multiplier*instr$tick_size + + tradeDefn <- match.arg(tradeDefn, c("flat.to.flat","flat.to.reduced")) trades <- list() - - # identify start and end for each trade, where end means flat position - trades$Start <- index(posPL[which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0),]) - trades$End <- index(posPL[which(posPL$Pos.Qty==0 & lag(posPL$Pos.Qty)!=0),]) - + switch(tradeDefn, + flat.to.flat = { + # identify start and end for each trade, where end means flat position + trades$Start <- index(posPL[which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0),]) + trades$End <- index(posPL[which(posPL$Pos.Qty==0 & lag(posPL$Pos.Qty)!=0),]) + }, + flat.to.reduced = { + # find all transactions that bring position closer to zero ('trade ends') + decrPos <- diff(abs(posPL$Pos.Qty)) < 0 + # find all transactions that open a position ('trade starts') + initPos <- posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0 + # all 'trades' start when we open a position, so determine which starts correspond to each end + StartEnd <- cumsum(!(decrPos[initPos | decrPos])) + starts <- sapply(split.default(StartEnd, StartEnd), function(i) rep(start(i), nrow(i)-1)) + starts <- unlist(starts, recursive=FALSE, use.names=FALSE) + attributes(starts) <- attributes(index(StartEnd)) + # add extra 'trade start' if there's an open trade, so 'includeOpenTrade' logic will work + if(last(posPL)[,"Pos.Qty"] != 0) + starts <- c(starts, last(starts)) + trades$Start <- starts + trades$End <- index(decrPos[decrPos]) + } + ) + # if the last trade is still open, adjust depending on whether wants open trades or not if(length(trades$Start)>length(trades$End)) { Modified: pkg/blotter/man/perTradeStats.Rd =================================================================== --- pkg/blotter/man/perTradeStats.Rd 2013-10-17 19:50:22 UTC (rev 1540) +++ pkg/blotter/man/perTradeStats.Rd 2013-10-18 14:16:06 UTC (rev 1541) @@ -3,7 +3,7 @@ \title{calculate flat to flat per-trade statistics} \usage{ perTradeStats(Portfolio, Symbol, includeOpenTrade = TRUE, - ...) + tradeDef = "flat.to.flat", ...) } \arguments{ \item{Portfolio}{string identifying the portfolio} @@ -16,6 +16,10 @@ trades, or the last trade if it is still open, default TRUE} + \item{tradeDef}{string to determine which definition of + 'trade' to use. Currently "flat.to.flat" (the default) + and "flat.to.reduced" are implemented.} + \item{\dots}{any other passthrough parameters} } \value{ From noreply at r-forge.r-project.org Fri Oct 18 19:25:18 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 18 Oct 2013 19:25:18 +0200 (CEST) Subject: [Blotter-commits] r1542 - pkg/blotter/R Message-ID: <20131018172519.0F6D81861C6@r-forge.r-project.org> Author: bodanker Date: 2013-10-18 19:25:18 +0200 (Fri, 18 Oct 2013) New Revision: 1542 Modified: pkg/blotter/R/perTradeStats.R Log: - Fix typo (thanks to Samo) Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-10-18 14:16:06 UTC (rev 1541) +++ pkg/blotter/R/perTradeStats.R 2013-10-18 17:25:18 UTC (rev 1542) @@ -54,10 +54,10 @@ instr <- getInstrument(Symbol) tick_value <- instr$multiplier*instr$tick_size - tradeDefn <- match.arg(tradeDefn, c("flat.to.flat","flat.to.reduced")) + tradeDef <- match.arg(tradeDef, c("flat.to.flat","flat.to.reduced")) trades <- list() - switch(tradeDefn, + switch(tradeDef, flat.to.flat = { # identify start and end for each trade, where end means flat position trades$Start <- index(posPL[which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0),]) From noreply at r-forge.r-project.org Sat Oct 19 19:26:25 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 19 Oct 2013 19:26:25 +0200 (CEST) Subject: [Blotter-commits] r1543 - pkg/blotter/R Message-ID: <20131019172625.B861A181103@r-forge.r-project.org> Author: bodanker Date: 2013-10-19 19:26:25 +0200 (Sat, 19 Oct 2013) New Revision: 1543 Modified: pkg/blotter/R/perTradeStats.R Log: - Use integer indexing instead of ISO8601-style subsetting, which was causing issues with floating-point rounding errors when digits.secs was set, and also caused issue #5015. Modified: pkg/blotter/R/perTradeStats.R =================================================================== --- pkg/blotter/R/perTradeStats.R 2013-10-18 17:25:18 UTC (rev 1542) +++ pkg/blotter/R/perTradeStats.R 2013-10-19 17:26:25 UTC (rev 1543) @@ -60,24 +60,27 @@ switch(tradeDef, flat.to.flat = { # identify start and end for each trade, where end means flat position - trades$Start <- index(posPL[which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0),]) - trades$End <- index(posPL[which(posPL$Pos.Qty==0 & lag(posPL$Pos.Qty)!=0),]) + trades$Start <- which(posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0) + trades$End <- which(posPL$Pos.Qty==0 & lag(posPL$Pos.Qty)!=0) }, flat.to.reduced = { # find all transactions that bring position closer to zero ('trade ends') decrPos <- diff(abs(posPL$Pos.Qty)) < 0 # find all transactions that open a position ('trade starts') initPos <- posPL$Pos.Qty!=0 & lag(posPL$Pos.Qty)==0 - # all 'trades' start when we open a position, so determine which starts correspond to each end - StartEnd <- cumsum(!(decrPos[initPos | decrPos])) - starts <- sapply(split.default(StartEnd, StartEnd), function(i) rep(start(i), nrow(i)-1)) - starts <- unlist(starts, recursive=FALSE, use.names=FALSE) - attributes(starts) <- attributes(index(StartEnd)) + # 'trades' start when we open a position, so determine which starts correspond to each end + # add small amount to Start index, so starts will always occur before ends in StartEnd + Start <- xts(initPos[initPos,which.i=TRUE],index(initPos[initPos])+1e-5) + End <- xts(decrPos[decrPos,which.i=TRUE],index(decrPos[decrPos])) + StartEnd <- merge(Start,End) + StartEnd$Start <- na.locf(StartEnd$Start) + StartEnd <- StartEnd[!is.na(StartEnd$End),] + # populate trades list + trades$Start <- drop(coredata(StartEnd$Start)) + trades$End <- drop(coredata(StartEnd$End)) # add extra 'trade start' if there's an open trade, so 'includeOpenTrade' logic will work if(last(posPL)[,"Pos.Qty"] != 0) - starts <- c(starts, last(starts)) - trades$Start <- starts - trades$End <- index(decrPos[decrPos]) + trades$Start <- c(trades$Start, last(trades$Start)) } ) @@ -85,7 +88,7 @@ if(length(trades$Start)>length(trades$End)) { if(includeOpenTrade) - trades$End <- c(trades$End,last(index(posPL))) + trades$End <- c(trades$End,nrow(posPL)) else trades$Start <- head(trades$Start, -1) } @@ -93,16 +96,9 @@ # calculate information about each trade for(i in 1:length(trades$End)) { - #timespan <- paste(format(trades$Start[[i]], "%Y-%m-%d %H:%M:%OS6"), - #format(trades$End[[i]], "%Y-%m-%d %H:%M:%OS6"), sep="::") - timespan <- paste(trades$Start[[i]], trades$End[[i]], sep="/") - - trade <- posPL[timespan] + timespan <- seq.int(trades$Start[i], trades$End[i]) + trade <- posPL[timespan] - # close and open may occur in at same index timestamp, must be corrected - if(first(trade)$Pos.Qty==0) trade <- tail(trade, -1) - if(last(trade)$Pos.Qty!=0) trade <- head(trade, -1) - # add cost basis column trade$Pos.Cost.Basis <- cumsum(trade$Txn.Value) #add running posPL column @@ -140,6 +136,8 @@ trades$tick.MAE[i] <- min(0,trade$tick.PL) trades$tick.MFE[i] <- max(0,trade$tick.PL) } + trades$Start <- index(posPL)[trades$Start] + trades$End <- index(posPL)[trades$End] return(as.data.frame(trades)) } # end fn perTradeStats From noreply at r-forge.r-project.org Mon Oct 21 20:34:05 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 21 Oct 2013 20:34:05 +0200 (CEST) Subject: [Blotter-commits] r1544 - in pkg/quantstrat: . demo man Message-ID: <20131021183405.A9EB01813BB@r-forge.r-project.org> Author: opentrades Date: 2013-10-21 20:34:05 +0200 (Mon, 21 Oct 2013) New Revision: 1544 Added: pkg/quantstrat/demo/luxor.7.exit.and.risk.R Removed: pkg/quantstrat/demo/luxor.7.exit+risk.R Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/NAMESPACE pkg/quantstrat/man/rulePctEquity.Rd Log: - renamed quantstrat/demo/luxor.7.exit+risk.R to luxor.7.exit.and.risk.R to fix problem using demo(luxor.7.risk+exit.R, package='quantstrat') ie. demo name without quotes Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2013-10-19 17:26:25 UTC (rev 1543) +++ pkg/quantstrat/DESCRIPTION 2013-10-21 18:34:05 UTC (rev 1544) @@ -15,8 +15,31 @@ Maintainer: Brian G. Peterson Description: Specify, build, and back-test quantitative financial trading and portfolio strategies -Contributors: Yu Chen, Joe Dunn, Dirk Eddelbuettel, +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.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' + 'tradeOrderStats.R' + 'utils.R' + 'walk.forward.R' + 'wrapup.R' Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-10-19 17:26:25 UTC (rev 1543) +++ pkg/quantstrat/NAMESPACE 2013-10-21 18:34:05 UTC (rev 1544) @@ -1,5 +1,5 @@ +export(add.distribution.constraint) export(add.distribution) -export(add.distribution.constraint) export(add.indicator) export(add.init) export(add.rule) @@ -11,10 +11,10 @@ export(applyParameter) export(applyRules) export(applySignals) +export(applyStrategy.rebalancing) export(applyStrategy) -export(applyStrategy.rebalancing) +export(chart.forward.training) export(chart.forward) -export(chart.forward.training) export(delete.paramset) export(enable.rule) export(get.orderbook) Deleted: pkg/quantstrat/demo/luxor.7.exit+risk.R =================================================================== --- pkg/quantstrat/demo/luxor.7.exit+risk.R 2013-10-19 17:26:25 UTC (rev 1543) +++ pkg/quantstrat/demo/luxor.7.exit+risk.R 2013-10-21 18:34:05 UTC (rev 1544) @@ -1,83 +0,0 @@ -#!/usr/bin/Rscript --vanilla -# -# Jan Humme (@opentrades) - April 2013 -# -# Tested and found to work correctly using blotter r1457 -# -# After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) -# -# Paragraph 3.5: determination of appropriate exit and risk management - -require(quantstrat) - -source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) - -##### PLACE DEMO AND TEST DATES HERE ################# -# -#if(isTRUE(options('in_test')$in_test)) -# # use test dates -# {initDate="2011-01-01" -# endDate="2012-12-31" -# } else -# # use demo defaults -# {initDate="1999-12-31" -# endDate=Sys.Date()} - -source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) - -### blotter - -initPortf(portfolio.st, symbols='GBPUSD', initDate=initDate, currency='USD') -initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD') - -### quantstrat - -load.strategy('luxor') - -### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules - -#enable.rule('luxor', 'chain', 'StopLoss') -#enable.rule('luxor', 'chain', 'StopTrailing') -#enable.rule('luxor', 'chain', 'TakeProfit') - -### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules - -addPosLimit( - portfolio=portfolio.st, - symbol='GBPUSD', - timestamp=initDate, - maxpos=.orderqty) - -initOrders(portfolio.st, initDate=initDate) - -applyStrategy(strategy.st, portfolio.st, prefer='Open') - -View(getOrderBook(portfolio.st)[[portfolio.st]]$GBPUSD) - -############################################################################### - -updatePortf(portfolio.st, Symbols='GBPUSD', Dates=paste('::',as.Date(Sys.time()),sep='')) - -chart.Posn(portfolio.st, "GBPUSD") - -############################################################################### - -View(t(tradeStats(portfolio.st, 'GBPUSD'))) - -############################################################################### - -print(tradeQuantiles('forex', 'GBPUSD')) - -dev.new() - -### Uncomment to choose appropriate MAE of MFE graph - -chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MAE') -dev.new() -chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MFE') - -##### PLACE THIS BLOCK AT END OF DEMO SCRIPT ################### -# book = getOrderBook(port) -# stats = tradeStats(port) -# rets = PortfReturns(acct) -################################################################ Copied: pkg/quantstrat/demo/luxor.7.exit.and.risk.R (from rev 1539, pkg/quantstrat/demo/luxor.7.exit+risk.R) =================================================================== --- pkg/quantstrat/demo/luxor.7.exit.and.risk.R (rev 0) +++ pkg/quantstrat/demo/luxor.7.exit.and.risk.R 2013-10-21 18:34:05 UTC (rev 1544) @@ -0,0 +1,83 @@ +#!/usr/bin/Rscript --vanilla +# +# Jan Humme (@opentrades) - April 2013 +# +# Tested and found to work correctly using blotter r1457 +# +# After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) +# +# Paragraph 3.5: determination of appropriate exit and risk management + +require(quantstrat) + +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) + +##### PLACE DEMO AND TEST DATES HERE ################# +# +#if(isTRUE(options('in_test')$in_test)) +# # use test dates +# {initDate="2011-01-01" +# endDate="2012-12-31" +# } else +# # use demo defaults +# {initDate="1999-12-31" +# endDate=Sys.Date()} + +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) + +### blotter + +initPortf(portfolio.st, symbols='GBPUSD', initDate=initDate, currency='USD') +initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD') + +### quantstrat + +load.strategy('luxor') + +### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules + +#enable.rule('luxor', 'chain', 'StopLoss') +#enable.rule('luxor', 'chain', 'StopTrailing') +#enable.rule('luxor', 'chain', 'TakeProfit') + +### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules + +addPosLimit( + portfolio=portfolio.st, + symbol='GBPUSD', + timestamp=initDate, + maxpos=.orderqty) + +initOrders(portfolio.st, initDate=initDate) + +applyStrategy(strategy.st, portfolio.st, prefer='Open') + +View(getOrderBook(portfolio.st)[[portfolio.st]]$GBPUSD) + +############################################################################### + +updatePortf(portfolio.st, Symbols='GBPUSD', Dates=paste('::',as.Date(Sys.time()),sep='')) + +chart.Posn(portfolio.st, "GBPUSD") + +############################################################################### + +View(t(tradeStats(portfolio.st, 'GBPUSD'))) + +############################################################################### + +print(tradeQuantiles('forex', 'GBPUSD')) + +dev.new() + +### Uncomment to choose appropriate MAE of MFE graph + +chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MAE') +dev.new() +chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MFE') + +##### PLACE THIS BLOCK AT END OF DEMO SCRIPT ################### +# book = getOrderBook(port) +# stats = tradeStats(port) +# rets = PortfReturns(acct) +################################################################ Modified: pkg/quantstrat/man/rulePctEquity.Rd =================================================================== --- pkg/quantstrat/man/rulePctEquity.Rd 2013-10-19 17:26:25 UTC (rev 1543) +++ pkg/quantstrat/man/rulePctEquity.Rd 2013-10-21 18:34:05 UTC (rev 1544) @@ -51,7 +51,7 @@ add.rule(strategy.name, 'rulePctEquity', arguments=list(rebalance_on='months', trade.percent=.02, - refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])), + refprice=quote(last(getPrice(mktdata)[paste('::',timestamp,sep='')])[,1]), digits=0 ), type='rebalance', From noreply at r-forge.r-project.org Mon Oct 21 20:42:37 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 21 Oct 2013 20:42:37 +0200 (CEST) Subject: [Blotter-commits] r1545 - pkg/quantstrat/demo Message-ID: <20131021184238.0A4B01813BB@r-forge.r-project.org> Author: opentrades Date: 2013-10-21 20:42:37 +0200 (Mon, 21 Oct 2013) New Revision: 1545 Modified: pkg/quantstrat/demo/luxor.8.walk.forward.R Log: - fixed path name for luxor.include.R in luxor.8.walk.forward.R demo Modified: pkg/quantstrat/demo/luxor.8.walk.forward.R =================================================================== --- pkg/quantstrat/demo/luxor.8.walk.forward.R 2013-10-21 18:34:05 UTC (rev 1544) +++ pkg/quantstrat/demo/luxor.8.walk.forward.R 2013-10-21 18:42:37 UTC (rev 1545) @@ -8,9 +8,11 @@ # # Paragraph 3.7 walk forward analysis -source('luxor.include.R') -source('luxor.getSymbols.R') +require(quantstrat) +source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) +source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) + ### foreach and doMC require(foreach) @@ -24,8 +26,6 @@ ### quantstrat -require(quantstrat) - initOrders(portfolio.st, initDate=initDate) load.strategy(strategy.st) From noreply at r-forge.r-project.org Tue Oct 22 02:09:32 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 22 Oct 2013 02:09:32 +0200 (CEST) Subject: [Blotter-commits] r1546 - pkg/quantstrat/demo Message-ID: <20131022000932.D825F181474@r-forge.r-project.org> Author: efmrforge Date: 2013-10-22 02:09:32 +0200 (Tue, 22 Oct 2013) New Revision: 1546 Modified: pkg/quantstrat/demo/00Index Log: Corrected name of luxor.7 demo Modified: pkg/quantstrat/demo/00Index =================================================================== --- pkg/quantstrat/demo/00Index 2013-10-21 18:42:37 UTC (rev 1545) +++ pkg/quantstrat/demo/00Index 2013-10-22 00:09:32 UTC (rev 1546) @@ -16,7 +16,7 @@ luxor.6.paramset.stoploss.R Jaekle & Tomasini; Sections 3.5: paramset implementation for stoploss optimization luxor.6.paramset.stoptrailing.R Jaekle & Tomasini; Sections 3.5: paramset implementation for stop trailing optimization luxor.6.paramset.takeprofit.R Jaekle & Tomasini; Sections 3.5: paramset implementation for take profit optimization -luxor.7.exit+risk.R Jaekle & Tomasini; Sections 3.5: running with stoploss and/or stoptrailing and/or takeprofit +luxor.7.exit.and.risk.R Jaekle & Tomasini; Sections 3.5: running with stoploss and/or stoptrailing and/or takeprofit luxor.8.walk.forward.R Jaekle & Tomasini; Sections 6: walk forward analysis luxor.getSymbols.R Jaekle & Tomasini; reading symbols luxor.include.R Jaekle & Tomasini; Sections constants From noreply at r-forge.r-project.org Tue Oct 22 17:01:20 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 22 Oct 2013 17:01:20 +0200 (CEST) Subject: [Blotter-commits] r1547 - pkg/blotter/R Message-ID: <20131022150120.742E818446E@r-forge.r-project.org> Author: bodanker Date: 2013-10-22 17:01:19 +0200 (Tue, 22 Oct 2013) New Revision: 1547 Modified: pkg/blotter/R/updatePortf.R Log: - make de-duplication faster Modified: pkg/blotter/R/updatePortf.R =================================================================== --- pkg/blotter/R/updatePortf.R 2013-10-22 00:09:32 UTC (rev 1546) +++ pkg/blotter/R/updatePortf.R 2013-10-22 15:01:19 UTC (rev 1547) @@ -82,14 +82,22 @@ # 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) ) - } + # extract duplicated rows; get last row for each duplicate 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) + # get the last value + cLast <- c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value') + lastCols <- summary.dups[which(ds),cLast] + # sum values + cSums <- c('Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') + # take cumulative sum; keep last value for each duplicate + sumCols <- cumsum(summary.dups[,cSums])[which(ds),cSums] + # subtract previous value from current value, since we used cumsum + sumColsLag <- lag(sumCols) + sumColsLag[1,] <- 0 + sumCols <- sumCols - sumColsLag + slist <- merge(sumCols,lastCols) # combine aggregated objects + slist <- slist[,colnames(summary)] # order columns summary <- rbind(summary[!d,], slist) # put it all back together } From noreply at r-forge.r-project.org Thu Oct 24 11:30:52 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 24 Oct 2013 11:30:52 +0200 (CEST) Subject: [Blotter-commits] r1548 - in pkg/quantstrat: R man Message-ID: <20131024093052.854A8180484@r-forge.r-project.org> Author: bodanker Date: 2013-10-24 11:30:51 +0200 (Thu, 24 Oct 2013) New Revision: 1548 Modified: pkg/quantstrat/R/paramsets.R pkg/quantstrat/man/apply.paramset.Rd Log: - add '...' to apply.paramset, and pass to applyStrategy and updatePortf Modified: pkg/quantstrat/R/paramsets.R =================================================================== --- pkg/quantstrat/R/paramsets.R 2013-10-22 15:01:19 UTC (rev 1547) +++ pkg/quantstrat/R/paramsets.R 2013-10-24 09:30:51 UTC (rev 1548) @@ -352,12 +352,13 @@ #' @param packages a vector specifying names of R packages to be loaded by the slave, default NULL #' @param audit a user-specified environment to store a copy of all portfolios, orderbooks and other data from the tests, or NULL to trash this information #' @param verbose return full information, in particular the .blotter environment, default FALSE +#' @param ... any other passthru parameters #' #' @author Jan Humme #' @export #' @seealso \code{\link{add.distribution.constraint}}, \code{\link{add.distribution.constraint}}, \code{\link{delete.paramset}} -apply.paramset <- function(strategy.st, paramset.label, portfolio.st, account.st, mktdata=NULL, nsamples=0, user.func=NULL, user.args=NULL, calc='slave', audit=NULL, packages=NULL, verbose=FALSE) +apply.paramset <- function(strategy.st, paramset.label, portfolio.st, account.st, mktdata=NULL, nsamples=0, user.func=NULL, user.args=NULL, calc='slave', audit=NULL, packages=NULL, verbose=FALSE, ...) { must.have.args(match.call(), c('strategy.st', 'paramset.label', 'portfolio.st')) @@ -375,6 +376,7 @@ param.combos <- expand.distributions(distributions) param.combos <- apply.constraints(constraints, distributions, param.combos) + rownames(param.combos) <- NULL # reset rownames if(nsamples > 0) param.combos <- select.samples(nsamples, param.combos) @@ -473,7 +475,7 @@ } strategy <- install.param.combo(strategy, param.combo, paramset.label) - applyStrategy(strategy, portfolios=result$portfolio.st, mktdata=mktdata, verbose=verbose) + applyStrategy(strategy, portfolios=result$portfolio.st, mktdata=mktdata, verbose=verbose, ...) if(exists('redisContext')) { @@ -487,7 +489,7 @@ if(calc == 'slave') { - updatePortf(result$portfolio.st, Dates=paste('::',as.Date(Sys.time()),sep=''), Prices=mktdata) + updatePortf(result$portfolio.st, Dates=paste('::',as.Date(Sys.time()),sep=''), Prices=mktdata, ...) result$tradeStats <- tradeStats(result$portfolio.st) if(!is.null(user.func) && !is.null(user.args)) Modified: pkg/quantstrat/man/apply.paramset.Rd =================================================================== --- pkg/quantstrat/man/apply.paramset.Rd 2013-10-22 15:01:19 UTC (rev 1547) +++ pkg/quantstrat/man/apply.paramset.Rd 2013-10-24 09:30:51 UTC (rev 1548) @@ -5,7 +5,7 @@ apply.paramset(strategy.st, paramset.label, portfolio.st, account.st, mktdata = NULL, nsamples = 0, user.func = NULL, user.args = NULL, calc = "slave", - audit = NULL, packages = NULL, verbose = FALSE) + audit = NULL, packages = NULL, verbose = FALSE, ...) } \arguments{ \item{strategy.st}{the name of the strategy object} @@ -49,6 +49,8 @@ \item{verbose}{return full information, in particular the .blotter environment, default FALSE} + + \item{...}{any other passthru parameters} } \description{ This function will run applyStrategy() on portfolio.st, From noreply at r-forge.r-project.org Thu Oct 24 14:34:33 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 24 Oct 2013 14:34:33 +0200 (CEST) Subject: [Blotter-commits] r1549 - pkg/blotter/R Message-ID: <20131024123433.553DC1859A2@r-forge.r-project.org> Author: bodanker Date: 2013-10-24 14:34:33 +0200 (Thu, 24 Oct 2013) New Revision: 1549 Modified: pkg/blotter/R/getPortfolio.R Log: - handle case where portfolio may already be a list - add class, currency, and initDate attributes Modified: pkg/blotter/R/getPortfolio.R =================================================================== --- pkg/blotter/R/getPortfolio.R 2013-10-24 09:30:51 UTC (rev 1548) +++ pkg/blotter/R/getPortfolio.R 2013-10-24 12:34:33 UTC (rev 1549) @@ -23,9 +23,15 @@ { pname<-Portfolio oport<- .getPortfolio(Portfolio, envir=envir) - port <- as.list.environment(oport) - port$symbols<-list() - port$symbols <- lapply(oport$symbols, as.list.environment) + if(is.environment(oport)) + port <- as.list.environment(oport) + else + port <- oport + port$symbols <- lapply(oport$symbols, function(s) if(is.environment(s)) as.list.environment(s) else s) + + class(port) <- class(oport) + attr(port, "currency") <- attr(oport, "currency") + attr(port, "initDate") <- attr(oport, "initDate") if(!is.null(Dates)){ message("date subsetting not yet supported") From noreply at r-forge.r-project.org Thu Oct 24 21:13:56 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 24 Oct 2013 21:13:56 +0200 (CEST) Subject: [Blotter-commits] r1550 - pkg/quantstrat/R Message-ID: <20131024191356.A538F18621F@r-forge.r-project.org> Author: opentrades Date: 2013-10-24 21:13:56 +0200 (Thu, 24 Oct 2013) New Revision: 1550 Modified: pkg/quantstrat/R/paramsets.R Log: - using registerDoSEQ() is now handled differently in appl.paramset() so it does noy wipe the .blotter and .startegy environments Modified: pkg/quantstrat/R/paramsets.R =================================================================== --- pkg/quantstrat/R/paramsets.R 2013-10-24 12:34:33 UTC (rev 1549) +++ pkg/quantstrat/R/paramsets.R 2013-10-24 19:13:56 UTC (rev 1550) @@ -445,8 +445,11 @@ # also, environments persist in each slave, so data may be accumulating # for each transition through the foreach loop # - rm(list=ls(pos=.blotter), pos=.blotter) - rm(list=ls(pos=.strategy), pos=.strategy) + if(!getDoSeqRegistered()) + { + rm(list=ls(pos=.blotter), pos=.blotter) + rm(list=ls(pos=.strategy), pos=.strategy) + } list2env(env.instrument, envir=FinancialInstrument:::.instrument) From noreply at r-forge.r-project.org Sat Oct 26 21:30:50 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 26 Oct 2013 21:30:50 +0200 (CEST) Subject: [Blotter-commits] r1551 - in pkg/blotter: . R man Message-ID: <20131026193050.320DF186276@r-forge.r-project.org> Author: braverock Date: 2013-10-26 21:30:49 +0200 (Sat, 26 Oct 2013) New Revision: 1551 Modified: pkg/blotter/.Rbuildignore pkg/blotter/NAMESPACE pkg/blotter/R/tradeStats.R pkg/blotter/man/dailyTxnPL.Rd Log: - add more documentation for dailyTxnPL and dailyEqPL Modified: pkg/blotter/.Rbuildignore =================================================================== --- pkg/blotter/.Rbuildignore 2013-10-24 19:13:56 UTC (rev 1550) +++ pkg/blotter/.Rbuildignore 2013-10-26 19:30:49 UTC (rev 1551) @@ -1 +1,3 @@ R/.vimrc +^.*\.Rproj$ +^\.Rproj\.user$ Modified: pkg/blotter/NAMESPACE =================================================================== --- pkg/blotter/NAMESPACE 2013-10-24 19:13:56 UTC (rev 1550) +++ pkg/blotter/NAMESPACE 2013-10-26 19:30:49 UTC (rev 1551) @@ -1,4 +1,3 @@ -useDynLib(blotter) export(.getPortfolio) export(AcctReturns) export(PortfReturns) @@ -36,3 +35,4 @@ export(updateEndEq) export(updatePortf) importFrom(zoo,as.Date) +useDynLib(blotter) Modified: pkg/blotter/R/tradeStats.R =================================================================== --- pkg/blotter/R/tradeStats.R 2013-10-24 19:13:56 UTC (rev 1550) +++ pkg/blotter/R/tradeStats.R 2013-10-26 19:30:49 UTC (rev 1551) @@ -224,11 +224,19 @@ #' #' designed to collate information for high frequency portfolios #' +#' If you do not pass \code{Symbols}, then all symbols in the provided +#' \code{Portfolios} will be used. +#' +#' The daily P&L is calculated from \code{Net.Txn.Realized.PL} if by +#' \code{dailyTxnPL} +#' and from \code{Net.Trading.PL} by \code{dailyEqPL} +#' #' @aliases dailyEqPL #' @param Portfolios portfolio string #' @param Symbols character vector of symbol strings #' @param drop.time remove time component of POSIX datestamp (if any), default TRUE #' @author Brian G. Peterson +#' @return a multi-column \code{xts} time series, one column per symbol, one row per day #' @seealso tradeStats #' @export dailyTxnPL <- function(Portfolios, Symbols, drop.time=TRUE) Modified: pkg/blotter/man/dailyTxnPL.Rd =================================================================== --- pkg/blotter/man/dailyTxnPL.Rd 2013-10-24 19:13:56 UTC (rev 1550) +++ pkg/blotter/man/dailyTxnPL.Rd 2013-10-26 19:30:49 UTC (rev 1551) @@ -15,10 +15,22 @@ \item{drop.time}{remove time component of POSIX datestamp (if any), default TRUE} } +\value{ + a multi-column \code{xts} time series, one column per + symbol, one row per day +} \description{ designed to collate information for high frequency portfolios } +\details{ + If you do not pass \code{Symbols}, then all symbols in + the provided \code{Portfolios} will be used. + + The daily P&L is calculated from + \code{Net.Txn.Realized.PL} if by \code{dailyTxnPL} and + from \code{Net.Trading.PL} by \code{dailyEqPL} +} \author{ Brian G. Peterson } From noreply at r-forge.r-project.org Sun Oct 27 01:09:00 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 27 Oct 2013 01:09:00 +0200 (CEST) Subject: [Blotter-commits] r1552 - pkg/blotter/R Message-ID: <20131026230901.04143184FD6@r-forge.r-project.org> Author: braverock Date: 2013-10-27 01:09:00 +0200 (Sun, 27 Oct 2013) New Revision: 1552 Modified: pkg/blotter/R/tradeStats.R Log: - change to use getPortfolio so we don't change the environment Modified: pkg/blotter/R/tradeStats.R =================================================================== --- pkg/blotter/R/tradeStats.R 2013-10-26 19:30:49 UTC (rev 1551) +++ pkg/blotter/R/tradeStats.R 2013-10-26 23:09:00 UTC (rev 1552) @@ -243,18 +243,10 @@ { ret <- NULL for (Portfolio in Portfolios){ - ## Error Handling Borrowed from getPortfolio pname <- Portfolio - if (!grepl("portfolio\\.", pname)) - Portfolio <- try(get(paste("portfolio", pname, sep = "."), envir = .blotter), silent=TRUE) - else Portfolio <- try(get(pname, envir = .blotter), silent=TRUE) - if (inherits(Portfolio, "try-error")) - stop(paste("Portfolio", pname, " not found, use initPortf() to create a new portfolio")) - if (!inherits(Portfolio, "portfolio")) - stop("Portfolio", pname, "passed is not the name of a portfolio object.") + Portfolio <- getPortfolio(pname) - ## FIXME: need a way to define symbols for each portfolio if(missing(Symbols)) symbols <- ls(Portfolio$symbols) else symbols <- Symbols @@ -286,18 +278,9 @@ { ret <- NULL for (Portfolio in Portfolios){ - ## Error Handling Borrowed from getPortfolio pname <- Portfolio - if (!grepl("portfolio\\.", pname)) - Portfolio <- try(get(paste("portfolio", pname, sep = "."), envir = .blotter), silent=TRUE) - else Portfolio <- try(get(pname, envir = .blotter), silent=TRUE) - if (inherits(Portfolio, "try-error")) - stop(paste("Portfolio", pname, " not found, use initPortf() to create a new portfolio")) - if (!inherits(Portfolio, "portfolio")) - stop("Portfolio", pname, "passed is not the name of a portfolio object.") + Portfolio <- getPortfolio(pname) - - ## FIXME: need a way to define symbols for each portfolio if(missing(Symbols)) symbols <- ls(Portfolio$symbols) else symbols <- Symbols From noreply at r-forge.r-project.org Sun Oct 27 18:33:00 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 27 Oct 2013 18:33:00 +0100 (CET) Subject: [Blotter-commits] r1553 - in pkg/quantstrat: . R man Message-ID: <20131027173300.5BB0E185DCE@r-forge.r-project.org> Author: braverock Date: 2013-10-27 18:33:00 +0100 (Sun, 27 Oct 2013) New Revision: 1553 Modified: pkg/quantstrat/NAMESPACE pkg/quantstrat/R/strategy.R pkg/quantstrat/man/applyStrategy.Rd Log: - make memory usage in applyStrategy more efficient with an environment - only accumulate ret list if debug=TRUE (replaces verbose arg) Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-10-26 23:09:00 UTC (rev 1552) +++ pkg/quantstrat/NAMESPACE 2013-10-27 17:33:00 UTC (rev 1553) @@ -1,5 +1,5 @@ +export(add.distribution) export(add.distribution.constraint) -export(add.distribution) export(add.indicator) export(add.init) export(add.rule) @@ -11,10 +11,11 @@ export(applyParameter) export(applyRules) export(applySignals) +export(applyStrategy) export(applyStrategy.rebalancing) -export(applyStrategy) +export(applyStrategy.rebalancing.training) +export(chart.forward) export(chart.forward.training) -export(chart.forward) export(delete.paramset) export(enable.rule) export(get.orderbook) @@ -23,6 +24,7 @@ export(getOrders) export(getParameterTable) export(getPosLimit) +export(getStrategy) export(initOrders) export(initStrategy) export(is.strategy) Modified: pkg/quantstrat/R/strategy.R =================================================================== --- pkg/quantstrat/R/strategy.R 2013-10-26 23:09:00 UTC (rev 1552) +++ pkg/quantstrat/R/strategy.R 2013-10-27 17:33:00 UTC (rev 1553) @@ -92,7 +92,7 @@ #' @param mktdata an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL #' @param parameters named list of parameters to be applied during evaluation of the strategy, default NULL #' @param ... any other passthru parameters -#' @param verbose if TRUE, return output list +#' @param debug if TRUE, return output list #' @param symbols character vector identifying symbols to initialize a portfolio for, default NULL #' @param initStrat whether to use (experimental) initialization code, default FALSE #' @param updateStrat whether to use (experimental) wrapup code, default FALSE @@ -100,72 +100,101 @@ #' @seealso \code{\link{strategy}}, \code{\link{applyIndicators}}, #' \code{\link{applySignals}}, \code{\link{applyRules}}, #' \code{\link{initStrategy}}, -applyStrategy <- function(strategy , portfolios, mktdata=NULL , parameters=NULL, ..., verbose=TRUE, symbols=NULL, initStrat=FALSE, updateStrat=FALSE ) { - #TODO add Date subsetting - #TODO add saving of modified market data +applyStrategy <- function(strategy , + portfolios, + mktdata=NULL , + parameters=NULL, + ..., + debug=FALSE, + symbols=NULL, + initStrat=FALSE, + updateStrat=FALSE ) { + + #TODO add saving of modified market data + + if(isTRUE(debug)) ret<-list() - ret<-list() - if (!is.strategy(strategy)) { - strategy<-try(getStrategy(strategy)) - if(inherits(strategy,"try-error")) - stop ("You must supply an object of type 'strategy'.") - } - - if (missing(mktdata) || is.null(mktdata)) load.mktdata=TRUE else load.mktdata=FALSE - - for (portfolio in portfolios) { - - # 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) - - # 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, ... ) - - 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 - } - - # call updateStrategy - if(isTRUE(updateStrat)) updateStrategy(strategy, portfolio, Symbols=symbols, ...=...) - - } - - if(verbose) return(ret) + strategy<-try(getStrategy(strategy)) + if(inherits(strategy,"try-error")) + stop ("You must supply an object of type 'strategy'.") + } + + if (missing(mktdata) || is.null(mktdata)) load.mktdata=TRUE else load.mktdata=FALSE + + for (portfolio in portfolios) { + + # call initStrategy + if(isTRUE(initStrat)) initStrategy(strategy=strategy, portfolio, symbols, ...=...) + + if(isTRUE(debug)) ret[[portfolio]]<-list() # this is slot [[i]] which we will use later + pobj<-.getPortfolio(portfolio) + symbols<- ls(pobj$symbols) + sret<-new.env(hash=TRUE) + + 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 + sret$indicators <- NULL + } + + # loop over signal generators + sret$signals <- applySignals(strategy=strategy, mktdata=mktdata, parameters=parameters, ... ) + + if(inherits(sret$signals,"xts") & nrow(mktdata)==nrow(sret$signals)){ + mktdata<-sret$signals + sret$signals<-NULL + } + + #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)} + + if(isTRUE(debug)) ret[[portfolio]][[symbol]]<-sret + } + + # call updateStrategy + if(isTRUE(updateStrat)) updateStrategy(strategy, portfolio, Symbols=symbols, ...=...) + + } + + if(isTRUE(debug)) return(ret) } #' test to see if object is of type 'strategy' @@ -182,7 +211,8 @@ #' @aliases #' get.strategy #' getStrategy -#' @export +#' @export get.strategy +#' @export getStrategy 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) ) { Modified: pkg/quantstrat/man/applyStrategy.Rd =================================================================== --- pkg/quantstrat/man/applyStrategy.Rd 2013-10-26 23:09:00 UTC (rev 1552) +++ pkg/quantstrat/man/applyStrategy.Rd 2013-10-27 17:33:00 UTC (rev 1553) @@ -3,7 +3,7 @@ \title{apply the strategy to arbitrary market data} \usage{ applyStrategy(strategy, portfolios, mktdata = NULL, - parameters = NULL, ..., verbose = TRUE, symbols = NULL, + parameters = NULL, ..., debug = FALSE, symbols = NULL, initStrat = FALSE, updateStrat = FALSE) } \arguments{ @@ -22,7 +22,7 @@ \item{...}{any other passthru parameters} - \item{verbose}{if TRUE, return output list} + \item{debug}{if TRUE, return output list} \item{symbols}{character vector identifying symbols to initialize a portfolio for, default NULL} From noreply at r-forge.r-project.org Mon Oct 28 17:53:59 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 28 Oct 2013 17:53:59 +0100 (CET) Subject: [Blotter-commits] r1554 - pkg/blotter/R Message-ID: <20131028165359.C1E2F185C85@r-forge.r-project.org> Author: braverock Date: 2013-10-28 17:53:59 +0100 (Mon, 28 Oct 2013) New Revision: 1554 Modified: pkg/blotter/R/updatePosPL.R Log: - rearrange to avoid $<- method dispatch - only calculate the currency table if the portfolio currency is different from the symbol currency Modified: pkg/blotter/R/updatePosPL.R =================================================================== --- pkg/blotter/R/updatePosPL.R 2013-10-27 17:33:00 UTC (rev 1553) +++ pkg/blotter/R/updatePosPL.R 2013-10-28 16:53:59 UTC (rev 1554) @@ -53,10 +53,10 @@ #subset Prices by dateRange too... Prices<-prices[dateRange] - if(nrow(Prices)<1) { - Prices=xts(cbind(Prices=as.numeric(last(prices[paste('::',endDate,sep='')]))),as.Date(endDate)) - warning('no Prices available for ',Symbol,' in ',dateRange,' : using last available price and marking to ', endDate) - } + if(nrow(Prices)<1) { + Prices=xts(cbind(Prices=as.numeric(last(prices[paste('::',endDate,sep='')]))),as.Date(endDate)) + warning('no Prices available for ',Symbol,' in ',dateRange,' : using last available price and marking to ', endDate) + } # Prices <- Prices[dateRange][,1] # only take the first column, if there is more than one @@ -84,67 +84,65 @@ #browser() - if(is.na(tmpPL$Prices[1])){ + if(is.na(tmpPL[,'Prices'][1])){ #first price is NA, it would be nice to fill it in with a previous last valid price fprice <- last(prices[paste('::',startDate,sep='')]) - if (length(fprice)==1) tmpPL$Prices[1] <- fprice + if (length(fprice)==1) tmpPL[,'Prices'][1] <- fprice } # na.locf any missing prices with last observation (this assumption seems the only rational one for vectorization) - tmpPL$Prices <- na.locf(tmpPL$Prices) + tmpPL[,'Prices'] <- na.locf( tmpPL[,'Prices']) - # na.locf Pos.Qty,Con.Mult,Pos.Avg.Cost to instantiate $posPL new rows - #tmpPL$Pos.Qty.1 <- na.locf(tmpPL$Pos.Qty.1) - #lagPosQty<-Lag(tmpPL$Pos.Qty.1) - tmpPL$Pos.Qty <- ifelse(is.na(tmpPL$Pos.Qty) & !is.na(tmpPL$Pos.Qty.1), tmpPL$Pos.Qty.1, tmpPL$Pos.Qty) - #tmpPL$Pos.Qty <- ifelse(is.na(tmpPL$Pos.Qty) & !is.na(lagPosQty), tmpPL$Pos.Qty.1, tmpPL$Pos.Qty) - tmpPL$Pos.Qty <- na.locf(tmpPL$Pos.Qty) + #select among our merged columns + tmpPL[,'Pos.Qty'] <- ifelse(is.na( tmpPL[,'Pos.Qty']) & !is.na( tmpPL[,'Pos.Qty.1']), tmpPL[,'Pos.Qty.1'], tmpPL[,'Pos.Qty']) + tmpPL[,'Con.Mult.1'] <- ifelse(is.na( tmpPL[,'Con.Mult']) & !is.na( tmpPL[,'Con.Mult.1']) , tmpPL[,'Con.Mult.1'], tmpPL[,'Con.Mult']) + tmpPL[,'Pos.Avg.Cost'] <- ifelse(is.na( tmpPL[,'Pos.Avg.Cost']) & !is.na( tmpPL[,'Pos.Avg.Cost.1']) , tmpPL[,'Pos.Avg.Cost.1'], tmpPL[,'Pos.Avg.Cost']) + + # na.locf Pos.Qty,Con.Mult,Pos.Avg.Cost to instantiate $posPL new rows + columns<-c('Pos.Qty','Con.Mult','Con.Mult.1','Pos.Avg.Cost','Pos.Avg.Cost.1') + tmpPL[,columns] <- na.locf(tmpPL[,columns]) - - #TODO check for instrument multiplier rather than doing all this messing around, if possible. - tmpPL$Con.Mult.1 <- na.locf(tmpPL$Con.Mult.1) - tmpPL$Con.Mult.1 <- ifelse(is.na(tmpPL$Con.Mult) & !is.na(tmpPL$Con.Mult.1) , tmpPL$Con.Mult.1, tmpPL$Con.Mult) - tmpPL$Con.Mult <- na.locf(tmpPL$Con.Mult) - tmpPL$Con.Mult <- na.locf(tmpPL$Con.Mult, fromLast=TRUE) # carry NA's backwards too, might cause problems with options contracts that change multiplier - tmpPL$Con.Mult <- ifelse(is.na(tmpPL$Con.Mult) ,1, tmpPL$Con.Mult) + #TODO check for instrument multiplier rather than doing all this messing around, if possible. + #tmpPL[,'Con.Mult.1'] <- na.locf( tmpPL[,'Con.Mult.1']) + #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Con.Mult']) + #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Con.Mult'], fromLast=TRUE) # carry NA's backwards too, might cause problems with options contracts that change multiplier + tmpPL[,'Con.Mult'] <- ifelse(is.na( tmpPL[,'Con.Mult']) ,1, tmpPL[,'Con.Mult']) + #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Pos.Avg.Cost.1']) + #tmpPL[,'Pos.Avg.Cost'] <- na.locf( tmpPL[,'Pos.Avg.Cost']) - tmpPL$Pos.Avg.Cost.1 <- na.locf(tmpPL$Pos.Avg.Cost.1) - tmpPL$Pos.Avg.Cost <- ifelse(is.na(tmpPL$Pos.Avg.Cost) & !is.na(tmpPL$Pos.Avg.Cost.1) ,tmpPL$Pos.Avg.Cost.1, tmpPL$Pos.Avg.Cost) - tmpPL$Pos.Avg.Cost <- na.locf(tmpPL$Pos.Avg.Cost) - # zerofill Txn.Value, Txn.Fees - tmpPL$Txn.Value <- ifelse(is.na(tmpPL$Txn.Value),0, tmpPL$Txn.Value) + tmpPL[,'Txn.Value'] <- ifelse(is.na( tmpPL[,'Txn.Value']),0, tmpPL[,'Txn.Value']) - tmpPL$Txn.Fees <- ifelse(is.na(tmpPL$Txn.Fees) ,0, tmpPL$Txn.Fees) + tmpPL[,'Txn.Fees'] <- ifelse(is.na(tmpPL[,'Txn.Fees']) ,0, tmpPL[,'Txn.Fees']) # matrix calc Pos.Qty * Price * Con.Mult to get Pos.Value - tmpPL$Pos.Value <- tmpPL$Pos.Qty * tmpPL$Con.Mult * tmpPL$Prices + tmpPL[,'Pos.Value'] <- tmpPL[,'Pos.Qty'] * tmpPL[,'Con.Mult'] * tmpPL[,'Prices'] - LagValue<-Lag(tmpPL$Pos.Value) + LagValue<-Lag(tmpPL[,'Pos.Value']) LagValue<-ifelse(is.na(LagValue),0,LagValue) # needed to avoid a possible NA on the first value that would mess up the Gross.Trading.PL calc - tmpPL$Gross.Trading.PL <- tmpPL$Pos.Value- LagValue - tmpPL$Txn.Value + tmpPL[,'Gross.Trading.PL'] <- tmpPL[,'Pos.Value']- LagValue - tmpPL[,'Txn.Value'] # alternate matrix calc for Realized&Unrealized PL that is only dependent on Txn PL and Gross.Trading.PL - tmpPL$Net.Txn.Realized.PL <- ifelse(is.na(tmpPL$Net.Txn.Realized.PL),0,tmpPL$Net.Txn.Realized.PL) - tmpPL$Gross.Txn.Realized.PL <- ifelse(is.na(tmpPL$Gross.Txn.Realized.PL),0,tmpPL$Gross.Txn.Realized.PL) + tmpPL[,'Net.Txn.Realized.PL'] <- ifelse(is.na(tmpPL[,'Net.Txn.Realized.PL']),0,tmpPL[,'Net.Txn.Realized.PL']) + tmpPL[,'Gross.Txn.Realized.PL'] <- ifelse(is.na(tmpPL[,'Gross.Txn.Realized.PL']),0,tmpPL[,'Gross.Txn.Realized.PL']) - #tmpPL$Gross.Trading.PL <- tmpPL$Pos.Value - (tmpPL$Pos.Qty*tmpPL$Pos.Avg.Cost) + tmpPL$Gross.Txn.Realized.PL - tmpPL$Period.Realized.PL <- tmpPL$Gross.Txn.Realized.PL - tmpPL$Period.Unrealized.PL <- round(tmpPL$Gross.Trading.PL - tmpPL$Period.Realized.PL,2) + #tmpPL[,'Gross.Trading.PL'] <- tmpPL[,'Pos.Value'] - (tmpPL[,'Pos.Qty']* tmpPL[,'Pos.Avg.Cost']) + tmpPL[,'Gross.Txn.Realized.PL'] + tmpPL$Period.Realized.PL <- tmpPL[,'Gross.Txn.Realized.PL'] + tmpPL$Period.Unrealized.PL <- round(tmpPL[,'Gross.Trading.PL'] - tmpPL$Period.Realized.PL,2) # matrix calc Net.Trading.PL as Gross.Trading.PL + Txn.Fees - tmpPL$Net.Trading.PL <- tmpPL$Gross.Trading.PL + tmpPL$Txn.Fees + tmpPL[,'Net.Trading.PL'] <- tmpPL[,'Gross.Trading.PL'] + tmpPL[,'Txn.Fees'] # Ccy.Mult for this step is always 1 - tmpPL$Ccy.Mult<-rep(1,nrow(tmpPL)) + tmpPL[,'Ccy.Mult']<-rep(1,nrow(tmpPL)) # reorder,discard columns for insert into portfolio object tmpPL <- tmpPL[,c('Pos.Qty', 'Con.Mult', 'Ccy.Mult', 'Pos.Value', 'Pos.Avg.Cost', 'Txn.Value', 'Period.Realized.PL', 'Period.Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')] # rbind to $posPL slot tmpPL <- tmpPL[dateRange] #subset to get rid of any prior period Txn or PosPL rows we inserted - Portfolio$symbols[[Symbol]]$posPL<-rbind(Portfolio$symbols[[Symbol]]$posPL,tmpPL) + Portfolio[['symbols']][[Symbol]][['posPL']]<-rbind(Portfolio[['symbols']][[Symbol]][['posPL']],tmpPL) @@ -200,24 +198,26 @@ CcyMult<-1/CcyMult } - - #multiply the correct columns - columns<-c('Pos.Value', 'Txn.Value', 'Pos.Avg.Cost', 'Period.Realized.PL', 'Period.Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') - TmpPeriods[,columns]<-TmpPeriods[,columns]*CcyMult - TmpPeriods[,'Ccy.Mult']<-CcyMult - - #add change in Pos.Value in base currency - LagValue <- as.numeric(last(Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]]$Pos.Value)) - if(length(LagValue)==0) LagValue <- 0 - LagPos.Value <- lag(TmpPeriods$Pos.Value,1) - LagPos.Value[1] <- LagValue - CcyMove <- TmpPeriods$Pos.Value - LagPos.Value - TmpPeriods$Txn.Value - TmpPeriods$Period.Unrealized.PL - TmpPeriods$Period.Realized.PL - TmpPeriods$Gross.Trading.PL <- TmpPeriods$Gross.Trading.PL + CcyMove - TmpPeriods$Net.Trading.PL <- TmpPeriods$Net.Trading.PL + CcyMove - TmpPeriods$Period.Unrealized.PL <- TmpPeriods$Period.Unrealized.PL + CcyMove - - #stick it in posPL.ccy - Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]]<-rbind(Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]],TmpPeriods) + if (length(CcyMult)==1 && CcyMult==1){ + Portfolio[['symbols']][[Symbol]][[paste('posPL',p.ccy.str,sep='.')]] <- Portfolio[['symbols']][[Symbol]][['posPL']] + } else { + #multiply the correct columns + columns<-c('Pos.Value', 'Txn.Value', 'Pos.Avg.Cost', 'Period.Realized.PL', 'Period.Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL') + TmpPeriods[,columns]<-TmpPeriods[,columns]*CcyMult + TmpPeriods[,'Ccy.Mult']<-CcyMult + + #add change in Pos.Value in base currency + LagValue <- as.numeric(last(Portfolio[['symbols']][[Symbol]][[paste('posPL',p.ccy.str,sep='.')]][,'Pos.Value'])) + if(length(LagValue)==0) LagValue <- 0 + LagPos.Value <- lag(TmpPeriods[,'Pos.Value'],1) + LagPos.Value[1] <- LagValue + CcyMove <- TmpPeriods[,'Pos.Value'] - LagPos.Value - TmpPeriods[,'Txn.Value'] - TmpPeriods[,'Period.Unrealized.PL'] - TmpPeriods[,'Period.Realized.PL'] + columns<-c('Gross.Trading.PL','Net.Trading.PL','Period.Unrealized') + TmpPeriods[,columns] <- TmpPeriods[,columns] + CcyMove + + #stick it in posPL.ccy + Portfolio[['symbols']][[Symbol]][[paste('posPL',p.ccy.str,sep='.')]]<-rbind(Portfolio[['symbols']][[Symbol]][[paste('posPL',p.ccy.str,sep='.')]],TmpPeriods) + } #portfolio is already an environment, it's been updated in place #assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) From noreply at r-forge.r-project.org Tue Oct 29 13:57:59 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 29 Oct 2013 13:57:59 +0100 (CET) Subject: [Blotter-commits] r1555 - pkg/blotter/demo Message-ID: <20131029125759.B4AFB18575C@r-forge.r-project.org> Author: braverock Date: 2013-10-29 13:57:59 +0100 (Tue, 29 Oct 2013) New Revision: 1555 Modified: pkg/blotter/demo/turtles.R Log: - fix turtles demo to work without subsetting Dates. - NOTE: this could be further improved, likely with a different format string Modified: pkg/blotter/demo/turtles.R =================================================================== --- pkg/blotter/demo/turtles.R 2013-10-28 16:53:59 UTC (rev 1554) +++ pkg/blotter/demo/turtles.R 2013-10-29 12:57:59 UTC (rev 1555) @@ -1,6 +1,13 @@ # - Turtle System #1 +# Author: Josh Ulrich +## NOTE: if you are trying to crete trading systems, +## the 'quantstrat' package is more likely to meet your needs. +## +## This demo is designed to show how all the parts of blotter fit together, +## it is not optimized for efficiency. + # required libraries require(quantmod) require(TTR) @@ -168,9 +175,9 @@ # Maintain Position } # End symbol loop # Now that we've updated all of our trades, its time to mark the book - updatePortf(Portfolio = portfolio, Dates = CurrentDate) - updateAcct(account, Dates = CurrentDate) - updateEndEq(account, Dates = CurrentDate) + updatePortf(Portfolio = portfolio) + updateAcct(account) + updateEndEq(account) } # End dates loop # Final values From noreply at r-forge.r-project.org Tue Oct 29 14:52:25 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 29 Oct 2013 14:52:25 +0100 (CET) Subject: [Blotter-commits] r1556 - pkg/quantstrat Message-ID: <20131029135225.5D272185AB5@r-forge.r-project.org> Author: braverock Date: 2013-10-29 14:52:24 +0100 (Tue, 29 Oct 2013) New Revision: 1556 Modified: pkg/quantstrat/NAMESPACE Log: - remove export(applyStrategy.rebalancing.training) errantly added in r1553 Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2013-10-29 12:57:59 UTC (rev 1555) +++ pkg/quantstrat/NAMESPACE 2013-10-29 13:52:24 UTC (rev 1556) @@ -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) From noreply at r-forge.r-project.org Wed Oct 30 17:47:23 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 30 Oct 2013 17:47:23 +0100 (CET) Subject: [Blotter-commits] r1557 - pkg/blotter/R Message-ID: <20131030164723.6A07B184EDC@r-forge.r-project.org> Author: bodanker Date: 2013-10-30 17:47:23 +0100 (Wed, 30 Oct 2013) New Revision: 1557 Modified: pkg/blotter/R/updatePosPL.R Log: - refactor .updatePosPL for speed and memory use Modified: pkg/blotter/R/updatePosPL.R =================================================================== --- pkg/blotter/R/updatePosPL.R 2013-10-29 13:52:24 UTC (rev 1556) +++ pkg/blotter/R/updatePosPL.R 2013-10-30 16:47:23 UTC (rev 1557) @@ -79,63 +79,60 @@ Txns <- last(Portfolio$symbols[[Symbol]]$txn[paste('::',startDate,sep='')]) } - # line up transaction with Dates list - tmpPL <- merge(Txns, priorPL, Prices) # most Txn columns will get discarded later, as will the rows from 'before' the startDate + # Get values frop priorPL into Txns; only keep columns we need from Txns + # NOTE: There will usually be fewer transactions than price observations, + # so do as much as possible before merging with potentially large price data + TxnsCols <- c('Txn.Value','Txn.Fees','Gross.Txn.Realized.PL','Net.Txn.Realized.PL','Pos.Qty','Pos.Avg.Cost','Con.Mult') + tmpPL <- merge(Txns[,TxnsCols], xts(,index(priorPL))) + if(is.na(tmpPL[1,'Pos.Qty'])) + tmpPL[1,'Pos.Qty'] <- priorPL[1,'Pos.Qty'] + if(is.na(tmpPL[1,'Con.Mult'])) + tmpPL[1,'Con.Mult'] <- priorPL[1,'Con.Mult'] + if(is.na(tmpPL[1,'Pos.Avg.Cost'])) + tmpPL[1,'Pos.Avg.Cost'] <- priorPL[1,'Pos.Avg.Cost'] - #browser() + # Now merge with prices + tmpPL <- merge(tmpPL, Prices) - if(is.na(tmpPL[,'Prices'][1])){ + if(is.na(tmpPL[1,'Prices'])){ #first price is NA, it would be nice to fill it in with a previous last valid price fprice <- last(prices[paste('::',startDate,sep='')]) - if (length(fprice)==1) tmpPL[,'Prices'][1] <- fprice + if (length(fprice)==1) tmpPL[1,'Prices'] <- fprice } - # na.locf any missing prices with last observation (this assumption seems the only rational one for vectorization) - tmpPL[,'Prices'] <- na.locf( tmpPL[,'Prices']) - - #select among our merged columns - tmpPL[,'Pos.Qty'] <- ifelse(is.na( tmpPL[,'Pos.Qty']) & !is.na( tmpPL[,'Pos.Qty.1']), tmpPL[,'Pos.Qty.1'], tmpPL[,'Pos.Qty']) - tmpPL[,'Con.Mult.1'] <- ifelse(is.na( tmpPL[,'Con.Mult']) & !is.na( tmpPL[,'Con.Mult.1']) , tmpPL[,'Con.Mult.1'], tmpPL[,'Con.Mult']) - tmpPL[,'Pos.Avg.Cost'] <- ifelse(is.na( tmpPL[,'Pos.Avg.Cost']) & !is.na( tmpPL[,'Pos.Avg.Cost.1']) , tmpPL[,'Pos.Avg.Cost.1'], tmpPL[,'Pos.Avg.Cost']) - - # na.locf Pos.Qty,Con.Mult,Pos.Avg.Cost to instantiate $posPL new rows - columns<-c('Pos.Qty','Con.Mult','Con.Mult.1','Pos.Avg.Cost','Pos.Avg.Cost.1') - tmpPL[,columns] <- na.locf(tmpPL[,columns]) - - #TODO check for instrument multiplier rather than doing all this messing around, if possible. - #tmpPL[,'Con.Mult.1'] <- na.locf( tmpPL[,'Con.Mult.1']) - #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Con.Mult']) - #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Con.Mult'], fromLast=TRUE) # carry NA's backwards too, might cause problems with options contracts that change multiplier - tmpPL[,'Con.Mult'] <- ifelse(is.na( tmpPL[,'Con.Mult']) ,1, tmpPL[,'Con.Mult']) - #tmpPL[,'Con.Mult'] <- na.locf( tmpPL[,'Pos.Avg.Cost.1']) - #tmpPL[,'Pos.Avg.Cost'] <- na.locf( tmpPL[,'Pos.Avg.Cost']) + # and na.locf Pos.Qty,Con.Mult,Pos.Avg.Cost to instantiate $posPL new rows + columns <- c('Prices','Pos.Qty','Con.Mult','Pos.Avg.Cost') + tmpPL[,columns] <- na.locf(tmpPL[,columns]) + + #TODO check for instrument multiplier rather than doing all this messing around, if possible. + tmpPL[,'Con.Mult'] <- na.locf(tmpPL[,'Con.Mult'], fromLast=TRUE) # carry NA's backwards too, might cause problems with options contracts that change multiplier + if(any(naConMult <- is.na(tmpPL[,'Con.Mult']))) # belt + suspenders? + tmpPL[naConMult,'Con.Mult'] <- 1 # zerofill Txn.Value, Txn.Fees - tmpPL[,'Txn.Value'] <- ifelse(is.na( tmpPL[,'Txn.Value']),0, tmpPL[,'Txn.Value']) + tmpPL[is.na(tmpPL[,'Txn.Value']),'Txn.Value'] <- 0 + tmpPL[is.na(tmpPL[,'Txn.Fees']),'Txn.Fees'] <- 0 - tmpPL[,'Txn.Fees'] <- ifelse(is.na(tmpPL[,'Txn.Fees']) ,0, tmpPL[,'Txn.Fees']) - # matrix calc Pos.Qty * Price * Con.Mult to get Pos.Value - tmpPL[,'Pos.Value'] <- tmpPL[,'Pos.Qty'] * tmpPL[,'Con.Mult'] * tmpPL[,'Prices'] + tmpPL <- merge(tmpPL, Pos.Value=drop(tmpPL[,'Pos.Qty'] * tmpPL[,'Con.Mult'] * tmpPL[,'Prices'])) - LagValue<-Lag(tmpPL[,'Pos.Value']) - LagValue<-ifelse(is.na(LagValue),0,LagValue) # needed to avoid a possible NA on the first value that would mess up the Gross.Trading.PL calc - tmpPL[,'Gross.Trading.PL'] <- tmpPL[,'Pos.Value']- LagValue - tmpPL[,'Txn.Value'] + LagValue <- lag(tmpPL[,'Pos.Value']) + LagValue[is.na(LagValue)] <- 0 # needed to avoid a possible NA on the first value that would mess up the Gross.Trading.PL calc + tmpPL <- merge(tmpPL, Gross.Trading.PL=drop(tmpPL[,'Pos.Value']- LagValue - tmpPL[,'Txn.Value'])) - # alternate matrix calc for Realized&Unrealized PL that is only dependent on Txn PL and Gross.Trading.PL - tmpPL[,'Net.Txn.Realized.PL'] <- ifelse(is.na(tmpPL[,'Net.Txn.Realized.PL']),0,tmpPL[,'Net.Txn.Realized.PL']) - tmpPL[,'Gross.Txn.Realized.PL'] <- ifelse(is.na(tmpPL[,'Gross.Txn.Realized.PL']),0,tmpPL[,'Gross.Txn.Realized.PL']) + tmpPL[is.na(tmpPL[,'Net.Txn.Realized.PL']),'Net.Txn.Realized.PL'] <- 0 + tmpPL[is.na(tmpPL[,'Gross.Txn.Realized.PL']),'Gross.Txn.Realized.PL'] <- 0 - #tmpPL[,'Gross.Trading.PL'] <- tmpPL[,'Pos.Value'] - (tmpPL[,'Pos.Qty']* tmpPL[,'Pos.Avg.Cost']) + tmpPL[,'Gross.Txn.Realized.PL'] - tmpPL$Period.Realized.PL <- tmpPL[,'Gross.Txn.Realized.PL'] - tmpPL$Period.Unrealized.PL <- round(tmpPL[,'Gross.Trading.PL'] - tmpPL$Period.Realized.PL,2) + # matrix calc Period.*.PL, Net.Trading.PL as Gross.Trading.PL + Txn.Fees + tmpPL <- merge(tmpPL, + Period.Realized.PL = drop(tmpPL[,'Gross.Txn.Realized.PL']), # believe it or not, merging is faster than renaming + Period.Unrealized.PL = drop(round(tmpPL[,'Gross.Trading.PL'] - tmpPL[,'Gross.Txn.Realized.PL'], 2)), + Net.Trading.PL = drop(tmpPL[,'Gross.Trading.PL'] + tmpPL[,'Txn.Fees']), + Ccy.Mult = 1) # Ccy.Mult for this step is always 1 - # matrix calc Net.Trading.PL as Gross.Trading.PL + Txn.Fees - tmpPL[,'Net.Trading.PL'] <- tmpPL[,'Gross.Trading.PL'] + tmpPL[,'Txn.Fees'] - # Ccy.Mult for this step is always 1 - tmpPL[,'Ccy.Mult']<-rep(1,nrow(tmpPL)) + tmpPL[,'Ccy.Mult'] <- 1 # reorder,discard columns for insert into portfolio object tmpPL <- tmpPL[,c('Pos.Qty', 'Con.Mult', 'Ccy.Mult', 'Pos.Value', 'Pos.Avg.Cost', 'Txn.Value', 'Period.Realized.PL', 'Period.Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')] From noreply at r-forge.r-project.org Wed Oct 30 23:29:47 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 30 Oct 2013 23:29:47 +0100 (CET) Subject: [Blotter-commits] r1558 - pkg/quantstrat/R Message-ID: <20131030222947.C5F09185BE3@r-forge.r-project.org> Author: bodanker Date: 2013-10-30 23:29:47 +0100 (Wed, 30 Oct 2013) New Revision: 1558 Modified: pkg/quantstrat/R/ruleOrderProc.R pkg/quantstrat/R/rules.R Log: - calculate periodicity(mktdata) in applyRules and pass to ruleOrderProc to avoid calling periodicity for every order - correct environment passed to do.call in ruleProc - add data=mktdata to sigThreshold calls Modified: pkg/quantstrat/R/ruleOrderProc.R =================================================================== --- pkg/quantstrat/R/ruleOrderProc.R 2013-10-30 16:47:23 UTC (rev 1557) +++ pkg/quantstrat/R/ruleOrderProc.R 2013-10-30 22:29:47 UTC (rev 1558) @@ -125,7 +125,11 @@ if(hasArg(allowMagicalThinking)) allowMagicalThinking=match.call(expand.dots=TRUE)$allowMagicalThinking else allowMagicalThinking = FALSE - freq = periodicity(mktdata) + # Get cached frequency, if it's available + if(hasArg(periodicity)) + freq <- eval(match.call(expand.dots=TRUE)$periodicity, envir=parent.frame()) + else + freq <- periodicity(mktdata) #switch on frequency switch(orderType, market = { Modified: pkg/quantstrat/R/rules.R =================================================================== --- pkg/quantstrat/R/rules.R 2013-10-30 16:47:23 UTC (rev 1557) +++ pkg/quantstrat/R/rules.R 2013-10-30 22:29:47 UTC (rev 1558) @@ -409,7 +409,7 @@ } if (is.na(col)) stop("no price discernable for stoplimit in applyRules") } - cross<-sigThreshold(label='tmpstop',column=col,threshold=tmpprice,relationship=relationship) + cross<-sigThreshold(label='tmpstop',data=mktdata,column=col,threshold=tmpprice,relationship=relationship) cross <- cross[timespan][-1] # don't look for crosses on curIndex if(any(cross)){ # find first index that would cross after this index @@ -458,7 +458,7 @@ if (is.na(col)) stop("no price discernable for limit in applyRules") } # use sigThreshold - cross<-sigThreshold(label='tmplimit',column=col,threshold=tmpprice,relationship=relationship) + cross<-sigThreshold(label='tmplimit',data=mktdata,column=col,threshold=tmpprice,relationship=relationship) cross <- cross[timespan][-1] # don't look for crosses on curIndex if(any(cross)){ # find first index that would cross after this index @@ -561,10 +561,9 @@ hold=FALSE holdtill=first(time(Dates))-1 # TODO FIXME make holdtill default more robust? - mktinstr<-getInstrument(symbol) - curIndex<-1 + freq <- periodicity(mktdata) # run once and pass to ruleOrderProc while(curIndex){ timestamp=Dates[curIndex] @@ -607,7 +606,7 @@ else timestamp=NULL - closed.orders <- ruleOrderProc(portfolio=portfolio, symbol=symbol, mktdata=mktdata, timestamp=timestamp, ...) + closed.orders <- ruleOrderProc(portfolio=portfolio, symbol=symbol, mktdata=mktdata, timestamp=timestamp, periodicity=freq, ...) } }, chain = { @@ -702,7 +701,7 @@ if(!is.null(rule$arguments$prefer)) .formals$prefer = rule$arguments$prefer # evaluate rule in applyRules' environment - tmp_val <- do.call(rule$name, .formals, envir=parent.frame(2)) + tmp_val <- do.call(rule$name, .formals, envir=parent.frame(1)) # print(paste('tmp_val ==', tmp_val)) } #end rules loop From noreply at r-forge.r-project.org Thu Oct 31 00:30:01 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 31 Oct 2013 00:30:01 +0100 (CET) Subject: [Blotter-commits] r1559 - pkg/quantstrat/R Message-ID: <20131030233001.17BD718461D@r-forge.r-project.org> Author: bodanker Date: 2013-10-31 00:30:00 +0100 (Thu, 31 Oct 2013) New Revision: 1559 Modified: pkg/quantstrat/R/ruleOrderProc.R pkg/quantstrat/R/ruleSignal.R pkg/quantstrat/R/rules.R pkg/quantstrat/R/utils.R Log: - add curIndex arguments to ruleOrderProc and ruleSignal because xts subsetting via integer is much faster than via POSIXct - don't remove '...' in modify.args when they are in formals and dots=TRUE Modified: pkg/quantstrat/R/ruleOrderProc.R =================================================================== --- pkg/quantstrat/R/ruleOrderProc.R 2013-10-30 22:29:47 UTC (rev 1558) +++ pkg/quantstrat/R/ruleOrderProc.R 2013-10-30 23:30:00 UTC (rev 1559) @@ -52,6 +52,11 @@ ruleOrderProc <- function(portfolio, symbol, mktdata, timestamp=NULL, ordertype=NULL, ..., slippageFUN=NULL) { if(is.null(timestamp)) return() + # Get row index of timestamp for faster subsetting + if(hasArg(curIndex)) + curIndex <- eval(match.call(expand.dots=TRUE)$curIndex, parent.frame()) + else + curIndex <- mktdata[timestamp,which.i=TRUE] orderbook <- getOrderBook(portfolio) ordersubset <- orderbook[[portfolio]][[symbol]] @@ -79,7 +84,7 @@ return(NULL) } else { - mktdataTimestamp <- mktdata[timestamp] + mktdataTimestamp <- mktdata[curIndex] # only keep the last observation per time stamp if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp) isOHLCmktdata <- is.OHLC(mktdata) Modified: pkg/quantstrat/R/ruleSignal.R =================================================================== --- pkg/quantstrat/R/ruleSignal.R 2013-10-30 22:29:47 UTC (rev 1558) +++ pkg/quantstrat/R/ruleSignal.R 2013-10-30 23:30:00 UTC (rev 1559) @@ -59,10 +59,13 @@ if(!is.function(osFUN)) osFUN<-match.fun(osFUN) - if (!is.na(timestamp) && - nrow(mktdata[timestamp])>0 && - (ruletype=='chain' || (!is.na(mktdata[timestamp][,sigcol]) && mktdata[timestamp][,sigcol] == sigval)) - ) + # Get row index of timestamp for faster subsetting + if(hasArg(curIndex)) + curIndex <- eval(match.call(expand.dots=TRUE)$curIndex, parent.frame()) + else + curIndex <- mktdata[timestamp,which.i=TRUE] + + if(curIndex > 0 && curIndex <= nrow(mktdata) && (ruletype=='chain' || (!is.na(mktdata[curIndex,sigcol]) && mktdata[curIndex,sigcol]==sigval))) { #calculate order price using pricemethod pricemethod<-pricemethod[1] #only use the first if not set by calling function @@ -87,7 +90,7 @@ if(length(col.idx) > 1) stop(paste('more than one indicator column in mktdata matches threshold name "', threshold, '"', sep='')) - threshold <- as.numeric(mktdata[,col.idx][timestamp]) + threshold <- as.numeric(mktdata[curIndex,col.idx]) } } @@ -140,7 +143,7 @@ else prefer='bid' # we're selling, so give it to them for what they're bidding } - orderprice <- try(getPrice(x=mktdata, prefer=prefer)[,1][timestamp]) + orderprice <- try(getPrice(x=mktdata[curIndex,], prefer=prefer)[,1]) }, passive =, work =, @@ -151,7 +154,7 @@ else prefer='ask' # we're selling, so work the ask price } - orderprice <- try(getPrice(x=mktdata, prefer=prefer)[,1][timestamp]) + orderprice <- try(getPrice(x=mktdata[curIndex,], prefer=prefer)[,1]) }, maker = { if(hasArg(price) & length(match.call(expand.dots=TRUE)$price)>1) { @@ -159,9 +162,9 @@ orderprice <- try(match.call(expand.dots=TRUE)$price) } else { if(!is.null(threshold)) { - baseprice<- last(getPrice(x=mktdata)[,1][timestamp]) # this should get either the last trade price or the Close + baseprice <- last(getPrice(x=mktdata[curIndex,])[,1]) # this should get either the last trade price or the Close if(hasArg(tmult) & isTRUE(match.call(expand.dots=TRUE)$tmult)) { - baseprice<- last(getPrice(x=mktdata)[,1][timestamp]) # this should get either the last trade price or the Close + baseprice <- last(getPrice(x=mktdata[curIndex,])[,1]) # this should get either the last trade price or the Close # threshold is a multiplier of current price if (length(threshold)>1){ orderprice <- baseprice * threshold # assume the user has set proper threshold multipliers for each side Modified: pkg/quantstrat/R/rules.R =================================================================== --- pkg/quantstrat/R/rules.R 2013-10-30 22:29:47 UTC (rev 1558) +++ pkg/quantstrat/R/rules.R 2013-10-30 23:30:00 UTC (rev 1559) @@ -587,17 +587,17 @@ switch( type , pre = { if(length(strategy$rules[[type]])>=1){ - ruleProc(strategy$rules$pre,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, ...) + ruleProc(strategy$rules$pre,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, curIndex=curIndex, ...) } }, risk = { if(length(strategy$rules$risk)>=1){ - ruleProc(strategy$rules$risk,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr,parameters=parameters, ...) + ruleProc(strategy$rules$risk,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr,parameters=parameters, curIndex=curIndex, ...) } }, order = { if(length(strategy$rules[[type]])>=1) { - ruleProc(strategy$rules[[type]],timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, ...) + ruleProc(strategy$rules[[type]],timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, curIndex=curIndex, ...) } else { #(mktdata, portfolio, symbol, timestamp, slippageFUN=NULL) @@ -606,7 +606,7 @@ else timestamp=NULL - closed.orders <- ruleOrderProc(portfolio=portfolio, symbol=symbol, mktdata=mktdata, timestamp=timestamp, periodicity=freq, ...) + closed.orders <- ruleOrderProc(portfolio=portfolio, symbol=symbol, mktdata=mktdata, timestamp=timestamp, periodicity=freq, curIndex=curIndex, ...) } }, chain = { @@ -626,7 +626,7 @@ txn.price <- last(txns$Txn.Price) # last() because there may be more than one txn at this timestamp #ruleProc(rules[j], timestamp=timestamp, path.dep=path.dep, mktdata=mktdata, portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=list(chain.price=as.numeric(closed.chain$Order.Price[i]), ...)) - ruleProc(rules[j], timestamp=timestamp, path.dep=path.dep, mktdata=mktdata, portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=list(chain.price=txn.price)) + ruleProc(rules[j], timestamp=timestamp, path.dep=path.dep, mktdata=mktdata, portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=list(chain.price=txn.price), curIndex=curIndex) } } } @@ -637,7 +637,7 @@ if(isTRUE(path.dep)) openOrdersLen <- length(getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timestamp,which.i=TRUE)) if(length(strategy$rules[[type]])>=1) { - ruleProc(strategy$rules[[type]],timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, ...) + ruleProc(strategy$rules[[type]],timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, curIndex=curIndex, ...) } if(isTRUE(path.dep) && length(getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timestamp,which.i=TRUE)) != openOrdersLen) { assign.dindex(c(get.dindex(),curIndex+1)) @@ -646,7 +646,7 @@ post = { #TODO do we process for hold here, or not? if(length(strategy$rules$post)>=1) { - ruleProc(strategy$rules$post,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, ...) + ruleProc(strategy$rules$post,timestamp=timestamp, path.dep=path.dep, mktdata=mktdata,portfolio=portfolio, symbol=symbol, ruletype=type, mktinstr=mktinstr, parameters=parameters, curIndex=curIndex, ...) } } ) # end switch @@ -682,7 +682,7 @@ if(!isTRUE(rule$enabled)) next() # check to see if we should run in this timespan - if(!is.null(rule$timespan) && nrow(mktdata[timestamp][rule$timespan])==0) next() + if(!is.null(rule$timespan) && nrow(mktdata[curIndex][rule$timespan])==0) next() # modify a few things rule$arguments$timestamp = timestamp @@ -695,7 +695,7 @@ # now add arguments from parameters .formals <- modify.args(.formals, parameters) # now add dots - .formals <- modify.args(.formals, ...) + .formals <- modify.args(.formals, ..., dots=TRUE) # any rule-specific prefer-parameters should override global prefer parameter if(!is.null(rule$arguments$prefer)) .formals$prefer = rule$arguments$prefer Modified: pkg/quantstrat/R/utils.R =================================================================== --- pkg/quantstrat/R/utils.R 2013-10-30 22:29:47 UTC (rev 1558) +++ pkg/quantstrat/R/utils.R 2013-10-30 23:30:00 UTC (rev 1559) @@ -84,7 +84,7 @@ if(dots && !is.null(.formals$...)) { dotnames <- names(arglist[pm == 0L]) .formals[dotnames] <- arglist[dotnames] - .formals$... <- NULL + #.formals$... <- NULL # should we assume we matched them all? } .formals From noreply at r-forge.r-project.org Thu Oct 31 13:14:46 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 31 Oct 2013 13:14:46 +0100 (CET) Subject: [Blotter-commits] r1560 - in pkg/quantstrat: R man Message-ID: <20131031121446.77DD418622E@r-forge.r-project.org> Author: braverock Date: 2013-10-31 13:14:45 +0100 (Thu, 31 Oct 2013) New Revision: 1560 Modified: pkg/quantstrat/R/osFUNs.R pkg/quantstrat/man/addPosLimit.Rd Log: - update docs to add more detail to addPosLimit, thanks to Chinmay Patel for the request Modified: pkg/quantstrat/R/osFUNs.R =================================================================== --- pkg/quantstrat/R/osFUNs.R 2013-10-30 23:30:00 UTC (rev 1559) +++ pkg/quantstrat/R/osFUNs.R 2013-10-31 12:14:45 UTC (rev 1560) @@ -30,12 +30,37 @@ #' add position and level limits at timestamp #' +#' Many strategies will not be allowed to trade unconstrained. +#' Typically, constraints will include position sizing limits. +#' +#' \code{addPosLimit} works with \code{\link{osMaxPos}} to set +#' and enforce position sizing limits. If \code{levels=1}, +#' then all order sizing will be in the complete control of +#' the strategy rules, up to the maximum position specified +#' using \code{addPosLimit}'s \code{maxpos} and \code{minpos} +#' arguments. +#' +#' Simply setting a position limit will not do anything. +#' The strategy entry rules also need to specify an +#' the use of order sizing function \code{\link{osMaxPos}}, +#' most typically as an argument to \code{\link{ruleSignal}}. +#' #' levels are a simplification of more complex (proprietary) #' techniques sometimes used for order sizing. -#' the max orderqty returned will be the limit/levels +#' the max orderqty returned will be the limit/levels. #' Obviously the strategy rules could ask for smaller order sizes, #' but this is the default. If you don't want to use levels, set #' them to 1. +#' +#' It is also important to note that position limits +#' may be time-varying. +#' If you only want one staic maximum position limit, then +#' call \code{addPosLimit} with a \code{timestamp} argument +#' before your first trade. If you want time varying limits, +#' typically in response to some rebalancing rule or risk +#' rule, set the \code{timestamp} at the time which you wish +#' the limit to take effect. +#' #' @param portfolio text name of the portfolio to place orders in #' @param symbol identifier of the instrument to place orders for. The name of any associated price objects (xts prices, usually OHLC) should match these #' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on Modified: pkg/quantstrat/man/addPosLimit.Rd =================================================================== --- pkg/quantstrat/man/addPosLimit.Rd 2013-10-30 23:30:00 UTC (rev 1559) +++ pkg/quantstrat/man/addPosLimit.Rd 2013-10-31 12:14:45 UTC (rev 1560) @@ -28,12 +28,38 @@ default longlevels} } \description{ + Many strategies will not be allowed to trade + unconstrained. Typically, constraints will include + position sizing limits. +} +\details{ + \code{addPosLimit} works with \code{\link{osMaxPos}} to + set and enforce position sizing limits. If + \code{levels=1}, then all order sizing will be in the + complete control of the strategy rules, up to the maximum + position specified using \code{addPosLimit}'s + \code{maxpos} and \code{minpos} arguments. + + Simply setting a position limit will not do anything. The + strategy entry rules also need to specify an the use of + order sizing function \code{\link{osMaxPos}}, most + typically as an argument to \code{\link{ruleSignal}}. + levels are a simplification of more complex (proprietary) techniques sometimes used for order sizing. the max - orderqty returned will be the limit/levels Obviously the + orderqty returned will be the limit/levels. Obviously the strategy rules could ask for smaller order sizes, but this is the default. If you don't want to use levels, set them to 1. + + It is also important to note that position limits may be + time-varying. If you only want one staic maximum position + limit, then call \code{addPosLimit} with a + \code{timestamp} argument before your first trade. If + you want time varying limits, typically in response to + some rebalancing rule or risk rule, set the + \code{timestamp} at the time which you wish the limit to + take effect. } \seealso{ \code{\link{osMaxPos}} \code{\link{getPosLimit}}