[Blotter-commits] r512 - in pkg/blotter: . R
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Thu Dec 30 22:21:47 CET 2010
Author: braverock
Date: 2010-12-30 22:21:45 +0100 (Thu, 30 Dec 2010)
New Revision: 512
Added:
pkg/blotter/R/tradeStats.R
Modified:
pkg/blotter/NAMESPACE
Log:
- add tradeStats function
Modified: pkg/blotter/NAMESPACE
===================================================================
--- pkg/blotter/NAMESPACE 2010-12-23 17:51:50 UTC (rev 511)
+++ pkg/blotter/NAMESPACE 2010-12-30 21:21:45 UTC (rev 512)
@@ -17,3 +17,4 @@
export(updateAcct)
export(updateEndEq)
export(updatePortf)
+export(tradeStats)
Added: pkg/blotter/R/tradeStats.R
===================================================================
--- pkg/blotter/R/tradeStats.R (rev 0)
+++ pkg/blotter/R/tradeStats.R 2010-12-30 21:21:45 UTC (rev 512)
@@ -0,0 +1,159 @@
+#' 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:
+#' \itemize{
+#' \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 Knect}{ 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!
+#'
+#' @param Portfolio portfolio string
+#' @param Symbols character vector of symbol strings, default NULL
+#' @author Lance Levenson
+#' @export
+#' TODO document each statistic included in this function, with equations
+tradeStats <- function(Portfolios, Symbols)
+{
+ 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))
+ else Portfolio <- try(get(pname, envir = .blotter))
+ 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 <- names(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]
+
+ TotalNetProfit <- sum(txn$Net.Txn.Realized.PL)
+
+ GrossProfits <- sum(PL.gt0)
+ GrossLosses <- sum(PL.lt0)
+ ProfitFactor <- abs(GrossProfits/GrossLosses)
+
+ AvgTradePL <- mean(PL.ne0)
+ MedTradePL <- median(PL.ne0)
+ StdTradePL <- as.numeric(sd(PL.ne0))
+
+ NumberOfTrades <- nrow(txn)
+
+ PercentPositive <- (nrow(PL.gt0)/nrow(PL.ne0))*100
+ PercentNegative <- (nrow(PL.lt0)/nrow(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
+
+ AvgDailyPL <- mean(apply.daily(PL.ne0,sum))
+ MedDailyPL <- median(apply.daily(PL.ne0,sum))
+ StdDailyPL <- as.numeric(sd(apply.daily(PL.ne0,sum)))
+
+ Equity <- cumsum(posPL$Net.Trading.PL)
+ Equity.max <- cummax(Equity)
+ maxEquity <- max(Equity)
+ minEquity <- min(Equity)
+ endEquity <- last(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.')
+ message('Total Net Profit for',symbol,'from transactions',TotalNetProfit,'and cumulative P&L from the Equity Curve', endEquity, 'do not match.')
+
+ }# 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
+
+ #TODO add skewness, kurtosis, and positive/negative semideviation if PerfA is available.
+
+ tmpret <- data.frame(Portfolio=pname,
+ Symbol=symbol,
+ 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,
+ maxDrawdown=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)
+}
+
+
+###############################################################################
+# Blotter: Tools for transaction-oriented trading systems development
+# for R (see http://r-project.org/)
+# Copyright (c) 2008-2010 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$
+#
+###############################################################################
More information about the Blotter-commits
mailing list