[Blotter-commits] r232 - in pkg/quantstrat: R man
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sat Feb 6 15:13:23 CET 2010
Author: braverock
Date: 2010-02-06 15:13:22 +0100 (Sat, 06 Feb 2010)
New Revision: 232
Added:
pkg/quantstrat/R/rules.R
pkg/quantstrat/man/applyRules.Rd
Modified:
pkg/quantstrat/R/indicators.R
pkg/quantstrat/R/signals.R
pkg/quantstrat/man/applySignals.Rd
Log:
- applyRules template function
- more documentation
- minor bugfixes
Modified: pkg/quantstrat/R/indicators.R
===================================================================
--- pkg/quantstrat/R/indicators.R 2010-02-06 12:11:21 UTC (rev 231)
+++ pkg/quantstrat/R/indicators.R 2010-02-06 14:13:22 UTC (rev 232)
@@ -95,7 +95,7 @@
#print(tmp_val)
} #end indicators loop
if(is.null(ret)) return(mktdata)
- else return(list(mktdata=mktdata,indicator_ret=ret))
+ else return(ret)
}
Copied: pkg/quantstrat/R/rules.R (from rev 231, pkg/quantstrat/R/traderules.R)
===================================================================
--- pkg/quantstrat/R/rules.R (rev 0)
+++ pkg/quantstrat/R/rules.R 2010-02-06 14:13:22 UTC (rev 232)
@@ -0,0 +1,181 @@
+#' add a rule to a strategy
+#'
+#' Rules will be processed in a very particular manner, so it bears going over.
+#'
+#' First, rules are either path dependent or non-path-dependent. Path dependent rules
+#' will be processed in every time increment for the \code{mktdata} passed into
+#' \code{\link{applyStrategy}}. Non path dependent rules will likely be quite rare in real life,
+#' and will be applied after indicators and signals, and before path-dependent rules are processed.
+#'
+#' All rules have a \code{type}. These may be any of:
+#' \itemize{
+#' \item{risk}{ rules that check and react to risk of positions, may stop all other rule execution temporarily or permanently}
+#' \item{order}{ rules for order processing of any open orders at time t, always path-dependent}
+#' \item{rebalance}{ rules executed specifically in a portfolio context, unnecessary in univariate strategies}
+#' \item{exit}{ rules to determine whether to exit a position}
+#' \item{enter}{ rules to determine whether to enter or increase a position}
+#' }
+#' The rules will be executed by type, in the order listed above.
+#' Multiple rules of each type may be defined, as with signals and indicators,
+#' they will be executed in order by index number with any other rules sharing the same
+#' type.
+#'
+#' The rule execution order was constructed because path-dependent rules may modify
+#' the ability of rules that have not fired yet to be evaluated. For example, a
+#' risk rule may flatten (close out) an entire position and put new orders
+#' on hold, effectively stopping all further execution of the strategy.
+#' Another example would be a rebalancing rule function that would enter
+#' orders to rebalance the portfolio, and would hold other strategy processing
+#' until the rebalancing period was over.
+#'
+#' We anticipate that rules will be the portion of a strategy most likely to
+#' not have suitable template code included with this package, as every strategy
+#' and environment are different, especially in this respect.
+#' We will attempt to provide enough examples and generic rules to give strategy
+#' authors a place to start.
+#'
+#' @param strategy an object of type 'strategy' to add the rule to
+#' @param name name of the rule, must correspond to an R function
+#' @param arguments default arguments to be passed to an rule function when executed
+#' @param label arbitrary text label for signal output, NULL default will be converted to '<name>.sig'
+#' @param type one of "risk","order","rebalance","exit","entry", see Details
+#' @param ... any other passthru parameters
+#' @param enabled TRUE/FALSE whether the rule is enabled for use in applying the strategy, default TRUE
+#' @param indexnum if you are updating a specific rule, the index number in the $rules[type] list to update
+#' @param path.dep TRUE/FALSE whether rule is path dependent, default TRUE, see Details
+#' @param store TRUE/FALSE whether to store the strategy in the .strategy environment, or return it. default FALSE
+#' @export
+add.rule <- function(strategy, name, arguments, label=NULL, type=c(NULL,"risk","order","rebalance","exit","entry"), ..., enabled=TRUE, indexnum=NULL, path.dep=TRUE, store=FALSE) {
+ if(!is.strategy(strategy)) stop("You must pass in a strategy object to manipulate")
+ type=type[1]
+ if(is.null(type)) stop("You must specify a type")
+ tmp_rule<-list()
+ tmp_rule$name<-name
+ tmp_rule$type<-type
+ # TODO change this to a separate slot!!!!!
+ tmp_rule$enabled<-enabled
+ if (!is.list(arguments)) stop("arguments must be passed as a named list")
+ arguments$label=label
+ tmp_rule$arguments<-arguments
+ if(!hasArg(indexnum) | (hasArg(indexnum) & is.null(indexnum))) indexnum = length(strategy$rules[type])+1
+ tmp_rule$call<-match.call()
+ strategy$rules[type][[indexnum]]<-tmp_rule
+
+ if (store) assign(strategy$name,strategy,envir=as.environment(.strategy))
+ else return(strategy)
+}
+
+#' apply the rules in the strategy to arbitrary market data
+#'
+#' In typical usage, this function will be called via \code{\link{applyStrategy}}. In this mode, this function will be called twice, once with \code{path.dep=FALSE} and then again in stepping over the .
+#' @param strategy an object of type 'strategy' to add the rule to
+#' @param mktdata an xts object containing market data. depending on rules, may need to be in OHLCV or BBO formats, and may include indicator and signal information
+#' @param indicators if indicator output is not contained in the mktdata object, it may be passed separately as an xts object or a list.
+#' @param signals if signal output is not contained in the mktdata object, it may be passed separately as an xts object or a list.
+#' @param ... any other passthru parameters
+#' @param path.dep TRUE/FALSE whether rule is path dependent, default TRUE, see Details
+#' @seealso \code{\link{add.rule}} \code{\link{applyStrategy}}
+#' @export
+applyRules <- function(strategy, mktdata, indicators=NULL, signals=NULL, ..., path.dep=TRUE) {
+ #TODO add Date subsetting
+
+ # TODO check for symbol name in mktdata using Josh's code:
+ # symbol <- strsplit(colnames(mktdata)[1],"\\.")[[1]][1]
+
+ # TODO handle indicator and signal lists as well as indicators/signals that were cbound to mktdata
+
+ if (!is.strategy(strategy)) {
+ strategy<-try(getStrategy(strategy))
+ if(inherits(strategy,"try-error"))
+ stop ("You must supply an object of type 'strategy'.")
+ }
+ ret <- NULL
+ nargs <-list(...)
+ if(length(nargs)==0) nargs=NULL
+ if (length('...')==0 | is.null('...')) {
+ rm('...')
+ nargs=NULL
+ }
+
+ ruleProc <- function (ruletypelist){
+ for (rule in ruletypelist){
+ #TODO check to see if they've already been calculated
+
+ if(!is.function(get(rule$name))){
+ if(!is.function(get(paste("sig",rule$name,sep='.')))){
+ message(paste("Skipping rule",rule$name,"because there is no function by that name to call"))
+ next()
+ } else {
+ rule$name<-paste("sig",rule$name,sep='.')
+ }
+ }
+
+ if(!isTRUE(rule$enabled)) next()
+
+ # see 'S Programming p. 67 for this matching
+ fun<-match.fun(rule$name)
+
+ .formals <- formals(fun)
+ onames <- names(.formals)
+
+ pm <- pmatch(names(rule$arguments), onames, nomatch = 0L)
+ if (any(pm == 0L))
+ warning(paste("some arguments stored for",rule$name,"do not match"))
+ names(rule$arguments[pm > 0L]) <- onames[pm]
+ .formals[pm] <- rule$arguments[pm > 0L]
+ #now add dots
+ if (length(nargs)) {
+ pm <- pmatch(names(nargs), onames, nomatch = 0L)
+ names(nargs[pm > 0L]) <- onames[pm]
+ .formals[pm] <- nargs[pm > 0L]
+ }
+ .formals$... <- NULL
+
+ tmp_val<-do.call(fun,.formals)
+ if(is.null(names(tmp_val)) & ncol(tmp_val)==1) names(tmp_val)<-rule$label
+ if (nrow(mktdata)==nrow(tmp_val) | length(mktdata)==length(tmp_val)) {
+ # the rule returned a time series, so we'll name it and cbind it
+ mktdata<-cbind(mktdata,tmp_val)
+ } else {
+ # the rule returned something else, add it to the ret list
+ if(is.null(ret)) ret<-list()
+ ret[[rule$name]]<-tmp_val
+ }
+ #print(tmp_val)
+ } #end rules loop
+ mktdata <<- mktdata
+ ret <<- ret
+ hold <<- hold
+ } # end sub process function
+
+ hold=FALSE
+ for ( type in names(strategy$rules)){
+ switch( names(strategy$rules),
+ risk = {
+
+ },
+ order = {
+
+ }
+
+ ) # send switch
+
+ }
+
+ if(is.null(ret)) return(mktdata)
+ else return(ret)
+}
+
+
+###############################################################################
+# R (http://r-project.org/) Quantitative Strategy Model Framework
+#
+# Copyright (c) 2009-2010
+# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich
+#
+# This library is distributed under the terms of the GNU Public License (GPL)
+# for full details see the file COPYING
+#
+# $Id$
+#
+###############################################################################
Modified: pkg/quantstrat/R/signals.R
===================================================================
--- pkg/quantstrat/R/signals.R 2010-02-06 12:11:21 UTC (rev 231)
+++ pkg/quantstrat/R/signals.R 2010-02-06 14:13:22 UTC (rev 232)
@@ -30,7 +30,7 @@
#' apply the signals in the strategy to arbitrary market data
#' @param strategy an object of type 'strategy' to add the signal to
#' @param mktdata an xts object containing market data. depending on signals, may need to be in OHLCV or BBO formats
-#' @param indicators if indicator output is not contained in the mktdata object, it may be passed separately an xts object or a list.
+#' @param indicators if indicator output is not contained in the mktdata object, it may be passed separately as an xts object or a list.
#' @param ... any other passthru parameters
#' @export
applySignals <- function(strategy, mktdata, indicators=NULL, ...) {
@@ -39,6 +39,8 @@
# TODO check for symbol name in mktdata using Josh's code:
# symbol <- strsplit(colnames(mktdata)[1],"\\.")[[1]][1]
+ # TODO handle indicator lists as well as indicators that were cbound to mktdata
+
if (!is.strategy(strategy)) {
strategy<-try(getStrategy(strategy))
if(inherits(strategy,"try-error"))
@@ -98,7 +100,7 @@
#print(tmp_val)
} #end signals loop
if(is.null(ret)) return(mktdata)
- else return(list(mktdata=mktdata,signal_ret=ret))
+ else return(ret)
}
@@ -174,7 +176,7 @@
#' @export
sigPeak <- function(label,data,column, direction=c("peak","bottom")){
#should we only do this for one column?
- column<-match.names(colnames(data),columns)
+ column<-match.names(colnames(data),column)
direction=direction[1] # only use the first]
#(Lag(IBM[,4],2)<Lag(IBM[,4],1)) & Lag(IBM[,4],1) >IBM[,4]
switch(direction,
@@ -206,13 +208,13 @@
'gt' = {ret_sig = data[,column] > threshold},
'<' =,
'lt' = {ret_sig = data[,column] < threshold},
- 'eq' = {ret_sig = data[,columns[1]] == threshold}, #FIXME any way to specify '='?
+ 'eq' = {ret_sig = data[,column] == threshold}, #FIXME any way to specify '='?
'gte' =,
'gteq'=,
- 'ge' = {ret_sig = data[,columns[1]] >= threshold}, #FIXME these fail with an 'unexpected =' error if you use '>='
+ 'ge' = {ret_sig = data[,column] >= threshold}, #FIXME these fail with an 'unexpected =' error if you use '>='
'lte' =,
'lteq'=,
- 'le' = {ret_sig = data[,columns[1]] <= threshold}
+ 'le' = {ret_sig = data[,column] <= threshold}
)
colnames(ret_sig)<-label
return(ret_sig)
Added: pkg/quantstrat/man/applyRules.Rd
===================================================================
--- pkg/quantstrat/man/applyRules.Rd (rev 0)
+++ pkg/quantstrat/man/applyRules.Rd 2010-02-06 14:13:22 UTC (rev 232)
@@ -0,0 +1,13 @@
+\name{applyRules}
+\alias{applyRules}
+\title{apply the rules in the strategy to arbitrary market data...}
+\usage{applyRules(strategy, mktdata, indicators, signals, ..., path.dep=TRUE)}
+\description{apply the rules in the strategy to arbitrary market data}
+\details{In typical usage, this function will be called via \code{\link{applyStrategy}}. In this mode, this function will be called twice, once with \code{path.dep=FALSE} and then again in stepping over the .}
+\seealso{\code{\link{add.rule}} \code{\link{applyStrategy}}}
+\arguments{\item{strategy}{an object of type 'strategy' to add the rule to}
+\item{mktdata}{an xts object containing market data. depending on rules, may need to be in OHLCV or BBO formats, and may include indicator and signal information}
+\item{indicators}{if indicator output is not contained in the mktdata object, it may be passed separately as an xts object or a list.}
+\item{signals}{if signal output is not contained in the mktdata object, it may be passed separately as an xts object or a list.}
+\item{...}{any other passthru parameters}
+\item{path.dep}{TRUE/FALSE whether rule is path dependent, default TRUE, see Details}}
Property changes on: pkg/quantstrat/man/applyRules.Rd
___________________________________________________________________
Name: svn:keywords
+ Revision Id Date Author
Modified: pkg/quantstrat/man/applySignals.Rd
===================================================================
--- pkg/quantstrat/man/applySignals.Rd 2010-02-06 12:11:21 UTC (rev 231)
+++ pkg/quantstrat/man/applySignals.Rd 2010-02-06 14:13:22 UTC (rev 232)
@@ -5,5 +5,5 @@
\description{apply the signals in the strategy to arbitrary market data}
\arguments{\item{strategy}{an object of type 'strategy' to add the signal to}
\item{mktdata}{an xts object containing market data. depending on signals, may need to be in OHLCV or BBO formats}
-\item{indicators}{if indicator output is not contained in the mktdata object, it may be passed separately an xts object or a list.}
+\item{indicators}{if indicator output is not contained in the mktdata object, it may be passed separately as an xts object or a list.}
\item{...}{any other passthru parameters}}
More information about the Blotter-commits
mailing list