From noreply at r-forge.r-project.org Mon Dec 1 17:02:39 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 1 Dec 2014 17:02:39 +0100 (CET) Subject: [Blotter-commits] r1658 - pkg/blotter/R Message-ID: <20141201160239.B68AC187889@r-forge.r-project.org> Author: bodanker Date: 2014-12-01 17:02:39 +0100 (Mon, 01 Dec 2014) New Revision: 1658 Modified: pkg/blotter/R/updateAcct.R Log: - Fix #5983; thanks to Alexios Ghalanos for the report/patch Modified: pkg/blotter/R/updateAcct.R =================================================================== --- pkg/blotter/R/updateAcct.R 2014-11-29 13:39:24 UTC (rev 1657) +++ pkg/blotter/R/updateAcct.R 2014-12-01 16:02:39 UTC (rev 1658) @@ -111,7 +111,7 @@ }, Additions = { result = if(on=="none") - as.xts(sum(Account$Additions[paste("::",obsDates, sep="")]), order.by=index(table)) + as.xts(sum(Account$Additions[obsDates]), order.by=index(table)) else{ if(length(Account$Additions[obsDates])>0) # catch empty sets period.apply(Account$Additions[obsDates], endpoints(Account$Additions[obsDates], on=on), sum) # aggregates multiple account txns @@ -121,7 +121,7 @@ }, Withdrawals = { result = if(on=="none") - as.xts(sum(Account$Withdrawals[paste("::",obsDates, sep="")]), order.by=index(table)) + as.xts(sum(Account$Withdrawals[obsDates]), order.by=index(table)) else{ if(length(Account$Withdrawals[obsDates])>0) # catch empty sets period.apply(Account$Withdrawals[obsDates], endpoints(Account$Withdrawals[obsDates], on=periodicity(table)$units), sum) @@ -131,7 +131,7 @@ }, Interest = { result = if(on=="none") - as.xts(sum(Account$Interest[paste("::",obsDates, sep="")]),, order.by=index(table)) + as.xts(sum(Account$Interest[obsDates]), order.by=index(table)) else{ if(length(Account$Interest[obsDates])>0) # catch empty sets period.apply(Account$Interest[obsDates], endpoints(Account$Interest[obsDates], on=periodicity(table)$units), sum) From noreply at r-forge.r-project.org Wed Dec 3 18:55:20 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 3 Dec 2014 18:55:20 +0100 (CET) Subject: [Blotter-commits] r1659 - pkg/blotter/sandbox Message-ID: <20141203175520.F28E018794A@r-forge.r-project.org> Author: bodanker Date: 2014-12-03 18:55:20 +0100 (Wed, 03 Dec 2014) New Revision: 1659 Modified: pkg/blotter/sandbox/blotter_R6.R Log: - More blotter_R6 experiments Modified: pkg/blotter/sandbox/blotter_R6.R =================================================================== --- pkg/blotter/sandbox/blotter_R6.R 2014-12-01 16:02:39 UTC (rev 1658) +++ pkg/blotter/sandbox/blotter_R6.R 2014-12-03 17:55:20 UTC (rev 1659) @@ -18,8 +18,28 @@ # Proposed blotter structure (comments welcome): # > Account (R6 'Account' object) +# $ addTxn / addTxns (addAcctTxn) +# $ addPortfolio +# $ Returns (AcctReturns) +# $ PortfReturns (PortfReturns) +# $ getPortfolioAttribute (getByPortf) +# $ getEquity (getEndEq) +# $ updateAcct (updateAcct) +# $ updateEndEq (updateEndEq) # -> Portfolios (list|env of R6 'Portfolio' objects) +# $ addInstrument (addPortfInstr) +# $ calcPortfWgt (calcPortfWgt) +# $ getSymbolAttribute (getBySymbol) +# $ updatePortf # -> Positions (list|env of R6 'Position' objects) +# $ addTxn / addTxns (addTxn / addTxns) +# $ getPos +# $ getPosQty +# $ getTxn +# $ tradeStats +# $ perTradeStats +# $ chart.Posn +# $ chart.ME # -> Instrument # -> Transaction # - trades, splits, dividends, expirations, assignments, etc. @@ -38,26 +58,153 @@ # If we choose either one, we need to ensure that the "name" member of the # new Portfolio object matches the "name" of the Account$portfolios "list". +#acct$portfolios$MyPort$positions$SPY$addTxn() + +# Q: Can we add stuff to the public environment internally? +# A: No, because self is locked +Simple <- R6Class("Simple", + public = list( + x = 1, + add = function(name, value) { + assign(name, value, self) + } + ) +) +s <- Simple$new() +s$add("y",2) # fails +# but maybe we can lock the binding of the portfolios in the environment? +Simple <- R6Class("Simple", + public = list( + initialize = function() { + self$portfolios <- new.env() + lockBinding("portfolios",self) + }, + x = 1, + portfolios = NULL, + add = function(name, value) { + unlockBinding("portfolios",self) + assign(name, value, self$portfolios) + lockBinding("portfolios",self) + } + ) +) +s <- Simple$new() +s$add("y",2) # works! +# but this also works unless the environment is locked... +rm(y, envir=s$portfolios) + + library(R6) library(blotter) +Account <- R6Class(classname = "Account", + public = list( + portfolios = NULL, + initialize = function(portfolios, date, equity, currency) { + # create the portfolios environment, then lock its binding + # still need to lock portfolios itself though, but there's no + # way to unlock environments in base R + self$portfolios <- new.env() + lockBinding("portfolios", self) + + if(!missing(currency)) private$currency. <- currency + }, + deposit = function(date, amount) { + private$deposits. <- rbind(private$deposits., xts(amount, date)) + #invisible(self) # if you want to allow chained calls + }, + withdrawal = function(date, amount) { + private$withdrawals. <- rbind(private$withdrawals., xts(amount, date)) + #invisible(self) # if you want to allow chained calls + }, + interest = function(date, amount) { + private$interest. <- rbind(private$interest., xts(amount, date)) + #invisible(self) # if you want to allow chained calls + }, + addPortfolio <- function(portfolio) { + if(inherits(portfolio, "Portfolio")) { + # unlock/relock portfolios environment here too, once it can be unlocked + unlockBinding("portfolios", self) + assign(portfolio$name, value, portfolios) + lockBinding("portfolios", self) + #invisible(self) # if you want to allow chained calls + } else { + stop(deparse(substitute(portfolio)), " is not a Portfolio object", call.=FALSE) + } + } + ), + private = list( + currency. = NA_character_, + deposits. = NULL, + interest. = NULL, + withdrawals. = NULL + ), + active = list( + equity = function(value) { + if(missing(value)) { + stop("equity calculation not yet implemented") + } else { + stop("equity cannot be directly updated") + } + } + ) +) + +Portfolio <- R6Class(classname = "Portfolio", + public = list( + positions = NULL, + initialize = function(positions, date, currency) { + # create the positions environment, then lock its binding + # still need to lock positions itself though, but there's no + # way to unlock environments in base R + self$positions <- new.env() + lockBinding("positions", self) + + if(!missing(currency)) private$currency. <- currency + }, + addPosition <- function(position) { + if(inherits(positions, "Position")) { + # unlock/relock positions environment here too, once it can be unlocked + unlockBinding("positions", self) + assign(position$symbol, value, positions) + lockBinding("positions", self) + #invisible(self) # if you want to allow chained calls + } else { + stop(deparse(substitute(position)), " is not a Position object", call.=FALSE) + } + } + ), + private = list( + currency. = NA_character_ + ), + active = list( +# equity = function(value) { +# if(missing(value)) { +# stop("equity calculation not yet implemented") +# } else { +# stop("equity cannot be directly updated") +# } +# } + ) +) + # I'm not sure "Position" is the correct name for this thing, but I was trying # to create the most basic component of the blotter structure. Position <- R6Class(classname = "Position", public = list( #initialize = function(instrument, transactions) { initialize = function(symbol, transactions, currency) { - if(!missing(symbol)) private$.symbol <- symbol - if(!missing(currency)) private$.currency <- currency + if(!missing(symbol)) private$symbol. <- symbol + if(!missing(currency)) private$currency. <- currency }, # addTxn {{{ addTxn = function(date, quantity, price, fees=0, ..., ConMult=1, verbose=TRUE) { - null.txn <- is.null(private$.txn) + null.txn <- is.null(private$txn.) #PrevPosQty <- getPos(date, 'Pos.Qty') # returns position 'as-of' date if(null.txn) PrevPosQty <- 0 else { - PrevPosQty <- private$.txn[paste0("/",date), 'Pos.Qty'] + PrevPosQty <- private$txn.[paste0("/",date), 'Pos.Qty'] PrevPosQty <- PrevPosQty[nrow(PrevPosQty),] } @@ -104,7 +251,7 @@ if(null.txn) PrevPosAvgCost <- 0 else { - PrevPosAvgCost <- private$.txn[paste0("/",date), 'Pos.Avg.Cost'] + PrevPosAvgCost <- private$txn.[paste0("/",date), 'Pos.Avg.Cost'] PrevPosAvgCost <- PrevPosAvgCost[nrow(PrevPosAvgCost),] } PosAvgCost <- blotter:::.calcPosAvgCost(PrevPosQty, PrevPosAvgCost, TxnValue, PosQty, ConMult) @@ -126,42 +273,42 @@ txnCols <- 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") - private$.txn <- rbind(private$.txn, xts(t(txn), date, dimnames=list(NULL, txnCols))) + private$txn. <- rbind(private$txn., xts(t(txn), date, dimnames=list(NULL, txnCols))) if(verbose) - print(paste(format(date, "%Y-%m-%d %H:%M:%S"), private$.symbol, quantity, "@", price, sep=" ")) + print(paste(format(date, "%Y-%m-%d %H:%M:%S"), private$symbol., quantity, "@", price, sep=" ")) invisible(self) } #}}} ), private = list( - .symbol = NA_character_, - .currency = NA_character_, - .txn = NULL + symbol. = NA_character_, + currency. = NA_character_, + txn. = NULL ), # use active bindings for type-checking; is there a better way? active = list( symbol = function(value) { if(missing(value)) { - private$.symbol + private$symbol. } else { stop("symbol is read-only") } }, currency = function(value) { if(missing(value)) { - private$.currency + private$currency. } else { if(is.character(value) && length(value)==1) - private$.currency <- value + private$currency. <- value else stop(deparse(substitute(value)), " is an invalid currency name") } }, transactions = function(value) { if(missing(value)) { - if(!is.null(private$.txn)) - private$.txn[,c("Txn.Qty", "Txn.Price", "Txn.Fees", + if(!is.null(private$txn.)) + private$txn.[,c("Txn.Qty", "Txn.Price", "Txn.Fees", "Txn.Value", "Txn.Avg.Cost", "Net.Txn.Realized.PL")] } else { stop("use addTxn to add a transaction") @@ -169,8 +316,8 @@ }, txns = function(value) { if(missing(value)) { - if(!is.null(private$.txn)) - private$.txn[,c("Txn.Qty", "Txn.Price", "Txn.Fees", + if(!is.null(private$txn.)) + private$txn.[,c("Txn.Qty", "Txn.Price", "Txn.Fees", "Txn.Value", "Txn.Avg.Cost", "Net.Txn.Realized.PL")] } else { stop("use addTxn to add a transaction") @@ -178,7 +325,7 @@ }, txn = function(value) { if(missing(value)) { - private$.txn + private$txn. } else { stop("txn is read-only") } @@ -213,83 +360,3 @@ } - -# other stuff; not sure it's useful -if(FALSE){ -Portfolio <- R6Class(classname = "Portfolio", - public = list( - initialize = function(name, positions, currency) { - if(!missing(name)) - private$.name <- name - if(!missing(positions)) { - if(is.list(positions)) - for(p in positions) - assign(p$symbol, p, private$.positions) - else - assign(positions$symbol, positions, private$.positions) - } - }, - update = function(symbols, dates, prices, interval) { } - ), - private = list( - .positions = new.env(hash=TRUE), - .name = "default" - ), - active = list( - name = function(value) { - if(missing(value)) { - private$.name - } else { - if(is.character(value) && length(value)==1) - private$.name <- value - else - stop(deparse(substitute(value)), " is an invalid portfolio name") - } - }, - positions = function(value) { - value_name <- deparse(substitute(value)) - if(missing(value)) { - #if(value_name!="") - # return a copy of the .positions environment as a list, because - # we do not want users to be able to change positions manually - # as.list(get(value_name, private$.positions, inherits=FALSE)) - as.list(private$.positions) - #else - # NULL - } else { - if(inherits(value, "Position")) { - assign(value_name, value, private$.positions) - } else { - stop(value_name, " is not a Position object", call.=FALSE) - } - } - } - ) -) -pos <- Position$new('foo') -pos$addTxn(Sys.Date()-1L, 10, 90, 0) -pos$addTxn(Sys.Date(), -10, 100, 0) -pos$txns -p <- Portfolio$new("hello_world", pos, "USD") -p$positions - -# prototype -Positions <- R6Class(classname = "Positions", - public = list( - add = function(position) { - if(missing(position)) - invisible() - if(inherits(position, "Position")) { - assign(position$symbol, position, private$.positions) - } else { - position_name <- deparse(substitute(position)) - stop(position_name, " is not a Position object", call.=FALSE) - } - } - ), - private = list( - .positions = new.env(hash=TRUE) - ) -) -} - From noreply at r-forge.r-project.org Sun Dec 7 20:47:28 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 7 Dec 2014 20:47:28 +0100 (CET) Subject: [Blotter-commits] r1660 - in pkg/FinancialInstrument: . R Message-ID: <20141207194728.9D6FE187716@r-forge.r-project.org> Author: gsee Date: 2014-12-07 20:47:28 +0100 (Sun, 07 Dec 2014) New Revision: 1660 Modified: pkg/FinancialInstrument/DESCRIPTION pkg/FinancialInstrument/NAMESPACE pkg/FinancialInstrument/R/FinancialInstrument-package.R Log: Depend on quantmod >= 0.4-3 and use importDefaults from there instead of the deprecated Defaults package Modified: pkg/FinancialInstrument/DESCRIPTION =================================================================== --- pkg/FinancialInstrument/DESCRIPTION 2014-12-03 17:55:20 UTC (rev 1659) +++ pkg/FinancialInstrument/DESCRIPTION 2014-12-07 19:47:28 UTC (rev 1660) @@ -13,12 +13,11 @@ Date: 2014-10-07 Depends: R (>= 2.12.0), - quantmod (>= 0.4-2), + quantmod (>= 0.4-3), zoo (>= 1.7-5), xts Imports: - TTR, - Defaults (>= 2.0.0) + TTR Suggests: foreach, XML (>= 3.96.1.1), Modified: pkg/FinancialInstrument/NAMESPACE =================================================================== --- pkg/FinancialInstrument/NAMESPACE 2014-12-03 17:55:20 UTC (rev 1659) +++ pkg/FinancialInstrument/NAMESPACE 2014-12-07 19:47:28 UTC (rev 1660) @@ -138,7 +138,6 @@ export(update_instruments.yahoo) export(volep) import(xts) -importFrom(Defaults,importDefaults) importFrom(TTR,runSum) importFrom(TTR,stockSymbols) importFrom(quantmod,Ad) @@ -159,6 +158,7 @@ importFrom(quantmod,has.Price) importFrom(quantmod,has.Trade) importFrom(quantmod,has.Vo) +importFrom(quantmod,importDefaults) importFrom(quantmod,is.BBO) importFrom(quantmod,is.HLC) importFrom(quantmod,is.OHLC) Modified: pkg/FinancialInstrument/R/FinancialInstrument-package.R =================================================================== --- pkg/FinancialInstrument/R/FinancialInstrument-package.R 2014-12-03 17:55:20 UTC (rev 1659) +++ pkg/FinancialInstrument/R/FinancialInstrument-package.R 2014-12-07 19:47:28 UTC (rev 1660) @@ -5,7 +5,7 @@ #' getSymbolLookup setSymbolLookup yahooQF has.Vo Vo getOptionChain #' @importFrom TTR stockSymbols runSum #' @importFrom zoo na.locf as.zoo coredata is.zoo index -#' @importFrom Defaults importDefaults +#' @importFrom quantmod importDefaults NULL # for packages in Suggests: From noreply at r-forge.r-project.org Sun Dec 7 22:32:37 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 7 Dec 2014 22:32:37 +0100 (CET) Subject: [Blotter-commits] r1661 - pkg/FinancialInstrument Message-ID: <20141207213238.0B4E2187654@r-forge.r-project.org> Author: gsee Date: 2014-12-07 22:32:37 +0100 (Sun, 07 Dec 2014) New Revision: 1661 Modified: pkg/FinancialInstrument/NEWS Log: update NEWS only Modified: pkg/FinancialInstrument/NEWS =================================================================== --- pkg/FinancialInstrument/NEWS 2014-12-07 19:47:28 UTC (rev 1660) +++ pkg/FinancialInstrument/NEWS 2014-12-07 21:32:37 UTC (rev 1661) @@ -4,8 +4,8 @@ USER VISIBLE CHANGES -------------------- -* No longer using Defaults package (which is now archived on CRAN) in - getSymbols.FI. +* Requires quantmod >= 0.4-3 and no longer using the Defaults package + (which is now archived on CRAN) for importDefaults() in getSymbols.FI. * getSymbols.FI() allows the user to set default values by checking for options(). For example, the default value for from= is now From noreply at r-forge.r-project.org Fri Dec 26 21:13:24 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 26 Dec 2014 21:13:24 +0100 (CET) Subject: [Blotter-commits] r1662 - in pkg/quantstrat: . sandbox/backtest_musings Message-ID: <20141226201324.B4F2B186509@r-forge.r-project.org> Author: braverock Date: 2014-12-26 21:13:24 +0100 (Fri, 26 Dec 2014) New Revision: 1662 Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/sandbox/backtest_musings/stat_process.bib pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.Rmd pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.pdf Log: - add notes on data transformation for predictor values, references to Kuhn 2013 Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2014-12-07 21:32:37 UTC (rev 1661) +++ pkg/quantstrat/DESCRIPTION 2014-12-26 20:13:24 UTC (rev 1662) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.9.1657 +Version: 0.9.1662 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: Modified: pkg/quantstrat/sandbox/backtest_musings/stat_process.bib =================================================================== --- pkg/quantstrat/sandbox/backtest_musings/stat_process.bib 2014-12-07 21:32:37 UTC (rev 1661) +++ pkg/quantstrat/sandbox/backtest_musings/stat_process.bib 2014-12-26 20:13:24 UTC (rev 1662) @@ -153,6 +153,14 @@ publisher={McGraw-Hill} } + at Book{Kuhn2013, + Title = {Applied predictive modeling}, + Author = {Kuhn, Max and Johnson, Kjell}, + Publisher = {Springer}, + Year = {2013}, + url = {http://appliedpredictivemodeling.com/} +} + @misc{mistakes2011, author={Martha K. Smith}, author_sort={Smith, Martha}, Modified: pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.Rmd =================================================================== --- pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.Rmd 2014-12-07 21:32:37 UTC (rev 1661) +++ pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.Rmd 2014-12-26 20:13:24 UTC (rev 1662) @@ -484,7 +484,7 @@ of training and cross validation tests in every part of strategy evaluation. Of particular utility is the application of these techniques to each *component* of the strategy, in turn, rather than or before testing the -entire strategy model. +entire strategy model. (see, e.g. @Kuhn2013) \newthought{Defining the objectives, hypotheses, and expected outcome(s)} of the experiment (backtest) as declared before any strategy code is written or run @@ -545,6 +545,18 @@ chosen subsets. Failure to exercise care here leads almost inevitably to overfitting (and poor out of sample results). +An indicator is, at it's core, a measurement used to make a prediction. +This means that the broader literature on statistical predictors is valid. +Many techniques have been developed by statisticians and other modelers +to improve the predictive value of model inputs. See @Kuhn2013 or Hastie +!@Hastie2009. Input scaling, detrending, centering, de-correlating, and many +other techniques may all be applicable. The correct adjustments or +transformations will depend on the nature of the specific indicator. +Luckily, the statistics literature is also full of diagnostics to help +determine which methods to apply, and what their impact is. You do need +to remain cognizant of what you give up in each of these cases in terms +of interpretability, trace-ability, or microstructure of the data. + It is also important to be aware of the structural dangers of bars. Many indicators are constructed on periodic or "bar" data. Bars are not a particularly stable analytical unit, and are often sensitive to exact @@ -631,7 +643,7 @@ signals, holding period, etc.) to the process you are evaluating, to ensure that you are really looking at comparable things. -Because every signal is a prediction, when analysing of signal processes, we +Because every signal is a prediction, when analyzing signal processes, we can begin to fully apply the literature on model specification and testing of predictions. From the simplest available methods such as mean squared model error or kernel distance from an ideal process, through extensive evaluation @@ -680,6 +692,18 @@ exact entry rule from the signal process, there will likely be a positive expectation for the entry in production. +Another analysis of entry rules that may be carried out both on the backtest +and in post-trade analysis is to extract the distribution of duration between +entering the order and getting a fill. Differences between the backtest and +production will provide you with information to calibrate the backtest +expectations. Information from post trade analysis will provide you with +information to calibrate your execution and microstructure parameters. +You can also analyze how conservative or aggressive your backtest fill +assumptions are by analyzing how many opportunities you may have had to +trade at the order price after entering the order but before the price +changes, or how many shares or contracts traded at your order price before +you would have moved or canceled the order. + ## exit rules There are two primary classes of exit rules, signal based and empirical; @@ -1157,7 +1181,7 @@ \includegraphics{MAE} \end{marginfigure} Maximum Adverse Excursion (MAE) or Maximum Favorable Excursion (MFE) show how -far down (or up) every trade went during the course of its lifecycle. You +far down (or up) every trade went during the course of its life-cycle. You can capture information on how many trades close close to their highs or lows, as well as evaluating points at which the P&L for the trade statistically just isn't going to get any better, or isn't going to recover. While @@ -1295,7 +1319,7 @@ - tail risk measures - volatility analysis - factor analysis - - factor model monte carlo + - factor model Monte Carlo - style analysis - comparing strategies in return space - applicability to asset allocation (see below) @@ -1339,14 +1363,14 @@ \newthought{What if you don't have enough data?} Let's suppose you want 500 observations for each of 50 synthetic assets based on the rule of thumb above. -That is approximately two years of daily returns. This number of obervations +That is approximately two years of daily returns. This number of observations would likely produce a high degree of confidence if you had been running the strategy on 50 synthetic assets for two years in a stable way. If you want to allocate capital in alignment with your business objectives before you have enough data, you can do a number of things: - use the data you have and re-optimize frequently to check for stability and add more data -- use higher frequency data, e.g. hourly instead fo daily +- use higher frequency data, e.g. hourly instead of daily - use a technique such as Factor Model Monte Carlo (Jiang 2007, Zivot 2011,2012) to construct equal histories - optimize over fewer assets, requiring a smaller history @@ -1414,7 +1438,7 @@ that may identify how much out of sample deterioration could be expected. With all of the methods described in this section, it is important to note -that you ar no longer measuring performance; that was covered in prior +that you are no longer measuring performance; that was covered in prior sections. At this point, we are measuring statistical error, and developing or refuting the level of confidence which may be appropriate for the backtest results. We have absolutely *fitted* the strategy to the data, but is it @@ -1539,7 +1563,7 @@ OOS periods in walk forward analysis are effectively validation sets as in cross validation. You can and should measure the out of sample deterioration of your walk forward model between the IS performance and the OOS performance -of the model. One advantage od walk forward is that it allows parameters to +of the model. One advantage of walk forward is that it allows parameters to change with the data. One disadvantage is that there is a temptation to make the OOS periods for walk forward analysis rather small, making it very difficult to measure deterioration from the training period. Another potential @@ -1549,7 +1573,7 @@ considered an advantage. The IS periods are not all independent draws from the data, and the OOS periods will later be used as IS periods, so any analytical technique that assumes *i.i.d.* observations should be viewed at least with -scepticism. +skepticism. *k*-fold cross validation improves on the classical single hold-out OOS model by randomly dividing the sample of size *T* into sequential @@ -1591,6 +1615,7 @@ - data mining bias and cross validation from @Aronson2006 +\newpage # Acknowledgements Modified: pkg/quantstrat/sandbox/backtest_musings/strat_dev_process.pdf =================================================================== (Binary files differ) From noreply at r-forge.r-project.org Wed Dec 31 14:19:06 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 31 Dec 2014 14:19:06 +0100 (CET) Subject: [Blotter-commits] r1663 - in pkg/quantstrat: . R demo man Message-ID: <20141231131906.3646818794A@r-forge.r-project.org> Author: michaelguan326 Date: 2014-12-31 14:19:05 +0100 (Wed, 31 Dec 2014) New Revision: 1663 Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/NAMESPACE pkg/quantstrat/R/signals.R pkg/quantstrat/demo/00Index pkg/quantstrat/man/ruleOrderProc.Rd Log: New Signal Analysis Module Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2014-12-26 20:13:24 UTC (rev 1662) +++ pkg/quantstrat/DESCRIPTION 2014-12-31 13:19:05 UTC (rev 1663) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.9.1662 +Version: 0.9.1663 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: @@ -14,12 +14,16 @@ PortfolioAnalytics, rgl, testthat, - xtsExtra + xtsExtra, + rCharts, + gamlss.util, + reshape2, + beanplot Maintainer: Brian G. Peterson Description: Specify, build, and back-test quantitative financial trading and portfolio strategies Contributors: Yu Chen, Joe Dunn, Dirk Eddelbuettel, - Jeffrey A. Ryan, Garrett See + Michael Guan, Jeffrey A. Ryan, Garrett See LazyLoad: yes License: GPL-3 ByteCompile: TRUE Modified: pkg/quantstrat/NAMESPACE =================================================================== --- pkg/quantstrat/NAMESPACE 2014-12-26 20:13:24 UTC (rev 1662) +++ pkg/quantstrat/NAMESPACE 2014-12-31 13:19:05 UTC (rev 1663) @@ -1,5 +1,6 @@ # Generated by roxygen2 (4.0.2): do not edit by hand +S3method(plot,signal.path) export(add.distribution) export(add.distribution.constraint) export(add.indicator) @@ -9,6 +10,7 @@ export(addOrder) export(addPosLimit) export(apply.paramset) +export(apply.paramset.signal.analysis) export(applyIndicators) export(applyRules) export(applySignals) Modified: pkg/quantstrat/R/signals.R =================================================================== --- pkg/quantstrat/R/signals.R 2014-12-26 20:13:24 UTC (rev 1662) +++ pkg/quantstrat/R/signals.R 2014-12-31 13:19:05 UTC (rev 1663) @@ -371,6 +371,575 @@ return(ret) } +#' Signal Analysis With Parmeter Optimization +#' +#' This function allows user to analyze signals independently from rules. +#' +#' This function is similar to \code{applyParameter} but includes additionally \code{applySignal} wrapped within it. To use it, the user +#' will need to initially define the distribution and constraints by using \code{add.distribution} and \code{add.distribution.constraint}. +#' +#' More generally, the function is designed to generate signals across various parameter combinations defined within the distribution and +#' constraints. Afterwards it extract the next N day price changes for further anlaysis. +#' +#' The parameter \code{on} allows user to calculate post signal returns in different frequencies. Different signals have different timeframes effectiveness. +#' \code{forward.days} lets the user select the number of post signal days to analyze results. +#' +#' To determine the goodness of a parameter set relative to all others, we let the user specify their own objective function (via parameter \code{obj.func}) +#' that will be used to calculate an objective value representing each parameter. These will then be sorted from best to worst. The +#' objective function will take in a single matrix \code{ret.mat} of price changes. Each row represents an individual signal +#' while each column represents periods/post signal. +#' +#' See demo 'signalAnalysisExample1.R' & 'signalAnalysisExample2.R' +#' +#' @param strategy.st an object of type 'strategy' to add the indicator to +#' @param paramset.label a label uniquely identifying the paramset within the strategy +#' @param portfolio.st text name of the portfolio to associate the order book with +#' @param sigval signal value to match against +#' @param sigcol column name to check for signal +#' @param on the periods endpoints to find as a character string +#' @param forward.days days to exit post signal +#' @param cum.sum whether to use cumsum on price changes +#' @param include.day.of.signal whether to include the day of signal generation +#' @param obj.fun objective function for determining goodness of each paramset +#' @param decreasing how to sort the obj.fun output values +#' @param mktdata market data +#' @param verbose whether to output processing messages +#' @author Michael Guan +#' @return +#' A list of objects that contains the results +#' \describe{ +#' \item{signals}{List of signals named by parameter combination. Each object within the list is a XTS object with columns being assets and rows being signals.} +#' \item{sigret.by.paramset}{List of list. Sorted by parameter combination and then by asset. Contains matrix of next day returns; columns are period (N day look ahead) and rows are signals} +#' \item{sigret.by.asset}{List of list. Sorted by Asset and then by parameter combinations. Contains same matrix as sigret.by.paramset} +#' \item{signal.stats}{List of signal statistics as calculated via custom user defined fitness function. Sorted by assets.} +#' } +#' @seealso +#' \code{\link{add.distribution}} +#' \code{\link{add.distribution.constraint}} +#' @export + +apply.paramset.signal.analysis<-function(strategy.st, paramset.label, portfolio.st, sigcol,sigval, + on,forward.days,cum.sum=TRUE,include.day.of.signal, + obj.fun,decreasing,mktdata=NULL,verbose=TRUE){ + + must.have.args(match.call(), c('strategy.st', 'paramset.label', 'portfolio.st')) # + + strategy <- must.be.strategy(strategy.st) + must.be.paramset(strategy, paramset.label) + portfolio <- .getPortfolio(portfolio.st) + + distributions <- strategy$paramsets[[paramset.label]]$distributions + constraints <- strategy$paramsets[[paramset.label]]$constraints + + param.combos <- expand.distributions(distributions) + param.combos <- apply.constraints(constraints, distributions, param.combos) + rownames(param.combos) <- NULL # reset rownames + + symbols = ls(portfolio$symbols) + + # list() + # ...$ Paramset1 Signals = xts object; columns = by asset + # ...$ Paramset2 Signals = xts object; columns = by asset + .sig.list<-list() #list of signals as xts objects, each element in list contains n columns of signals for each asset in universe + + + # list() by paramset + # ...$ Paramset1 + # ...$ Asset1 + # ...$ Asset2 + # ...$ Paramset2 + # ...$ Asset1 + # ...$ Asset2 + .sig.ret.by.paramset = list() + + # list() by asset + # ...$ Asset1: + # ...paramset1 + # ...paramset2 + # ...$ Asset2: + # ...$ paramset1 + # ...$ paramset2 + .sig.ret.by.asset = list() + for(sym in symbols) .sig.ret.by.asset[[sym]] = list() + + # Loop through parameter by row to get signals + # Loop through each symbol + # TODO: parallelize it + for(i in 1:nrow(param.combos)){ # param.combo = param.combos[1,] + param.combo = param.combos[i,] + + if(verbose)cat("Applying Parameter Set: ",toString(param.combo),'\n') + + # Attached Paramset to Strategy Object + strategy <- quantstrat:::install.param.combo(strategy, param.combo, paramset.label) + + # Generate Indicators and Signals for Given Paramset + name.ref = paste('paramset.',gsub(", ",".",toString(param.combo)),sep='') + .sig.list[[name.ref]] = applyIndicatorSignals(strategy, portfolio.st, mktdata, sigcol) + + # Construct Post Signal Returns, loop through signal for each asset + signal.ret.list.by.asset <- list() # post signal returns by asset + for(j in 1:length( symbols )){ + + # Extract Post Signal Price Deltas for Given Asset Signals [can't do apply() here, unless force a dim on it inside function] + signal.ret.list.by.asset[[symbols[j]]] = post.signal.returns(signals=.sig.list[[name.ref]][,paste(symbols[j],'.signal',sep='')], + sigval=sigval,on=on,forward.days=forward.days, + cum.sum=cum.sum,include.day.of.signal=include.day.of.signal) + + # Store Post Signal Price Deltas for Given Asset + .sig.ret.by.asset[[symbols[j]]][[name.ref]] = signal.ret.list.by.asset[[symbols[j]]] + } + + # Store Post Signal Price Deltas for Given Paramset + .sig.ret.by.paramset[[name.ref]] = signal.ret.list.by.asset + } + + # Generate Statistics by Asset + signal.stats<-list() + for(sym in symbols){ + signal.stats[[sym]] = signal.generate.statistics(post.ret=.sig.ret.by.asset[[sym]], obj.fun=obj.fun, decreasing=decreasing) + } + + results = list() + results$signals = .sig.list + results$sigret.by.paramset = .sig.ret.by.paramset + results$sigret.by.asset = .sig.ret.by.asset + results$signal.stats = signal.stats + return(results) +} + +#' Calculate Indicators and Signals for a Strategy +#' +#' Calculate signals given indicators and signal definitions. +#' +#' @param strategy an object (or the name of an object) type 'strategy' to add the indicator to +#' @param portfolio text name of the portfolio to associate the order book with +#' @param mktdata market data +#' @param sigcol String name of signal to use for analysis +#' @author Michael Guan +#' @return \code{xts} object with columns representing signals for each symbol +#' @seealso +#' \code{\link{apply.paramset.signal.analysis}} +#' \code{\link{applyIndicators}} +#' \code{\link{applySignals}} + +applyIndicatorSignals<-function(strategy, portfolio, mktdata, sigcol, ...){ + + # Get Portfolio & Symbols + pobj <- .getPortfolio(portfolio) + symbols <- ls(pobj$symbols) + + # Loop Through asset by asset and combine signal columns in to single xts object + .signals<-c() + for(symbol in symbols){ + mktdata <- get(symbol) #get market data for current iteration symbol + + # Apply Indicators and Signals for Given Asset + temp <- applyIndicators(strategy = strategy, mktdata = mktdata, ...) + temp <- applySignals(strategy = strategy, mktdata = temp, ...) + + sig.col = temp[,sigcol] + sig.col[which(is.na(sig.col) == TRUE),] = 0 + colnames(sig.col) <- paste(symbol,'.signal',sep='') + .signals = merge.xts(.signals,sig.col) #cbind,merge.xts,or merge? + } + + return(.signals) +} + + +#' Signal Objective Function Calculation +#' +#' This function takes a list of matrix of post signal price changes and +#' applies an user defined objective function on it. +#' +#' @param post.ret \code{matrix} of parameter set of post signal price deltas +#' @param obj.fun custom objective function for measuring signal goodness +#' @param decreasing if true, the higher the objective value, the better +#' @author Michael Guan +#' @return objective function values +#' @seealso +#' \code{\link{apply.paramset.signal.analysis}} + +signal.generate.statistics<-function(post.ret, obj.fun=NULL, decreasing=TRUE){ + if(is.null(obj.fun)) stop("Must define an objective function for signal sorting.") + obj.fun = match.fun(obj.fun) + results = list() + obj.values = matrix(NA,nrow=length(post.ret),ncol=1) + row.names = c() + + for(j in 1:length(names(post.ret))){ + obj.value = obj.fun(post.ret[[names(post.ret)[j]]]) + if(length(obj.value)!=1) stop('Custom objective function must return only a single value.') + obj.values[j,]=obj.value + row.names=c(row.names,names(post.ret)[j]) + } + rownames(obj.values) = row.names + + results[['obj']] = apply(obj.values,2,sort,decreasing=decreasing) #Sort + + return(results) +} + + +#' Generate Post Signal Returns +#' +#' This function collects and aggregates post signal price changes for N days forward. +#' +#' @param signals xts object with signals, one column +#' @param sigvals signal value to match against +#' @param on the periods endpoints to find as a character string +#' @param forward.days number of days to look forward after signal (days to exit post signal) +#' @param cum.sum \code{TRUE},\code{FALSE}; cumulative sum of price changes +#' @param include.day.of.signal whether to analyze the return on signal day +#' @param mktdata market data +#' @author Michael Guan +#' @return \code{matrix} of post signal price changes; rows = nth signal, column = nth period since signal +#' @seealso +#' \code{\link{apply.paramset.signal.analysis}} + +post.signal.returns<-function(signals,sigval,on=NULL,forward.days,cum.sum=TRUE, + include.day.of.signal=FALSE,mktdata=NULL){ + + # Incremental Index Values / Label Generation + if(include.day.of.signal == TRUE){ + days.increment = c(0,seq(1,forward.days)) + name.ref = sapply( days.increment ,function(x){paste("Period",x,sep='.')}) + }else{ + days.increment = seq(1,forward.days+1) + name.ref = sapply( days.increment[-length(days.increment)] ,function(x){paste("Period",x,sep='.')}) + } + + # Get Relevant Market Data + if(is.null(mktdata)){ + symbol = gsub('.signal','',colnames(signals)) + mktdata = get(symbol) + } + + if(!is.null(on)){ + # Determine Number of Periods in Given Frequency ie) 1 week has 5 days if signal frequency = days + days.in.period = cbind(na.omit(signals),na.omit(signals)[endpoints(na.omit(signals),on),])[,2] + days.in.period[which(days.in.period == 0),] = 1 + days.in.period[is.na(days.in.period),]=0 + days.in.period = max(rle(as.vector(days.in.period))$lengths) + 1 + }else{ + days.in.period = 1 + } + + # Get Price Delta + ret = tryCatch({ + ret = diff(Cl(mktdata)) + }, error = function(e){ + stop('Market Data does not contain a row with Close. Try to set and aggregate data on to a higher frequency.') + }) + ret[1,] = 0 + + # Align Mkt Data and Signals + signals = signals[index(ret),] + # Get Indexes of Signals + idx = which(as.vector(signals)==sigval) + + # Take out signals that cause "out of bounds" exception + idx.cancel = idx[which((nrow(signals) - idx) < max((days.increment * days.in.period)))] + if(length(idx.cancel)!=0){ + signals[idx.cancel,]=0 + idx = idx[-which(idx %in% idx.cancel)] + } + + if(length(idx) == 0)stop("There are no signals for analysis. Try reducing the number of look ahead periods.") + + # Daily return since signal; each column = days since signal; each row = each signal + signal.ret = matrix(NA,nrow=length(idx),ncol=length(name.ref)) #daily return since signal + + # Extract Returns + for(j in 1:length(idx)){ + + signal.ret[j,] = tryCatch({ + na.omit(diff(mktdata[idx[j] + (days.increment * days.in.period) ,4])) + }, error = function(e){ + cat('') + stop('Not enough forward data to evaluate post signal returns.') + }) + } + + colnames(signal.ret) = name.ref + + if(cum.sum == TRUE) signal.ret = t(apply(signal.ret,1,cumsum)) # cumulative sum of price changes yields equity drift + #matplot(signal.ret,type='l') + return(signal.ret) +} + + + +# post.signal.returns<-function(signals,sigval,on='weeks',forward.days,cum.sum=TRUE, +# include.day.of.signal=FALSE,mktdata=NULL){ +# +# # Get Relevant Market Data +# if(is.null(mktdata)){ +# symbol = gsub('.signal','',colnames(signals)) +# mktdata = get(symbol) +# } +# +# # Transform Market data to Specific Frequency +# if(!is.null(on)){ +# # Find the Dates for Mktdata in the frequency of interest +# # Find the Dates of Signals, merge the two to get the final dates of interest +# +# sig.date.idx = index(signals)[which(signals == sigval)] +# mktdata.temp = mktdata[endpoints(x=mktdata,on=on),] +# +# mktdata.idx = index(cbind(mktdata.temp,signals)) +# mktdata = mktdata[mktdata.idx,] +# signals = signals[mktdata.idx,] +# } +# +# # Get Price Delta +# ret = tryCatch({ +# ret = diff(Cl(mktdata)) +# }, error = function(e){ +# stop('Market Data does not contain a column with Close. Try to set and aggregate data on to a higher frequency.') +# }) +# ret[1,] = 0 +# +# # Align Mkt Data and Signals +# signals = signals[index(ret),] +# +# # Take out signals that cause "out of bounds" exception +# signals[(nrow(signals)-forward.days):nrow(signals),]=0 +# +# # Get Indexes of Signals +# idx = which(as.vector(signals)==sigval) +# +# if(length(idx) == 0) stop("There are no signals for analysis.") +# +# # Incremental Index Values / Label Generation +# if(isTRUE(include.day.of.signal)){ +# days.increment = c(0,seq(1,forward.days)) +# name.ref = sapply( days.increment ,function(x){paste("Period",x,sep='.')}) +# }else{ +# days.increment = seq(1,forward.days) +# name.ref = sapply( days.increment ,function(x){paste("Period",x,sep='.')}) +# } +# +# # Daily return since signal; each column = days since signal; each row = each signal +# signal.ret = matrix(NA,nrow=length(idx),ncol=length(name.ref)) #daily return since signal +# +# # Extract return +# for(j in 1:length(idx))signal.ret[j,] = ret[idx[j] + days.increment ,] +# +# colnames(signal.ret) = name.ref +# +# if(isTRUE(cum.sum)) signal.ret = t(apply(signal.ret,1,cumsum)) # cumulative sum of price changes yields equity drift +# +# return(signal.ret) +# } + + +#' Signal Objective Function +#' +#' Simple example of objective function that can can be used to measure the effectiveness of various parameter combinations. +#' +#' Calculates the slope of the Cumulative Equity line. Higher the better. +#' +#' It is important to note that all objective functions are called within \code{signal.generate.statistics}. What gets +#' passed in to it as parameter is an matrix of post signal price changes or cumulative equity for each signal. The matrix +#' is of N-by-M dimensions. N being the row representing the Nth signal. M being the column representing Mth period. +#' +#' @param x Return matrix, each row represents price deltas for a single signal, each column represents periods +#' @author Michael Guan +#' @return Single Objective Value +#' @seealso +#' \code{\link{apply.paramset.signal.analysis}} + +signal.obj.slope<-function(x){ + mu = colMeans(x) + lm.r = lm(mu~seq(length(mu))) + obj = coef(lm.r)[2] + return(obj) +} + + +#' Visualization of Signal Across Lookback +#' +#' This function takes a list of matrix of post signal price changes and +#' plots boxplots. Note function plots whatever is given to it therefore when +#' there are lots paramsets, it is best to plot a smaller portion so the +#' information can be displayed clearly. +#' +#' @param signal list of paramset forward looking price changes by asset +#' @param rows number of rows for plot +#' @param columns number of columns for plot +#' @param mai A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches. +#' @param mgp The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0). +#' @param xlab a title for the x axis +#' @param ylab a title for the y axis +#' @param cex.main The magnification to be used for main titles relative to the current setting of cex. +#' @param xaxt A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting. +#' @param cex.axis The magnification to be used for axis annotation relative to the current setting of cex. +#' @param h the y-value(s) for horizontal line(s). +#' @param hlinecol A specification for the default plotting color. See section ?Color Specification?. +#' @author Michael Guan +#' @return plot +#' + +plot.signals<-function(signals,rows=NULL,columns=NULL,mai = c(0.1,0.4,0.2,0.1), mgp = c(1,1,0), + xlab='',ylab='',cex.main=0.6,xaxt='n',cex.axis=0.5,h=0,hlinecol='red',...){ + + if(is.null(signals)) stop('No signals to plot') + + # Determine Plot layout + if(is.null(rows) | is.null(columns)){ + list.len = length(signals) + rows = ceiling(list.len / as.numeric(substring(toString(list.len),1,1))) + columns = ceiling(list.len / rows) + } + + # Set up display parameters + plt = par(mfrow=c(rows,columns),mai=mai,mgp=mgp) + + # Generate Boxplot for each paramset + for(plt in names(signals)){ + boxplot(x=signals[[plt]],main=plt,xlab=xlab,ylab=ylab, + cex.main=cex.main,xaxt=xaxt,cex.axis=cex.axis,...) + abline(h=h,col=hlinecol) + } + +} + +#' Visualization of Signal Across Lookback with Beanplots +#' +#' This function is similar to \code{plot.signals} but uses beanplots +#' instead of barplots. Requires 'beanplot' package +#' +#' @param signal list of paramset forward looking price changes by asset +#' @param rows number of rows for plot +#' @param columns number of columns for plot +#' @param mai A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches. +#' @param mgp The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0). +#' @param xlab a title for the x axis +#' @param ylab a title for the y axis +#' @param cex.main The magnification to be used for main titles relative to the current setting of cex. +#' @param xaxt A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting. +#' @param cex.axis The magnification to be used for axis annotation relative to the current setting of cex. +#' @param h the y-value(s) for horizontal line(s). +#' @param hlinecol A specification for the default plotting color. See section ?Color Specification?. +#' @author Michael Guan +#' @return plot + +beanplot.signals<-function(signals,rows=NULL,columns=NULL,mai = c(0.1,0.4,0.2,0.1), mgp = c(1,1,0), + xlab='',ylab='',cex.main=0.6,xaxt='n',cex.axis=0.5, + h=0,hlinecol='red',...){ + require(beanplot) + + if(is.null(signals)) stop('No signals to plot') + + # Determine Plot layout + if(is.null(rows) | is.null(columns)){ + list.len = length(signals) + rows = ceiling(list.len / as.numeric(substring(toString(list.len),1,1))) + columns = ceiling(list.len / rows) + } + + plt = par(mfrow=c(rows,columns),mai=mai,mgp=mgp) + + for(plt in names(signals)){ + beanplot(data.frame(signals[[plt]]),xlab=xlab,ylab=ylab,main=plt, + cex.main = cex.main,xaxt=xaxt,cex.axis=cex.axis,...) + abline(h=h,col=hlinecol) + } +} + + +#' Visualization of Single Signal +#' +#' This function employs \code(plotSimpleGamlss) in package \code(gamlss.util). +#' +#' @param signal list of paramset forward looking price changes by asset +#' @param x.val he values of the explanatory variable where we want to see the distribution +#' @param val this parameter determines how the plotted distribution is shown, increase/decrease it if the distribution is not shown properly +#' @param ylim the y limits in the plot +#' @param xlim the x limits in the plot +#' @param mai A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches. +#' @param h the y-value(s) for horizontal line(s). +#' @author Michael Guan +#' @return plot + +distributional.boxplot<-function(signal,x.val=seq(1, 50, 5),val=10,ylim=c(-5, 5), + xlim=c(0, 50),mai=c(1,1,0.3,0.5),h=0,...){ + + if(is.null(signal)) stop('No signals to plot') + if(!isTRUE("gamlss" %in% rownames(installed.packages()))) stop('Please install gamlss') + if(!isTRUE("gamlss.util" %in% rownames(installed.packages()))) stop('Please install gamlss.util') + + require(gamlss.util) + require(gamlss) + + # Reformat data + n.row = nrow(signal) + ind.var = matrix(signal) + dep.var = signal * NA + for(i in 1:ncol(dep.var)) dep.var[,i] = i + dep.var = matrix(dep.var) + + mat.data = cbind(dep.var,ind.var) + colnames(mat.data) = c('Period','Change') + mat.data = data.frame(mat.data) + par(mai=mai) + + # Regression + m1 <- gamlss(Change~Period, data=mat.data) + + # Visualization + tryCatch({ + plotSimpleGamlss(y=Change,x=Period, model=m1,data=mat.data, + x.val=x.val, # where to plot the dist + val=val, # size of dist + ylim=ylim, xlim=xlim) + abline(h=0,lty=3,...) + },error=function(e){cat('gamlss package currently doesnt + support encapsulation of their + plotting function. Pending Patch. \n')}) + +} + +#' Visualization of Signal Path +#' +#' This function creates a rChart - hplot that is interactive. It displays +#' +#' @param data signal data +#' @param main plot title +#' @author Michael Guan +#' @return plot +#' @examples +#' \dontrun{ +#' # signalAnalysisExample1.R +#' plot.signal.path(results$sigret.by.asset$RTH$paramset.1.5[1:10,]) +#' } +#' @export +plot.signal.path<-function(data,main='Cumulative Return Paths'){ + require(rCharts) #TODO: Need to wrap around If statement + require(reshape2) + data = t(data) + n.row = nrow(data) + ind.var = matrix(data) + dep.var = ind.var * NA + dep.var[] = rep(seq(1,n.row,1),ncol(data)) + + groups = ind.var * NA + groups[]=melt(sapply( seq(1,ncol(data),1),function(x)rep(x,n.row)))[,2] + + + mat = cbind(dep.var,ind.var,groups) + colnames(mat) = c('Periods','Returns','groups') + mat = data.frame(mat) + h2a = hPlot(x = "Periods", y = "Returns",group='groups', data = mat, + type = "line",showInLegend = FALSE,title=main) + + h2a$legend(FALSE) + h2a +} + + #TODO Going Up/Going Down maybe better implemented as slope/diff() indicator, then coupled with threshold signal #TODO set/reset indicator/signal for n-periods since some other signal is set, or signal set for n periods Modified: pkg/quantstrat/demo/00Index =================================================================== --- pkg/quantstrat/demo/00Index 2014-12-26 20:13:24 UTC (rev 1662) +++ pkg/quantstrat/demo/00Index 2014-12-31 13:19:05 UTC (rev 1663) @@ -26,3 +26,5 @@ luxor.sample.MFE.takeprofit.R Jaekle & Tomasini; sample MFE take profit graph luxor.sample.tradeGraphs.sma.R Jaekle & Tomasini; sample 3D SMA graph luxor.sample.tradeGraphs.timespan.R Jaekle & Tomasini; sample 3D timespan graph +signal.SMA.R SMA Cross Strategy with Signal Analysis Example; See maCross.R +signal.RSI.R RSI Cross Strategy with Signal Analysis Example; See rsi.R \ No newline at end of file Modified: pkg/quantstrat/man/ruleOrderProc.Rd =================================================================== --- pkg/quantstrat/man/ruleOrderProc.Rd 2014-12-26 20:13:24 UTC (rev 1662) +++ pkg/quantstrat/man/ruleOrderProc.Rd 2014-12-31 13:19:05 UTC (rev 1663) @@ -5,9 +5,6 @@ \usage{ ruleOrderProc(portfolio, symbol, mktdata, timestamp = NULL, ordertype = NULL, ..., slippageFUN = NULL) - -ruleOrderProc(portfolio, symbol, mktdata, timestamp = NULL, - ordertype = NULL, ..., slippageFUN = NULL) } \arguments{ \item{portfolio}{text name of the portfolio to associate the order book with} @@ -23,31 +20,12 @@ \item{...}{any other passthru parameters} \item{slippageFUN}{default NULL, not yet implemented} - -\item{portfolio}{text name of the portfolio to associate the order book with} - -\item{symbol}{identfier of the instrument to find orders for. The name of any associated price objects (xts prices, usually OHLC or BBO) should match these} - -\item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} - -\item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be processed on} - -\item{ordertype}{one of NULL, "market","limit","stoplimit", or "stoptrailing" default NULL} - -\item{...}{any other passthru parameters} - -\item{slippageFUN}{default NULL, not yet implemented} } \description{ The ruleOrderProc function is effectively the default fill simulator for quantstrat. This function is meant to be sufficient for backtesting most strategies, but would need to be replaced for production use. It provides the interface for taking the order book and determining when orders become trades. - -The ruleOrderProc function is effectively the default fill simulator for quantstrat. -This function is meant to be sufficient for backtesting most strategies, -but would need to be replaced for production use. It provides the interface -for taking the order book and determining when orders become trades. } \details{ In this version, in contrast with an earlier version, @@ -71,28 +49,6 @@ We would like to model slippage here via \code{slippageFUN}. Code contributions, suggestions, and requests appreciated. - -In this version, in contrast with an earlier version, -this function will allow a transaction to cross your current -position through zero. The accounting rules for realizing gains in such cases -are quite complicated, so blotter will split this transaction into two transactions. -Many brokers will break, revise, or split such transactions for the same reason. - -This function would need to be revised or replaced for connection to a live trading infrastructure. -In a production mode, you would replace the \code{\link{addOrder}} function -with a custom function to connect to your market infrastructure. -In that case, you might need to add additional code to your strategy, -or overload functions for checking position. - -Note that this function is called by default in the 'orders' slot of the -\code{\link{applyRules}} processing. If you have defined another order -processing rule, it will \emph{replace} this function. If you want your -custom order rule and ruleOrderProc to both be called, you will need -explicitly add a rule to call ruleOrderProc either before or after your -custom order processing function. - -We would like to model slippage here via \code{slippageFUN}. Code contributions, suggestions, -and requests appreciated. } \seealso{ add.rule @@ -104,16 +60,6 @@ addOrder updateOrders - -add.rule - -applyRules - -getOrderBook - -addOrder - -updateOrders } \concept{ fill simulator @@ -127,17 +73,5 @@ This function is meant to be sufficient for backtesting many/most strategies, but would need to be replaced for production use. It provides the interface for taking the order book and determining when orders become trades. - -fill simulator - -orders - -backtest - -fills - -This function is meant to be sufficient for backtesting many/most strategies, -but would need to be replaced for production use. It provides the interface -for taking the order book and determining when orders become trades. } From noreply at r-forge.r-project.org Wed Dec 31 15:38:01 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Wed, 31 Dec 2014 15:38:01 +0100 (CET) Subject: [Blotter-commits] r1664 - in pkg/quantstrat: . man Message-ID: <20141231143801.DD76C18779C@r-forge.r-project.org> Author: braverock Date: 2014-12-31 15:38:01 +0100 (Wed, 31 Dec 2014) New Revision: 1664 Added: pkg/quantstrat/man/apply.paramset.signal.analysis.Rd pkg/quantstrat/man/applyIndicatorSignals.Rd pkg/quantstrat/man/applyStrategy.rebalancing.training.Rd pkg/quantstrat/man/beanplot.signals.Rd pkg/quantstrat/man/distributional.boxplot.Rd pkg/quantstrat/man/initSymbol.Rd pkg/quantstrat/man/plot.signal.path.Rd pkg/quantstrat/man/plot.signals.Rd pkg/quantstrat/man/post.signal.returns.Rd pkg/quantstrat/man/signal.generate.statistics.Rd pkg/quantstrat/man/signal.obj.slope.Rd Modified: pkg/quantstrat/DESCRIPTION pkg/quantstrat/man/ruleOrderProc.Rd Log: - update roxygen docs to include new signal generation functions Modified: pkg/quantstrat/DESCRIPTION =================================================================== --- pkg/quantstrat/DESCRIPTION 2014-12-31 13:19:05 UTC (rev 1663) +++ pkg/quantstrat/DESCRIPTION 2014-12-31 14:38:01 UTC (rev 1664) @@ -1,7 +1,7 @@ Package: quantstrat Type: Package Title: Quantitative Strategy Model Framework -Version: 0.9.1663 +Version: 0.9.1664 Date: $Date$ Author: Peter Carl, Brian G. Peterson, Joshua Ulrich, Jan Humme Depends: Added: pkg/quantstrat/man/apply.paramset.signal.analysis.Rd =================================================================== --- pkg/quantstrat/man/apply.paramset.signal.analysis.Rd (rev 0) +++ pkg/quantstrat/man/apply.paramset.signal.analysis.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,73 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{apply.paramset.signal.analysis} +\alias{apply.paramset.signal.analysis} +\title{Signal Analysis With Parmeter Optimization} +\usage{ +apply.paramset.signal.analysis(strategy.st, paramset.label, portfolio.st, + sigcol, sigval, on, forward.days, cum.sum = TRUE, include.day.of.signal, + obj.fun, decreasing, mktdata = NULL, verbose = TRUE) +} +\arguments{ +\item{strategy.st}{an object of type 'strategy' to add the indicator to} + +\item{paramset.label}{a label uniquely identifying the paramset within the strategy} + +\item{portfolio.st}{text name of the portfolio to associate the order book with} + +\item{sigcol}{column name to check for signal} + +\item{sigval}{signal value to match against} + +\item{on}{the periods endpoints to find as a character string} + +\item{forward.days}{days to exit post signal} + +\item{cum.sum}{whether to use cumsum on price changes} + +\item{include.day.of.signal}{whether to include the day of signal generation} + +\item{obj.fun}{objective function for determining goodness of each paramset} + +\item{decreasing}{how to sort the obj.fun output values} + +\item{mktdata}{market data} + +\item{verbose}{whether to output processing messages} +} +\value{ +A list of objects that contains the results +\describe{ + \item{signals}{List of signals named by parameter combination. Each object within the list is a XTS object with columns being assets and rows being signals.} + \item{sigret.by.paramset}{List of list. Sorted by parameter combination and then by asset. Contains matrix of next day returns; columns are period (N day look ahead) and rows are signals} + \item{sigret.by.asset}{List of list. Sorted by Asset and then by parameter combinations. Contains same matrix as sigret.by.paramset} + \item{signal.stats}{List of signal statistics as calculated via custom user defined fitness function. Sorted by assets.} +} +} +\description{ +This function allows user to analyze signals independently from rules. +} +\details{ +This function is similar to \code{applyParameter} but includes additionally \code{applySignal} wrapped within it. To use it, the user +will need to initially define the distribution and constraints by using \code{add.distribution} and \code{add.distribution.constraint}. + +More generally, the function is designed to generate signals across various parameter combinations defined within the distribution and +constraints. Afterwards it extract the next N day price changes for further anlaysis. + +The parameter \code{on} allows user to calculate post signal returns in different frequencies. Different signals have different timeframes effectiveness. +\code{forward.days} lets the user select the number of post signal days to analyze results. + +To determine the goodness of a parameter set relative to all others, we let the user specify their own objective function (via parameter \code{obj.func}) +that will be used to calculate an objective value representing each parameter. These will then be sorted from best to worst. The +objective function will take in a single matrix \code{ret.mat} of price changes. Each row represents an individual signal +while each column represents periods/post signal. + +See demo 'signalAnalysisExample1.R' & 'signalAnalysisExample2.R' +} +\author{ +Michael Guan +} +\seealso{ +\code{\link{add.distribution}} +\code{\link{add.distribution.constraint}} +} + Added: pkg/quantstrat/man/applyIndicatorSignals.Rd =================================================================== --- pkg/quantstrat/man/applyIndicatorSignals.Rd (rev 0) +++ pkg/quantstrat/man/applyIndicatorSignals.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,31 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{applyIndicatorSignals} +\alias{applyIndicatorSignals} +\title{Calculate Indicators and Signals for a Strategy} +\usage{ +applyIndicatorSignals(strategy, portfolio, mktdata, sigcol, ...) +} +\arguments{ +\item{strategy}{an object (or the name of an object) type 'strategy' to add the indicator to} + +\item{portfolio}{text name of the portfolio to associate the order book with} + +\item{mktdata}{market data} + +\item{sigcol}{String name of signal to use for analysis} +} +\value{ +\code{xts} object with columns representing signals for each symbol +} +\description{ +Calculate signals given indicators and signal definitions. +} +\author{ +Michael Guan +} +\seealso{ +\code{\link{apply.paramset.signal.analysis}} +\code{\link{applyIndicators}} +\code{\link{applySignals}} +} + Added: pkg/quantstrat/man/applyStrategy.rebalancing.training.Rd =================================================================== --- pkg/quantstrat/man/applyStrategy.rebalancing.training.Rd (rev 0) +++ pkg/quantstrat/man/applyStrategy.rebalancing.training.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,39 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{applyStrategy.rebalancing.training} +\alias{applyStrategy.rebalancing.training} +\title{apply the strategy to arbitrary market data, with periodic rebalancing} +\usage{ +applyStrategy.rebalancing.training(strategy, portfolios, mktdata = NULL, + parameters = NULL, ..., verbose = TRUE, symbols = NULL, + initStrat = FALSE, updateStrat = FALSE, training = 3) +} +\arguments{ +\item{strategy}{an object of type 'strategy' or the name of a stored strategy to apply} + +\item{portfolios}{a list of portfolios to apply the strategy to} + +\item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} + +\item{parameters}{named list of parameters to be applied during evaluation of the strategy, default NULL} + +\item{...}{any other passthru parameters} + +\item{verbose}{if TRUE, return output list} + +\item{symbols}{character vector identifying symbols to initialize a portfolio for, default NULL} + +\item{initStrat}{whether to use (experimental) initialization code, default FALSE} + +\item{updateStrat}{whether to use (experimental) wrapup code, default FALSE} + +\item{training}{minimum number of periods before we should try to apply rebalance rules} +} +\description{ +This function is the wrapper that holds together the execution of a strategy with rebalancing rules. +} +\seealso{ +\code{\link{strategy}}, \code{\link{applyIndicators}}, + \code{\link{applySignals}}, \code{\link{applyRules}}, + \code{\link{initStrategy}}, \code{\link{applyStrategy}} +} + Added: pkg/quantstrat/man/beanplot.signals.Rd =================================================================== --- pkg/quantstrat/man/beanplot.signals.Rd (rev 0) +++ pkg/quantstrat/man/beanplot.signals.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,45 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{beanplot.signals} +\alias{beanplot.signals} +\title{Visualization of Signal Across Lookback with Beanplots} +\usage{ +beanplot.signals(signals, rows = NULL, columns = NULL, mai = c(0.1, 0.4, + 0.2, 0.1), mgp = c(1, 1, 0), xlab = "", ylab = "", cex.main = 0.6, + xaxt = "n", cex.axis = 0.5, h = 0, hlinecol = "red", ...) +} +\arguments{ +\item{rows}{number of rows for plot} + +\item{columns}{number of columns for plot} + +\item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} + +\item{mgp}{The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0).} + +\item{xlab}{a title for the x axis} + +\item{ylab}{a title for the y axis} + +\item{cex.main}{The magnification to be used for main titles relative to the current setting of cex.} + +\item{xaxt}{A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting.} + +\item{cex.axis}{The magnification to be used for axis annotation relative to the current setting of cex.} + +\item{h}{the y-value(s) for horizontal line(s).} + +\item{hlinecol}{A specification for the default plotting color. See section ?Color Specification?.} + +\item{signal}{list of paramset forward looking price changes by asset} +} +\value{ +plot +} +\description{ +This function is similar to \code{plot.signals} but uses beanplots +instead of barplots. Requires 'beanplot' package +} +\author{ +Michael Guan +} + Added: pkg/quantstrat/man/distributional.boxplot.Rd =================================================================== --- pkg/quantstrat/man/distributional.boxplot.Rd (rev 0) +++ pkg/quantstrat/man/distributional.boxplot.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,33 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{distributional.boxplot} +\alias{distributional.boxplot} +\title{Visualization of Single Signal} +\usage{ +distributional.boxplot(signal, x.val = seq(1, 50, 5), val = 10, + ylim = c(-5, 5), xlim = c(0, 50), mai = c(1, 1, 0.3, 0.5), h = 0, ...) +} +\arguments{ +\item{signal}{list of paramset forward looking price changes by asset} + +\item{x.val}{he values of the explanatory variable where we want to see the distribution} + +\item{val}{this parameter determines how the plotted distribution is shown, increase/decrease it if the distribution is not shown properly} + +\item{ylim}{the y limits in the plot} + +\item{xlim}{the x limits in the plot} + +\item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} + +\item{h}{the y-value(s) for horizontal line(s).} +} +\value{ +plot +} +\description{ +This function employs \code(plotSimpleGamlss) in package \code(gamlss.util). +} +\author{ +Michael Guan +} + Added: pkg/quantstrat/man/initSymbol.Rd =================================================================== --- pkg/quantstrat/man/initSymbol.Rd (rev 0) +++ pkg/quantstrat/man/initSymbol.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,28 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{initSymbol} +\alias{initSymbol} +\title{Run standard and custom symbol initialization functions} +\usage{ +initSymbol(strategy, symbol, ...) +} +\arguments{ +\item{strategy}{an object (or the name of an object) of type 'strategy' to add the init function definition to} + +\item{symbol}{symbol} + +\item{...}{} +} +\description{ +\code{initSymbol} will load a symbol and run user-defined functions to pre-process the symbol's data +before constructing indicators. +} +\details{ +The custom initialization must be defined as named list containing +\describe{ + \item{name}{function name} + \item{argument}{list of arguments} + \item{enabled}{TRUE or FALSE} +} +and included as the slot \code{init_symbol} of the strategy object. +} + Added: pkg/quantstrat/man/plot.signal.path.Rd =================================================================== --- pkg/quantstrat/man/plot.signal.path.Rd (rev 0) +++ pkg/quantstrat/man/plot.signal.path.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,28 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{plot.signal.path} +\alias{plot.signal.path} +\title{Visualization of Signal Path} +\usage{ +\method{plot}{signal.path}(data, main = "Cumulative Return Paths") +} +\arguments{ +\item{data}{signal data} + +\item{main}{plot title} +} +\value{ +plot +} +\description{ +This function creates a rChart - hplot that is interactive. It displays +} +\examples{ +\dontrun{ +# signalAnalysisExample1.R +plot.signal.path(results$sigret.by.asset$RTH$paramset.1.5[1:10,]) +} +} +\author{ +Michael Guan +} + Added: pkg/quantstrat/man/plot.signals.Rd =================================================================== --- pkg/quantstrat/man/plot.signals.Rd (rev 0) +++ pkg/quantstrat/man/plot.signals.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,48 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{plot.signals} +\alias{plot.signals} +\title{Visualization of Signal Across Lookback} +\usage{ +\method{plot}{signals}(signals, rows = NULL, columns = NULL, mai = c(0.1, + 0.4, 0.2, 0.1), mgp = c(1, 1, 0), xlab = "", ylab = "", + cex.main = 0.6, xaxt = "n", cex.axis = 0.5, h = 0, hlinecol = "red", + ...) +} +\arguments{ +\item{rows}{number of rows for plot} + +\item{columns}{number of columns for plot} + +\item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} + +\item{mgp}{The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0).} + +\item{xlab}{a title for the x axis} + +\item{ylab}{a title for the y axis} + +\item{cex.main}{The magnification to be used for main titles relative to the current setting of cex.} + +\item{xaxt}{A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting.} + +\item{cex.axis}{The magnification to be used for axis annotation relative to the current setting of cex.} + +\item{h}{the y-value(s) for horizontal line(s).} + +\item{hlinecol}{A specification for the default plotting color. See section ?Color Specification?.} + +\item{signal}{list of paramset forward looking price changes by asset} +} +\value{ +plot +} +\description{ +This function takes a list of matrix of post signal price changes and +plots boxplots. Note function plots whatever is given to it therefore when +there are lots paramsets, it is best to plot a smaller portion so the +information can be displayed clearly. +} +\author{ +Michael Guan +} + Added: pkg/quantstrat/man/post.signal.returns.Rd =================================================================== --- pkg/quantstrat/man/post.signal.returns.Rd (rev 0) +++ pkg/quantstrat/man/post.signal.returns.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,36 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{post.signal.returns} +\alias{post.signal.returns} +\title{Generate Post Signal Returns} +\usage{ +post.signal.returns(signals, sigval, on = NULL, forward.days, + cum.sum = TRUE, include.day.of.signal = FALSE, mktdata = NULL) +} +\arguments{ +\item{signals}{xts object with signals, one column} + +\item{on}{the periods endpoints to find as a character string} + +\item{forward.days}{number of days to look forward after signal (days to exit post signal)} + +\item{cum.sum}{\code{TRUE},\code{FALSE}; cumulative sum of price changes} + +\item{include.day.of.signal}{whether to analyze the return on signal day} + +\item{mktdata}{market data} + +\item{sigvals}{signal value to match against} +} +\value{ +\code{matrix} of post signal price changes; rows = nth signal, column = nth period since signal +} +\description{ +This function collects and aggregates post signal price changes for N days forward. +} +\author{ +Michael Guan +} +\seealso{ +\code{\link{apply.paramset.signal.analysis}} +} + Modified: pkg/quantstrat/man/ruleOrderProc.Rd =================================================================== --- pkg/quantstrat/man/ruleOrderProc.Rd 2014-12-31 13:19:05 UTC (rev 1663) +++ pkg/quantstrat/man/ruleOrderProc.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -5,6 +5,9 @@ \usage{ ruleOrderProc(portfolio, symbol, mktdata, timestamp = NULL, ordertype = NULL, ..., slippageFUN = NULL) + +ruleOrderProc(portfolio, symbol, mktdata, timestamp = NULL, + ordertype = NULL, ..., slippageFUN = NULL) } \arguments{ \item{portfolio}{text name of the portfolio to associate the order book with} @@ -20,12 +23,31 @@ \item{...}{any other passthru parameters} \item{slippageFUN}{default NULL, not yet implemented} + +\item{portfolio}{text name of the portfolio to associate the order book with} + +\item{symbol}{identfier of the instrument to find orders for. The name of any associated price objects (xts prices, usually OHLC or BBO) should match these} + +\item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} + +\item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be processed on} + +\item{ordertype}{one of NULL, "market","limit","stoplimit", or "stoptrailing" default NULL} + +\item{...}{any other passthru parameters} + +\item{slippageFUN}{default NULL, not yet implemented} } \description{ The ruleOrderProc function is effectively the default fill simulator for quantstrat. This function is meant to be sufficient for backtesting most strategies, but would need to be replaced for production use. It provides the interface for taking the order book and determining when orders become trades. + +The ruleOrderProc function is effectively the default fill simulator for quantstrat. +This function is meant to be sufficient for backtesting most strategies, +but would need to be replaced for production use. It provides the interface +for taking the order book and determining when orders become trades. } \details{ In this version, in contrast with an earlier version, @@ -49,6 +71,28 @@ We would like to model slippage here via \code{slippageFUN}. Code contributions, suggestions, and requests appreciated. + +In this version, in contrast with an earlier version, +this function will allow a transaction to cross your current +position through zero. The accounting rules for realizing gains in such cases +are quite complicated, so blotter will split this transaction into two transactions. +Many brokers will break, revise, or split such transactions for the same reason. + +This function would need to be revised or replaced for connection to a live trading infrastructure. +In a production mode, you would replace the \code{\link{addOrder}} function +with a custom function to connect to your market infrastructure. +In that case, you might need to add additional code to your strategy, +or overload functions for checking position. + +Note that this function is called by default in the 'orders' slot of the +\code{\link{applyRules}} processing. If you have defined another order +processing rule, it will \emph{replace} this function. If you want your +custom order rule and ruleOrderProc to both be called, you will need +explicitly add a rule to call ruleOrderProc either before or after your +custom order processing function. + +We would like to model slippage here via \code{slippageFUN}. Code contributions, suggestions, +and requests appreciated. } \seealso{ add.rule @@ -60,6 +104,16 @@ addOrder updateOrders + +add.rule + +applyRules + +getOrderBook + +addOrder + +updateOrders } \concept{ fill simulator @@ -73,5 +127,17 @@ This function is meant to be sufficient for backtesting many/most strategies, but would need to be replaced for production use. It provides the interface for taking the order book and determining when orders become trades. + +fill simulator + +orders + +backtest + +fills + +This function is meant to be sufficient for backtesting many/most strategies, +but would need to be replaced for production use. It provides the interface +for taking the order book and determining when orders become trades. } Added: pkg/quantstrat/man/signal.generate.statistics.Rd =================================================================== --- pkg/quantstrat/man/signal.generate.statistics.Rd (rev 0) +++ pkg/quantstrat/man/signal.generate.statistics.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,28 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{signal.generate.statistics} +\alias{signal.generate.statistics} +\title{Signal Objective Function Calculation} +\usage{ +signal.generate.statistics(post.ret, obj.fun = NULL, decreasing = TRUE) +} +\arguments{ +\item{post.ret}{\code{matrix} of parameter set of post signal price deltas} + +\item{obj.fun}{custom objective function for measuring signal goodness} + +\item{decreasing}{if true, the higher the objective value, the better} +} +\value{ +objective function values +} +\description{ +This function takes a list of matrix of post signal price changes and +applies an user defined objective function on it. +} +\author{ +Michael Guan +} +\seealso{ +\code{\link{apply.paramset.signal.analysis}} +} + Added: pkg/quantstrat/man/signal.obj.slope.Rd =================================================================== --- pkg/quantstrat/man/signal.obj.slope.Rd (rev 0) +++ pkg/quantstrat/man/signal.obj.slope.Rd 2014-12-31 14:38:01 UTC (rev 1664) @@ -0,0 +1,30 @@ +% Generated by roxygen2 (4.0.2): do not edit by hand +\name{signal.obj.slope} +\alias{signal.obj.slope} +\title{Signal Objective Function} +\usage{ +signal.obj.slope(x) +} +\arguments{ +\item{x}{Return matrix, each row represents price deltas for a single signal, each column represents periods} +} +\value{ +Single Objective Value +} +\description{ +Simple example of objective function that can can be used to measure the effectiveness of various parameter combinations. +} +\details{ +Calculates the slope of the Cumulative Equity line. Higher the better. + +It is important to note that all objective functions are called within \code{signal.generate.statistics}. What gets +passed in to it as parameter is an matrix of post signal price changes or cumulative equity for each signal. The matrix +is of N-by-M dimensions. N being the row representing the Nth signal. M being the column representing Mth period. +} +\author{ +Michael Guan +} +\seealso{ +\code{\link{apply.paramset.signal.analysis}} +} +