From noreply at r-forge.r-project.org Fri Dec 6 16:54:23 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 6 Dec 2013 16:54:23 +0100 (CET) Subject: [Blotter-commits] r1575 - pkg/blotter/R Message-ID: <20131206155423.88564186356@r-forge.r-project.org> Author: bodanker Date: 2013-12-06 16:54:23 +0100 (Fri, 06 Dec 2013) New Revision: 1575 Modified: pkg/blotter/R/updateAcct.R pkg/blotter/R/updateEndEq.R pkg/blotter/R/updatePosPL.R Log: - Patch updateAcct and updateEndEq to do nothing if called before there are any transactions in any portfolios. - Replace calls to xts:::time.xts() with index() Modified: pkg/blotter/R/updateAcct.R =================================================================== --- pkg/blotter/R/updateAcct.R 2013-11-20 14:10:01 UTC (rev 1574) +++ pkg/blotter/R/updateAcct.R 2013-12-06 15:54:23 UTC (rev 1575) @@ -14,8 +14,12 @@ Portfolios = names(Account$portfolios) - 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))) + if(is.null(Dates)) + Dates <- unique(do.call(c,c(lapply(Portfolios, function(x) index(.getPortfolio(x)$summary)), use.names=FALSE, recursive=FALSE)))[-1] + # if all the portfolio summary tables only have one observation + # then we haven't made any transactions, so there's nothing to update + if(!length(Dates)) + return(name) #trim to only time prior to Dates if(last(index(Account$summary))>.parseISO8601(Dates)$first.time){ @@ -150,7 +154,6 @@ Account$summary <- rbind(Account$summary, summary) # 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) return(name) #not sure this is a good idea } Modified: pkg/blotter/R/updateEndEq.R =================================================================== --- pkg/blotter/R/updateEndEq.R 2013-11-20 14:10:01 UTC (rev 1574) +++ pkg/blotter/R/updateEndEq.R 2013-12-06 15:54:23 UTC (rev 1575) @@ -18,11 +18,15 @@ stop(paste("Account",aname," not found, use initAcct() to create a new account")) if(is.null(Dates)) # if no date is specified, get all available dates - Dates = xts:::time.xts(Account$summary)[-1] + Dates = index(Account$summary)[-1] else - Dates = xts:::time.xts(Account$summary[Dates]) + Dates = index(Account$summary[Dates]) + # if the account summary table only has one observation + # then we haven't made any transactions, so there's nothing to update + if(!length(Dates)) + return(aname) - PrevDate = xts:::time.xts(Account$summary[first(Account$summary[Dates,which.i=TRUE])-1,]) # get index of previous end date + PrevDate = index(Account$summary[first(Account$summary[Dates,which.i=TRUE])-1,]) # get index of previous end date PrevEndEq = getEndEq(aname, PrevDate) Additions = Account$summary[Dates]$Additions Withdrawals = Account$summary[Dates]$Withdrawals @@ -34,7 +38,6 @@ EndCapital = PrevEndEq + cumsum(Additions + Withdrawals + NetPerformance) 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) return(aname) #not sure this is a good idea } Modified: pkg/blotter/R/updatePosPL.R =================================================================== --- pkg/blotter/R/updatePosPL.R 2013-11-20 14:10:01 UTC (rev 1574) +++ pkg/blotter/R/updatePosPL.R 2013-12-06 15:54:23 UTC (rev 1575) @@ -37,12 +37,12 @@ # if no date is specified, get all available dates if(is.null(Dates)) { - Dates = xts:::time.xts(prices) + Dates = index(prices) } else if(!is.timeBased(Dates)) { Dates<- if(is.na(.parseISO8601(Dates)$first.time) || .parseISO8601(Dates)$first.time < as.POSIXct(first(index(prices)))){ index(prices[paste('/',.parseISO8601(Dates)$last.time,sep='')]) - } else xts:::time.xts(prices[Dates]) + } else index(prices[Dates]) } if(!missing(Interval) && !is.null(Interval)) { ep_args <- .parse_interval(Interval) From noreply at r-forge.r-project.org Fri Dec 6 16:55:29 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 6 Dec 2013 16:55:29 +0100 (CET) Subject: [Blotter-commits] r1576 - pkg/blotter/demo Message-ID: <20131206155529.E82181865B7@r-forge.r-project.org> Author: bodanker Date: 2013-12-06 16:55:29 +0100 (Fri, 06 Dec 2013) New Revision: 1576 Modified: pkg/blotter/demo/turtles.R Log: - Patch turtles demo to work with portfolio environments Modified: pkg/blotter/demo/turtles.R =================================================================== --- pkg/blotter/demo/turtles.R 2013-12-06 15:54:23 UTC (rev 1575) +++ pkg/blotter/demo/turtles.R 2013-12-06 15:55:29 UTC (rev 1576) @@ -49,13 +49,17 @@ # No output. Modifies STRATEGY in local namespace. # FUNCTION - # Store the transaction and calculations, returns the portfolio - pname=Portfolio - NewTxn = xts(t(c(PosUnitsQty, UnitSize, StopPrice, TxnPrice, TxnN)), order.by=as.POSIXct(TxnDate)) - colnames(NewTxn) = c('Pos.Units', 'Unit.Size', 'Stop.Price', 'Txn.Price', 'Txn.N') - Portfolio<-getPortfolio(Portfolio) - Portfolio[[Symbol]]$strat <- rbind(Portfolio[[Symbol]]$strat, NewTxn) - assign( paste("portfolio",pname,sep='.'), Portfolio, envir=.blotter ) + # Store the transaction and calculations + # Called for its side-effects of updating the 'strat' table in the portfolio + NewTxn <- xts(t(c(PosUnitsQty, UnitSize, StopPrice, TxnPrice, TxnN)), order.by=as.POSIXct(TxnDate), + dimnames=list(NULL, c('Pos.Units', 'Unit.Size', 'Stop.Price', 'Txn.Price', 'Txn.N'))) + # .getPortfolio returns the portfolio environment, which allows you to write to it, since + # environments are pass-by-reference. + # NOTE: To be safe, use getPortfolio for a read-only copy of the portfolio. getPortfolio copies + # the portfolio environment to a list. + Portfolio <- .getPortfolio(Portfolio) + # This table stores transaction-related information relative to the strategy + Portfolio$symbols[[Symbol]]$strat <- rbind(Portfolio$symbols[[Symbol]]$strat, NewTxn) } getSymbols(symbols, index.class="POSIXct", from=initDate, src="yahoo") @@ -68,17 +72,6 @@ account = "turtles" initAcct(name=account,portfolios="turtles", initDate=initDate, initEq=initEq) -# This table stores transaction-related information relative to the strategy -# Placing it into the portfolio object, sure why not? -Portfolio<-getPortfolio(portfolio) -for(symbol in symbols){ - Portfolio[[symbol]]$strat <- xts( as.matrix(t(c(0,0,0,0,0))), order.by=as.POSIXct(initDate) ) - colnames(Portfolio[[symbol]]$strat) <- c('Pos.Units', 'Unit.Size', 'Stop.Price', 'Txn.Price', 'Txn.N') -} -# now put it back where it belongs -assign( "portfolio.turtles", Portfolio , envir=.blotter ) -rm("Portfolio") - # @todo: decrease the size of the notional account by 20% each time lose 10% of original account (10% drawdown). E.g., if trading a $1M account and down 100K, trade as if $800K account until out of drawdown. If lose another 10% from 800K, or 80K loss, then reduce account size another 20% for notional size of 640K. # Set up indicators @@ -117,7 +110,6 @@ Units=0 verbose=TRUE - # Create trades for( i in 57:NROW(x) ) { # Assumes all dates are the same CurrentDate=time(x)[i] @@ -129,7 +121,7 @@ ClosePrice = as.numeric(Cl(x[i,])) Posn = getPosQty(Portfolio=portfolio, Symbol=symbol, Date=CurrentDate) - s = tail(getPortfolio(portfolio)[[symbol]]$strat,1) + s = tail(getPortfolio(portfolio)$symbols[[symbol]]$strat,1) Units = as.numeric(s[,'Pos.Units']) TxnPrice = as.numeric(s[,'Txn.Price']) @@ -176,8 +168,8 @@ } # End symbol loop # Now that we've updated all of our trades, its time to mark the book updatePortf(Portfolio = portfolio) - updateAcct(account) - updateEndEq(account) + updateAcct(account, Dates=CurrentDate) + updateEndEq(account, Dates=CurrentDate) } # End dates loop # Final values From noreply at r-forge.r-project.org Fri Dec 6 20:23:06 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 6 Dec 2013 20:23:06 +0100 (CET) Subject: [Blotter-commits] r1577 - pkg/blotter/R Message-ID: <20131206192306.C75FC18685F@r-forge.r-project.org> Author: bodanker Date: 2013-12-06 20:23:05 +0100 (Fri, 06 Dec 2013) New Revision: 1577 Modified: pkg/blotter/R/addTxn.R Log: - addTxns now splits transactions that would cross through zero - addTxn and addTxns now re-calculate fees pro-rata by quantity Modified: pkg/blotter/R/addTxn.R =================================================================== --- pkg/blotter/R/addTxn.R 2013-12-06 15:55:29 UTC (rev 1576) +++ pkg/blotter/R/addTxn.R 2013-12-06 19:23:05 UTC (rev 1577) @@ -66,11 +66,13 @@ # split transactions that would cross through zero if(PrevPosQty!=0 && sign(PrevPosQty+TxnQty)!=sign(PrevPosQty) && PrevPosQty!=-TxnQty){ + txnFeeQty=TxnFees/abs(TxnQty) # calculate fees pro-rata by quantity addTxn(Portfolio=pname, Symbol=Symbol, TxnDate=TxnDate, TxnQty=-PrevPosQty, TxnPrice=TxnPrice, ..., - TxnFees = TxnFees, ConMult = ConMult, verbose = verbose, eps=eps) + TxnFees = txnFeeQty*abs(PrevPosQty), ConMult = ConMult, verbose = verbose, eps=eps) TxnDate=TxnDate+2*eps #transactions need unique timestamps, so increment a bit TxnQty=TxnQty+PrevPosQty PrevPosQty=0 + TxnFees=txnFeeQty*abs(TxnQty+PrevPosQty) } Portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) @@ -153,7 +155,7 @@ #' @rdname addTxn #' @export -addTxns<- function(Portfolio, Symbol, TxnData , verbose=FALSE, ..., ConMult=NULL) +addTxns<- function(Portfolio, Symbol, TxnData , verbose=FALSE, ..., ConMult=NULL, eps=1e-06) { pname<-Portfolio Portfolio<-get(paste("portfolio",pname,sep='.'),envir=.blotter) @@ -179,12 +181,37 @@ } else { NewTxns$Txn.Fees <- 0 } + # split transactions that would cross through zero + Pos <- drop(cumsum(NewTxns$Txn.Qty)) + Pos <- merge(Qty=Pos, PrevQty=lag(Pos)) + PosCrossZero <- Pos$PrevQty!= 0 & sign(Pos$PrevQty+NewTxns$Txn.Qty) != sign(Pos$PrevQty) & Pos$PrevQty!= -NewTxns$Txn.Qty + PosCrossZero[1] <- FALSE + if(any(PosCrossZero)) { + # subset position object + Pos <- Pos[PosCrossZero,] + # subset transactions we need to split, and initialize objects we can alter + flatTxns <- initTxns <- NewTxns[PosCrossZero,] + # set quantity for flat and initiating transactions + flatTxns$Txn.Qty <- -Pos$PrevQty + initTxns$Txn.Qty <- initTxns$Txn.Qty + Pos$PrevQty + # calculate fees pro-rata by quantity + txnFeeQty <- NewTxns$Txn.Fees/abs(NewTxns$Txn.Qty) + flatTxns$Txn.Fees <- txnFeeQty * abs(flatTxns$Txn.Qty) + initTxns$Txn.Fees <- txnFeeQty * abs(initTxns$Txn.Qty) + # transactions need unique timestamps, so increment initiating transaction index + .index(initTxns) <- .index(initTxns) + 2*eps + # remove split transactions from NewTxns, add flat and initiating transactions + NewTxns <- rbind(NewTxns[!PosCrossZero,], flatTxns, initTxns) + rm(flatTxns, initTxns, txnFeeQty) # clean up + } + rm(Pos, PosCrossZero) # clean up + # calculate transaction values 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)) + initPosQty <- initPosAvgCost <- numeric(nrow(NewTxns)) + initPosQty[1] <- getPosQty(pname, Symbol, start(NewTxns)) + initPosAvgCost[1] <- .getPosAvgCost(pname, Symbol, start(NewTxns)) # 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 From noreply at r-forge.r-project.org Fri Dec 13 02:23:36 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 13 Dec 2013 02:23:36 +0100 (CET) Subject: [Blotter-commits] r1578 - pkg/quantstrat/R Message-ID: <20131213012336.56AEC186748@r-forge.r-project.org> Author: efmrforge Date: 2013-12-13 02:23:35 +0100 (Fri, 13 Dec 2013) New Revision: 1578 Modified: pkg/quantstrat/R/chart.forward.training.R Log: removed exec bit Modified: pkg/quantstrat/R/chart.forward.training.R =================================================================== --- pkg/quantstrat/R/chart.forward.training.R 2013-12-06 19:23:05 UTC (rev 1577) +++ pkg/quantstrat/R/chart.forward.training.R 2013-12-13 01:23:35 UTC (rev 1578) @@ -61,3 +61,4 @@ .audit <- NULL } + From noreply at r-forge.r-project.org Sun Dec 15 03:11:40 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 15 Dec 2013 03:11:40 +0100 (CET) Subject: [Blotter-commits] r1579 - pkg/quantstrat/R Message-ID: <20131215021140.A58C0180554@r-forge.r-project.org> Author: efmrforge Date: 2013-12-15 03:11:38 +0100 (Sun, 15 Dec 2013) New Revision: 1579 Modified: pkg/quantstrat/R/chart.forward.R Log: fixed as.environment(NULL) error NEEDS TESTING [17:05] i'm doing some code review of quantstrat [17:06] this may be a very old error (2006ish?) [17:06] the relevant lines are [17:06] .audit <- NULL [17:06] portfolios.st = ls(name=.audit, pattern='portfolio.*.[0-9]+') [17:07] which, when I run just those lines throws an error: [17:07] Error in as.environment(pos) : using 'as.environment(NULL)' is defunct [17:07] which looks to be a change from 2006: http://tolstoy.newcastle.edu.au/R/e2/devel/06/09/0012.html [17:09] as this is the first I've seen the .audit environment (I haven't done any walkforwards yet), I was wondering if the fix from that post to set the package:quantstrat would make sense, or if the change would be better to .audit <- new.env() 17:49] well, if we need .audit to be an environment, then yes, I's say setting it to new.env() would make sense [17:50] but I'd also expect that it would be created during the walk-forward process, not inside a chart function, because then it would only have function-scope [18:00] --> meretrix has joined this channel (meretrix at unaffiliated/meretrix). [18:03] braverock_hm: I'll check that, thanks [18:05] walkforward also does .audit <- NULL but creates the .audit evironment [18:05] .audit <- NULL [18:05] if(!is.null(audit.prefix)) [18:05] .audit <- new.env() [18:05] that's likely the correct behavior for chart.forward, which loads the .audit environment from the audit.file [18:09] <-- top4o has left this server (Read error: Connection reset by peer). [18:11] rifght, creating it if it doesn't exist makes sense. obviously if there is no data available to chart, it would be nice to bail out gracefully Modified: pkg/quantstrat/R/chart.forward.R =================================================================== --- pkg/quantstrat/R/chart.forward.R 2013-12-13 01:23:35 UTC (rev 1578) +++ pkg/quantstrat/R/chart.forward.R 2013-12-15 02:11:38 UTC (rev 1579) @@ -8,10 +8,14 @@ { if(!require(xtsExtra, quietly=TRUE)) stop('The "xtsExtra" package is required to use this function') - .audit <- NULL + #.audit <- NULL + if(is.null(.audit)) stop ('You need to run a walk forward test first to create the .audit environment') + + if(!is.null(audit.filename)) + load(audit.filename) + else + stop('You need to provide an audit.filename.') - load(audit.filename) - # extract all portfolio names from the audit environment, except wfa portfolio portfolios.st = ls(name=.audit, pattern='portfolio.*.[0-9]+') n <- length(portfolios.st) From noreply at r-forge.r-project.org Mon Dec 16 02:35:36 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 16 Dec 2013 02:35:36 +0100 (CET) Subject: [Blotter-commits] r1580 - pkg/blotter Message-ID: <20131216013536.DF052186C64@r-forge.r-project.org> Author: efmrforge Date: 2013-12-16 02:35:36 +0100 (Mon, 16 Dec 2013) New Revision: 1580 Removed: pkg/blotter/.project Log: Removed a dot file .project Deleted: pkg/blotter/.project =================================================================== --- pkg/blotter/.project 2013-12-15 02:11:38 UTC (rev 1579) +++ pkg/blotter/.project 2013-12-16 01:35:36 UTC (rev 1580) @@ -1,21 +0,0 @@ - - - blotter - - - PerformanceAnalytics - quantmod - quantstrat - - - - de.walware.statet.r.builders.RSupport - - - - - - de.walware.statet.base.StatetNature - de.walware.statet.r.RNature - - From noreply at r-forge.r-project.org Mon Dec 16 02:43:42 2013 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 16 Dec 2013 02:43:42 +0100 (CET) Subject: [Blotter-commits] r1581 - pkg/blotter/R Message-ID: <20131216014342.B71CA185F36@r-forge.r-project.org> Author: efmrforge Date: 2013-12-16 02:43:42 +0100 (Mon, 16 Dec 2013) New Revision: 1581 Removed: pkg/blotter/R/.vimrc Log: Removed .vimrc not needed Deleted: pkg/blotter/R/.vimrc =================================================================== --- pkg/blotter/R/.vimrc 2013-12-16 01:35:36 UTC (rev 1580) +++ pkg/blotter/R/.vimrc 2013-12-16 01:43:42 UTC (rev 1581) @@ -1,3 +0,0 @@ -set tabstop=4 -set shiftwidth=4 -set expandtab