[Blotter-commits] r987 - pkg/quantstrat/R

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Mar 25 21:14:04 CEST 2012


Author: braverock
Date: 2012-03-25 21:14:04 +0200 (Sun, 25 Mar 2012)
New Revision: 987

Removed:
   pkg/quantstrat/R/traderules.R
Log:
- remove traderules.R file, split into ruleSignal.R and osFUNs.R


Deleted: pkg/quantstrat/R/traderules.R
===================================================================
--- pkg/quantstrat/R/traderules.R	2012-03-25 19:04:37 UTC (rev 986)
+++ pkg/quantstrat/R/traderules.R	2012-03-25 19:14:04 UTC (rev 987)
@@ -1,371 +0,0 @@
-
-#' default rule to generate a trade order on a signal
-#' 
-#' \code{pricemethod} may be one of 
-#'      \describe{ 
-#'          \item{'market', 'opside', or 'active'}{ will use the 'ask' price if you're buying and 
-#'            the 'bid' price if you're selling, crossing the market at the time of 
-#'            order entry to attempt to set an aggressive price to get the trade. }
-#' 		   \item{'passive', 'work' or 'join'}{ which will join the 'bid' price if you are buying
-#'      	  or join the 'ask' price if you are selling, passively working to make liquidity 
-#'            at the prevailing market price without crossing the market at time of order entry}
-#' 		   \item{'maker'}{will create a pair of orders for both bid and offer, modeling 
-#' 		      market making activities by having orders on both sides.  
-#'            This will then create an Order.Set, and use the \code{threshold} to set the prices for these orders.}
-#'      } 
-#' 
-#' If \code{threshold} is not numeric or \code{NULL} it should be the character string describing a function that can calculate a threshold.  
-#' Ideally this will be a column lookup on a non-path-dependent indicator calculated in advance.
-#' 
-#' If \code{orderside} is NULL, the function will attempt to calculate the side from the current position 
-#' (if any), the order quantity, and the order type.    
-#'   
-#' @param data 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 timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 
-#' @param sigcol column name to check for signal
-#' @param sigval signal value to match against
-#' @param orderqty numeric quantity of the desired order, or 'all', modified by osFUN
-#' @param ordertype one of "market","limit","stoplimit", "stoptrailing", or "iceberg"
-#' @param orderside one of either "long" or "short", default NULL, see details 
-#' @param threshold numeric or function threshold to apply to trailing stop orders, default NULL, see Details
-#' @param tmult if TRUE, threshold is a percent multiplier for \code{price}, not a scalar to be added/subtracted from price.  threshold will be dynamically converted to a scalar at time of order entry
-#' @param replace TRUE/FALSE, whether to replace any other open order(s) on this portfolio symbol, default TRUE 
-#' @param delay what delay to add to timestamp when inserting the order into the order book, in seconds
-#' @param osFUN function or text descriptor of function to use for order sizing, default \code{\link{osNoOp}}
-#' @param pricemethod determines how the order price will be calculated, see Details
-#' @param portfolio text name of the portfolio to place orders in
-#' @param symbol identifier of the instrument to place orders for.  The name of any associated price objects (xts prices, usually OHLC) should match these
-#' @param ... any other passthru parameters
-#' @param ruletype one of "risk","order","rebalance","exit","entry", see \code{\link{add.rule}}
-#' @param TxnFees numeric fees (usually negative) or function name for calculating TxnFees (processing happens later, not in this function)
-#' @param prefer price method for getPrice
-#' @param sethold boolean, puts entry Rule processing on hold, default FALSE
-#' @param label rule label, default '', added by \code{\link{applyRules}}
-#' @seealso \code{\link{osNoOp}} , \code{\link{add.rule}}
-#' @export
-ruleSignal <- function(data=mktdata, timestamp, sigcol, sigval, orderqty=0, ordertype, orderside=NULL, threshold=NULL, tmult=FALSE, replace=TRUE, delay=0.0001, osFUN='osNoOp', pricemethod=c('market','opside','active'), portfolio, symbol, ..., ruletype, TxnFees=0, prefer=NULL, sethold=FALSE, label='')
-{
-
-    if(!is.function(osFUN)) osFUN<-match.fun(osFUN)
-    #print(paste(symbol,timestamp, sigval))
-    #print(data[timestamp][,sigcol])
-    #browser()
-    if (!is.na(timestamp) && !is.na(data[timestamp][,sigcol]) && data[timestamp][,sigcol] == sigval) {
-        #calculate order price using pricemethod
-        pricemethod<-pricemethod[1] #only use the first if not set by calling function
-
-		if(hasArg(prefer)) prefer=match.call(expand.dots=TRUE)$prefer
-		else prefer = NULL
-
-		#if(hasArg(TxnFees)) TxnFees=match.call(expand.dots=TRUE)$TxnFees
-		#else TxnFees=0
-
-		switch(pricemethod,
-                market = ,
-				opside = ,
-				active = {
-                    if(is.BBO(data)){
-                        if (orderqty>0) 
-                            prefer='ask'  # we're buying, so pay what they're asking
-                        else
-                            prefer='bid'  # we're selling, so give it to them for what they're bidding  
-                    } 
-					orderprice <- try(getPrice(x=data, prefer=prefer))[timestamp] 
-				},
-				passive =,
-				work =,
-				join = {
-					if(is.BBO(data)){
-						if (orderqty>0) 
-							prefer='bid'  # we're buying, so work the bid price
-						else
-							prefer='ask'  # we're selling, so work the ask price
-					}
-                    orderprice <- try(getPrice(x=data, prefer=prefer))[timestamp]
-				},
-				maker = {
-					if(hasArg(price) & length(match.call(expand.dots=TRUE)$price)>1) {
-						# we have prices, just use them
-						orderprice <- try(match.call(expand.dots=TRUE)$price)
-					} else {
-						if(!is.null(threshold)) {
-							baseprice<- last(getPrice(x=data)[timestamp]) # this should get either the last trade price or the Close
-							if(hasArg(tmult) & isTRUE(match.call(expand.dots=TRUE)$tmult)) {
-								baseprice<- last(getPrice(x=data)[timestamp]) # this should get either the last trade price or the Close
-								# threshold is a multiplier of current price
-								if (length(threshold)>1){
-									orderprice <- baseprice * threshold # assume the user has set proper threshold multipliers for each side
-								} else {
-									orderprice <- c(baseprice*threshold,baseprice*(1+1-threshold)) #just bracket on both sides
-								}
-							} else {
-								# tmult is FALSE or NULL, threshold is numeric
-								if (length(threshold)>1){
-									orderprice <- baseprice + threshold # assume the user has set proper threshold numerical offsets for each order
-								} else {
-									orderprice <- c(baseprice+threshold,baseprice+(-threshold)) #just bracket on both sides
-								}
-							}
-						} else{
-							# no threshold, put it on the averages?
-							stop('maker orders without specified prices and without threholds not (yet?) supported')
-							if(is.BBO(data)){
-
-							} else {
-
-							}
-						}
-					}
-					if(length(orderqty)==1) orderqty <- c(orderqty,-orderqty) #create paired market maker orders at the same size
-				}
-        )
-        if(inherits(orderprice,'try-error')) orderprice<-NULL
-        if(length(orderprice>1) && !pricemethod=='maker') orderprice<-last(orderprice[timestamp])
-        if(!is.null(orderprice) && !is.null(ncol(orderprice))) orderprice <- orderprice[,1]
-
-        if(is.null(orderside) & !isTRUE(orderqty == 0)){
-            curqty<-getPosQty(Portfolio=portfolio, Symbol=symbol, Date=timestamp)
-            if (curqty>0 ){
-                #we have a long position
-                orderside<-'long'
-            } else if (curqty<0){
-                #we have a short position
-                orderside<-'short'
-            } else {
-                # no current position, which way are we going?
-                if (orderqty>0) 
-                    orderside<-'long'
-                else
-                    orderside<-'short'
-            }
-        }
-        
-        ## now size the order
-        #TODO add fancy formals matching for osFUN
-        orderqty <- osFUN(strategy=strategy, data=data, timestamp=timestamp, orderqty=orderqty, ordertype=ordertype, orderside=orderside, portfolio=portfolio, symbol=symbol,...=...,ruletype=ruletype, orderprice=as.numeric(orderprice))
-        
-        
-        if(!is.null(orderqty) && !orderqty == 0 && !is.null(orderprice)){ #orderqty could have length > 1
-            addOrder(portfolio=portfolio, symbol=symbol, timestamp=timestamp, qty=orderqty, price=as.numeric(orderprice), ordertype=ordertype, side=orderside, threshold=threshold, status="open", replace=replace , delay=delay, tmult=tmult, ...=..., TxnFees=TxnFees,label=label)
-        }
-    }
-    if(sethold) hold <<- TRUE
-}
-
-#TODO ruleORSignal
-#TODO ruleANDSingnal
-# perhaps this could be done using the approach of sigFormula, or perhaps we should advise users to use sigFormula to create a signal you can use ruleSignal on.  Thoughts?
-
-
-#' default order sizing function 
-#' 
-#' default function performs no operation (NoOp), returns orderqty
-#' 
-#' if orderqty 'all', will only work on an exit rule type, otherwize orderqty is zero.
-#'  
-#' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 
-#' @param orderqty numeric quantity of the desired order, modified by osFUN
-#' @param portfolio text name of the portfolio to place orders in
-#' @param symbol identifier of the instrument to place orders for.  The name of any associated price objects (xts prices, usually OHLC) should match these
-#' @param ... any other passthru parameters
-#' @param ruletype one of "risk","order","rebalance","exit","enter", see \code{\link{add.rule}}
-#' @export
-osNoOp <- function(timestamp, orderqty, portfolio, symbol, ruletype, ...){
-	if(orderqty=='all'){
-		if (ruletype=='exit') {
-			orderqty=-1*getPosQty(Portfolio=portfolio,Symbol=symbol,Date=timestamp)
-		} else {
-			message("orderqty 'all' would produce nonsense, maybe use osMaxPos instead?")
-			orderqty=0
-		}
-	} 
-	return(orderqty)
-}
-
-
-#' add position and level limits at timestamp
-#' 
-#' levels are a simplification of more complex (proprietary) 
-#' techniques sometimes used for order sizing.  
-#' the max orderqty returned will be the limit/levels
-#' Obviously the strategy rules could ask for smaller order sizes, 
-#' but this is the default.  If you don't want to use levels, set 
-#' them to 1.
-#' @param portfolio text name of the portfolio to place orders in
-#' @param symbol identifier of the instrument to place orders for.  The name of any associated price objects (xts prices, usually OHLC) should match these
-#' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 
-#' @param maxpos numeric maximum long position for symbol 
-#' @param longlevels numeric number of levels
-#' @param minpos numeric minimum position, default -minpos (short allowed use negative number)
-#' @param shortlevels numeric number of short levels, default longlevels 
-#' @seealso 
-#' \code{\link{osMaxPos}}
-#' \code{\link{getPosLimit}}
-#' @export
-addPosLimit <- function (portfolio, symbol, timestamp, maxpos, longlevels = 1, minpos = -maxpos, shortlevels = longlevels) 
-{
-	portf <- getPortfolio(portfolio)
-	newrow <- xts(cbind(maxpos, longlevels, minpos, shortlevels), order.by = as.POSIXct(timestamp))
-	colnames(newrow) <- c("MaxPos", "LongLevels", "MinPos", "ShortLevels")
-	
-	if (is.null(portf$symbols[[symbol]]$PosLimit)) {
-		portf$symbols[[symbol]]$PosLimit <- newrow
-	} else {
-		if (is.null(portf$symbols[[symbol]]$PosLimit[timestamp])) {
-			portf$symbols[[symbol]]$PosLimit[timestamp] <- newrow
-		} else {
-			portf$symbols[[symbol]]$PosLimit <- rbind(portf$symbols[[symbol]]$PosLimit,	newrow)
-		}
-	}
-	assign(paste("portfolio", portfolio, sep = "."), portf, envir = .blotter)
-}
-
-#' get position and level limits on timestamp
-#' @param portfolio text name of the portfolio to place orders in
-#' @param symbol identifier of the instrument to place orders for.  The name of any associated price objects (xts prices, usually OHLC) should match these
-#' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 
-#' @seealso \code{\link{addPosLimit}},\code{\link{osMaxPos}}
-#' @export
-getPosLimit <- function(portfolio, symbol, timestamp){
-    portf<-getPortfolio(portfolio)
-    # try to get on timestamp, otherwise find the most recent
-    toDate = paste('::', timestamp, sep="")
-    PosLimit = last(portf$symbols[[symbol]]$PosLimit[toDate])
-    return(PosLimit)
-}
-
-#' order sizing function for position limits and level sizing 
-#' 
-#' levels are a simplification of more complex (proprietary) 
-#' techniques sometimes used for order sizing.  
-#' the max orderqty returned will be the limit/levels
-#' Obviously the strategy rules could ask for smaller order sizes, 
-#' but this is the default.  If you don't want to use levels, set 
-#' them to 1.
-#' 
-#' \code{orderqty='all'} in a risk rule will return an order size 
-#' appropriate to flatten the current position.
-#' 
-#' @param data 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 timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 
-#' @param orderqty numeric quantity of the desired order, modified by osFUN
-#' @param ordertype one of "market","limit","stoplimit", or "stoptrailing"
-#' @param orderside one of either "long" or "short" 
-#' @param portfolio text name of the portfolio to place orders in
-#' @param symbol identifier of the instrument to place orders for.  The name of any associated price objects (xts prices, usually OHLC) should match these
-#' @param ruletype one of "risk","order","rebalance","exit","enter", see \code{\link{add.rule}}
-#' @param ... any other passthru parameters
-#' @seealso \code{\link{addPosLimit}},\code{\link{getPosLimit}}
-#' @export
-#' @note 
-#' TODO integrate orderqty='all' into osMaxPos for non-risk exit orders by combining side and pos for exits
-osMaxPos <- function(data, timestamp, orderqty, ordertype, orderside, portfolio, symbol, ruletype, ...){
-	# check for current position
-    pos<-getPosQty(portfolio,symbol,timestamp)
-    # check against max position
-    PosLimit<-getPosLimit(portfolio,symbol,timestamp)
-	
-	#TODO add handling for orderqty='all', and handle risk ruletype separately
-	
-	#check order side
-	if(is.null(orderside) & !isTRUE(orderqty == 0)){
-		curqty<-pos
-		if (curqty>0 ){
-			#we have a long position
-			orderside<-'long'
-		} else if (curqty<0){
-			#we have a short position
-			orderside<-'short'
-		} else {
-			# no current position, which way are we going?
-			if (orderqty>0) 
-				orderside<-'long'
-			else
-				orderside<-'short'
-		}
-	}
-	
-	# check levels
-	# buy long
-    if(orderqty>0 & orderside=='long'){
-        if ((orderqty+pos)<PosLimit[,"MaxPos"]) {
-            #we have room to expand the position
-            if(orderqty<=(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"]) ) {
-                orderqty=orderqty
-            } else {
-                orderqty = round(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"],0) #note no round lots
-            }
-        } else {
-            # this order would put us over the MaxPos limit
-            orderqty<-ifelse((PosLimit[,"MaxPos"]-pos)<=round(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"],0),PosLimit[,"MaxPos"]-pos, round(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"],0)) 
-            if(orderqty+pos>PosLimit[,"MaxPos"]) orderqty <- PosLimit[,"MaxPos"]-pos
-        }
-        return(orderqty)
-    }
-    
-    #sell long
-    if(orderqty<0 & orderside=='long'){
-		if(ruletype=='risk'){
-          if(orderqty=='all') return(-1*pos)
-          else return(orderqty)
-        } 
-		if ((orderqty+pos)>=0) {
-            return(orderqty)
-        } else {
-			orderqty <- -pos #flatten position, don't cross through zero
-            #TODO add code to break into two orders?
-            return(orderqty)
-        }
-    }
-    
-    #sell short
-    if(orderqty<0 & orderside=='short'){
-        if ((orderqty+pos)>PosLimit[,"MinPos"]) {
-            #we have room to expand the position
-            if(orderqty<=(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"]) ) {
-                orderqty=orderqty
-            } else {
-                orderqty = round(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"],0) #note no round lots
-            }
-        } else {
-            # this order would put us over the MinPos limit
-            orderqty<-ifelse((PosLimit[,"MinPos"]-pos)>=round(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"],0),PosLimit[,"MinPos"]-pos, round(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"],0)) 
-            if(orderqty+pos>PosLimit[,"MaxPos"]) orderqty <- PosLimit[,"MinPos"]-pos
-        }
-        return(orderqty)
-    }
-    
-    #buy cover short
-    if(orderqty>0 & orderside=='short'){
-        if(ruletype=='risk'){
-            if(orderqty=='all') return(-1*pos)
-            else return(orderqty)
-        } 
-        if ((orderqty+pos)<=0) {
-            return(orderqty)
-        } else {
-            orderqty<-pos #flatten position, don't cross through zero
-            #TODO add code to break into two orders?
-            return(orderqty)
-        }
-    }
-    
-    # fall through
-    return(0)
-}
-
-#TODO ruleRiskPosLimits to check for overfilled position and scale back
-
-###############################################################################
-# R (http://r-project.org/) Quantitative Strategy Model Framework
-#
-# Copyright (c) 2009-2011
-# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson,
-# Jeffrey Ryan, Joshua Ulrich, and Garrett See
-#
-# This library is distributed under the terms of the GNU Public License (GPL)
-# for full details see the file COPYING
-#
-# $Id$
-#
-###############################################################################



More information about the Blotter-commits mailing list