[Blotter-commits] r403 - in pkg/blotter: . R demo
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sat Oct 2 20:12:25 CEST 2010
Author: braverock
Date: 2010-10-02 20:12:24 +0200 (Sat, 02 Oct 2010)
New Revision: 403
Modified:
pkg/blotter/DESCRIPTION
pkg/blotter/R/calcPortfAttr.R
pkg/blotter/R/calcPortfSummary.R
pkg/blotter/R/chart.Posn.R
pkg/blotter/R/initPosPL.R
pkg/blotter/R/updatePortf.R
pkg/blotter/R/updatePosPL.R
pkg/blotter/demo/turtles.R
Log:
- fix edge cases for PL calc when transactions happen on first measurement period
- simplify some of the other calculations
- fix turtles demo so it can be run multiple times in the same session
Modified: pkg/blotter/DESCRIPTION
===================================================================
--- pkg/blotter/DESCRIPTION 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/DESCRIPTION 2010-10-02 18:12:24 UTC (rev 403)
@@ -5,11 +5,15 @@
Date: $Date$
Author: Peter Carl, Brian G. Peterson, Joshua Ulrich
Maintainer: Brian G. Peterson <brian at braverock.com>
-Description: Transaction infrastructure for defining instruments, transactions, portfolios and accounts for trading systems and simulation. Intends to provide portfolio support for multi-asset class and multi-currency portfolios. Still in heavy development.
+Description: Transaction infrastructure for defining instruments,
+ transactions, portfolios and accounts for trading systems and
+ simulation. Intends to provide portfolio support for multi-asset
+ class and multi-currency portfolios. Still in heavy development.
License: GPL
LazyLoad: yes
-Depends: R (>= 2.9.0), xts (>= 0.7-5), quantmod (>= 0.3-14), FinancialInstrument
+Depends: R (>= 2.9.0), xts (>= 0.7-5), quantmod (>= 0.3-14),
+ FinancialInstrument
Suggests: PerformanceAnalytics, PortfolioAnalytics, Hmisc, RUnit
-Contributors: Wolfgang Wu, Ben McCann
+Contributors: Wolfgang Wu, Ben McCann
URL: https://r-forge.r-project.org/projects/blotter/
-Copyright: (c) 2008-2010
+Copyright: (c) 2008-2010
\ No newline at end of file
Modified: pkg/blotter/R/calcPortfAttr.R
===================================================================
--- pkg/blotter/R/calcPortfAttr.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/calcPortfAttr.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -24,15 +24,15 @@
result = xts(rowSums(table, na.rm=TRUE), order.by=index(table))
colnames(result) = 'Net.Trading.PL'
},
- Realized.PL = {
- table = .getBySymbol(Portfolio = Portfolio, Attribute = 'Realized.PL', Dates = Dates, Symbols = Symbols)
+ Period.Realized.PL = {
+ table = .getBySymbol(Portfolio = Portfolio, Attribute = 'Period.Realized.PL', Dates = Dates, Symbols = Symbols)
result = xts(rowSums(table, na.rm=TRUE), order.by=index(table))
- colnames(result) = 'Realized.PL'
+ colnames(result) = 'Period.Realized.PL'
},
- Unrealized.PL = {
- table = .getBySymbol(Portfolio = Portfolio, Attribute = 'Unrealized.PL', Dates = Dates, Symbols = Symbols)
+ Period.Unrealized.PL = {
+ table = .getBySymbol(Portfolio = Portfolio, Attribute = 'Period.Unrealized.PL', Dates = Dates, Symbols = Symbols)
result = xts(rowSums(table, na.rm=TRUE), order.by=index(table))
- colnames(result) = 'Unrealized.PL'
+ colnames(result) = 'Period.Unrealized.PL'
},
Net.Value = {
table = .getBySymbol(Portfolio = Portfolio, Attribute = 'Pos.Value', Dates = Dates, Symbols = Symbols)
Modified: pkg/blotter/R/calcPortfSummary.R
===================================================================
--- pkg/blotter/R/calcPortfSummary.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/calcPortfSummary.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -11,8 +11,8 @@
GrossTradingPL = calcPortfAttr(Portfolio, 'Gross.Trading.PL', Dates)
NetTradingPL = calcPortfAttr(Portfolio, 'Net.Trading.PL', Dates)
- RealizedPL = calcPortfAttr(Portfolio, 'Realized.PL', Dates)
- UnrealizedPL = calcPortfAttr(Portfolio, 'Unrealized.PL', Dates)
+ RealizedPL = calcPortfAttr(Portfolio, 'Period.Realized.PL', Dates)
+ UnrealizedPL = calcPortfAttr(Portfolio, 'Period.Unrealized.PL', Dates)
# UnrealizedPL = TradingPL - RealizedPL
TxnFees = calcPortfAttr(Portfolio, 'Txn.Fees', Dates)
NetValue = calcPortfAttr(Portfolio, 'Net.Value', Dates)
Modified: pkg/blotter/R/chart.Posn.R
===================================================================
--- pkg/blotter/R/chart.Posn.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/chart.Posn.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -1,5 +1,10 @@
+#' chart trades against market data, position through time, and equity curve
+#' @param Portfolio string identifying the portfolio to chart
+#' @param Symbol string identifying the symbol to chart
+#' @param Dates date range, currently not used
+#' @param ... any other passthru parameters (typically parameters to \code{chart_Series})
#' @export
-chart.Posn <- function(Portfolio, Symbol = NULL, Dates = NULL, ...)
+chart.Posn <- function(Portfolio, Symbol, Dates = NULL, ...)
{ # @author Peter Carl
pname<-Portfolio
Portfolio<-getPortfolio(pname)
Modified: pkg/blotter/R/initPosPL.R
===================================================================
--- pkg/blotter/R/initPosPL.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/initPosPL.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -18,7 +18,7 @@
# FUNCTION
posPL <- xts( as.matrix(t(c(initPosQty,initConMult,initCcyMult,0,0,0,0,0,0,0,0))), order.by=as.POSIXct(initDate) )
- colnames(posPL) <- c('Pos.Qty', 'Con.Mult', 'Ccy.Mult', 'Pos.Value', 'Pos.Avg.Cost', 'Txn.Value', 'Realized.PL', 'Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')
+ colnames(posPL) <- 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')
class(posPL)<- c("posPL",class(posPL))
return(posPL)
}
Modified: pkg/blotter/R/updatePortf.R
===================================================================
--- pkg/blotter/R/updatePortf.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/updatePortf.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -15,7 +15,7 @@
#' @param Prices
#' @export
updatePortf <- function(Portfolio, Symbols=NULL, Dates=NULL, Prices=NULL)
-{ #' @author Peter Carl
+{ #' @author Peter Carl, Brian Peterson
pname<-Portfolio
Portfolio<-getPortfolio(pname) # TODO add Date handling
@@ -32,7 +32,7 @@
Portfolio<-getPortfolio(pname) # refresh with an updated object
if(is.null(Dates)) Dates <- time(Portfolio$symbols[[1]]$posPL) #not quite right, only using first symbol...
#Symbols = names(Portfolio$symbols)
- Attributes = c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value', 'Realized.PL', 'Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')
+ Attributes = c('Long.Value', 'Short.Value', 'Net.Value', 'Gross.Value', 'Period.Realized.PL', 'Period.Unrealized.PL', 'Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')
summary = NULL
tmp.attr=NULL
for(attribute in Attributes) {
@@ -58,8 +58,8 @@
Net.Value = { result = xts(rowSums(table, na.rm=TRUE), order.by=index(table)) }
)
},
- Realized.PL =,
- Unrealized.PL =,
+ Period.Realized.PL =,
+ Period.Unrealized.PL =,
Gross.Trading.PL =,
Txn.Fees =,
Net.Trading.PL = {
Modified: pkg/blotter/R/updatePosPL.R
===================================================================
--- pkg/blotter/R/updatePosPL.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/R/updatePosPL.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -48,52 +48,65 @@
# trim posPL slot to not double count, related to bug 831 on R-Forge
Portfolio$symbols[[Symbol]]$posPL<-Portfolio$symbols[[Symbol]]$posPL[paste('::',startDate,sep='')]
Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]]<-Portfolio$symbols[[Symbol]][[paste('posPL',p.ccy.str,sep='.')]][paste('::',startDate,sep='')]
+ priorPL<-last(Portfolio$symbols[[Symbol]]$posPL)
Txns <- Portfolio$symbols[[Symbol]]$txn[dateRange]
# if there are no transactions, get the last one before the current dateRange, we'll discard later
if(nrow(Txns)==0) {
Txns <- last(Portfolio$symbols[[Symbol]]$txn[paste('::',startDate,sep='')])
- rmfirst=TRUE
}
# line up transaction with Dates list
- tmpPL <- merge(Txns, Prices) # most Txn columns will get discarded later
-
+ tmpPL <- merge(Txns, priorPL, Prices) # most Txn columns will get discarded later, as will the rows from 'before' the startDate
+
+ #browser()
+
if(is.na(tmpPL$Prices[1])){
- tmpPL$Prices[1] <- last(prices[paste('::',startDate,sep='')])
+ #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
}
-
+
# na.locf any missing prices with last observation (this assumption seems the only rational one for vectorization)
tmpPL$Prices <- na.locf(tmpPL$Prices)
- # na.locf Pos.Qty,Con.Mult,Pos.Avg.Cost to instantiate $posPL new rows
+ # 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)
- tmpPL$Pos.Qty <- ifelse(is.na(tmpPL$Pos.Qty),0, tmpPL$Pos.Qty)
+ 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 <- ifelse(is.na(tmpPL$Con.Mult) ,1, tmpPL$Con.Mult)
+ 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)
- tmpPL$Pos.Avg.Cost <- ifelse(is.na(tmpPL$Pos.Avg.Cost),0, tmpPL$Pos.Avg.Cost)
# zerofill Txn.Value, Txn.Fees
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)
# matrix calc Pos.Qty * Price * Con.Mult to get Pos.Value
tmpPL$Pos.Value <- tmpPL$Pos.Qty * tmpPL$Con.Mult * tmpPL$Prices
- # matrix calc Unrealized.PL as Pos.Qty*(Price-Pos.Avg.Cost)*Con.Mult
- tmpPL$Unrealized.PL <- round(tmpPL$Pos.Qty*(tmpPL$Prices-tmpPL$Pos.Avg.Cost)*tmpPL$Con.Mult,2)
-
- # matrix calc Gross.Trading.PL as Pos.Value-Lag(Pos.Value)-Txn.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
- # matrix calc Realized.PL as Gross.Trading.PL - Unrealized.PL
- tmpPL$Realized.PL <- round(tmpPL$Gross.Trading.PL - tmpPL$Unrealized.PL,2)
+ # 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$Gross.Trading.PL <- tmpPL$Pos.Value - (tmpPL$Pos.Qty*tmpPL$Pos.Avg.Cost) + tmpPL$Gross.Txn.Realized.PL
+ tmpPL$Period.Realized.PL <- tmpPL$Net.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
@@ -101,10 +114,10 @@
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', 'Realized.PL', 'Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')]
+ 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
- if(isTRUE(rmfirst)) tmpPL<-tmpPL[-1,] #remove the constructed first row, so we don't insert dups in the table
+ 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)
@@ -160,7 +173,7 @@
}
#multiply the correct columns
- columns<-c('Pos.Value', 'Txn.Value', 'Realized.PL', 'Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')
+ columns<-c('Pos.Value', 'Txn.Value', 'Period.Realized.PL', 'Period.Unrealized.PL','Gross.Trading.PL', 'Txn.Fees', 'Net.Trading.PL')
# for (column in columns){
# TmpPeriods[,column]<-TmpPeriods[,column]*CcyMult
# }
Modified: pkg/blotter/demo/turtles.R
===================================================================
--- pkg/blotter/demo/turtles.R 2010-09-27 13:03:51 UTC (rev 402)
+++ pkg/blotter/demo/turtles.R 2010-10-02 18:12:24 UTC (rev 403)
@@ -1,29 +1,4 @@
-updateStrat <- function(Portfolio, Symbol, TxnDate, PosUnitsQty, UnitSize, StopPrice, TxnPrice, TxnN)
-{ # @author Peter Carl
- # DESCRIPTION:
- # Adds transactions-related data to the STRATEGY timeseries.
-
- # Inputs
- # TxnDate: transaction date as ISO 8106, e.g., '2008-09-01'
- # PosUnitsQty: total units (shares) of the transaction
- # StopPrice: price at which the transaction was done
- # TxnPrice: last trade price
- # TxnN: calculated N for last transaction
-
- # Outputs:
- # 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 )
-}
-
# - Turtle System #1
# required libraries
@@ -31,6 +6,11 @@
require(TTR)
require(blotter)
+# Try to clean up in case the demo was run previously
+try(rm("account.turtles","portfolio.turtles",pos=.blotter),silent=TRUE)
+try(rm("portfolio","account","N","symbol","symbols","ClosePrice","CurrentDate","equity","Units","maxUnits","size","Stop","equity","TxnPrice","initDate","initEq","Posn","verbose"),silent=TRUE)
+
+
# Set initial values
initDate="2008-01-01"
initEq=100000
@@ -42,6 +22,33 @@
stock(symbol, currency="USD",multiplier=1)
}
+#set function for storing intermediate values
+updateStrat <- function(Portfolio, Symbol, TxnDate, PosUnitsQty, UnitSize, StopPrice, TxnPrice, TxnN)
+{ # @author Peter Carl
+
+ # DESCRIPTION:
+ # Adds transactions-related data to the STRATEGY timeseries.
+
+ # Inputs
+ # TxnDate: transaction date as ISO 8106, e.g., '2008-09-01'
+ # PosUnitsQty: total units (shares) of the transaction
+ # StopPrice: price at which the transaction was done
+ # TxnPrice: last trade price
+ # TxnN: calculated N for last transaction
+
+ # Outputs:
+ # 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 )
+}
+
getSymbols(symbols, index.class="POSIXct", from=initDate, source="yahoo")
# getSymbols now defaults (as originally) to "Date" indexing. We can change to use POSIXct here.
# getSymbols(symbols, index.class=c("POSIXt","POSIXct"), from=initDate, source="yahoo")
More information about the Blotter-commits
mailing list