[Blotter-commits] r1010 - in pkg/quantstrat: R demo

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Fri May 4 13:55:18 CEST 2012


Author: braverock
Date: 2012-05-04 13:55:18 +0200 (Fri, 04 May 2012)
New Revision: 1010

Modified:
   pkg/quantstrat/R/orders.R
   pkg/quantstrat/R/ruleOrderProc.R
   pkg/quantstrat/R/ruleSignal.R
   pkg/quantstrat/demo/macd.R
Log:
- improve order sets functionality to provide OCO (one cancels other) capability.
	many thanks to Jan Humme (OpenTrades) for much of the code

Modified: pkg/quantstrat/R/orders.R
===================================================================
--- pkg/quantstrat/R/orders.R	2012-05-04 11:24:31 UTC (rev 1009)
+++ pkg/quantstrat/R/orders.R	2012-05-04 11:55:18 UTC (rev 1010)
@@ -78,7 +78,7 @@
 #' @seealso addOrder
 #' @concept order book
 #' @export
-getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, which.i=FALSE)
+getOrders <- function(portfolio,symbol,status="open",timespan=NULL,ordertype=NULL, side=NULL, qtysign=NULL, orderset=NULL, which.i=FALSE)
 {
     #if(is.null(timespan)) stop("timespan must be an xts style timestring")
     # get order book
@@ -98,6 +98,7 @@
                      (if(!is.null(status)) ordersubset[,"Order.Status"]==status else TRUE) &
                      (if(!is.null(ordertype)) ordersubset[,"Order.Type"]==ordertype else TRUE) &
                      (if(!is.null(side)) ordersubset[,"Order.Side"]==side else TRUE) &
+                     (if(!is.null(orderset)) ordersubset[,"Order.Set"]==orderset else TRUE) &
                      (if(!is.null(qtysign)) sign(as.numeric(ordersubset[,"Order.Qty"]))==qtysign else TRUE)
                     )
 
@@ -208,7 +209,7 @@
 #' @seealso updateOrders
 #' @concept order book
 #' @export
-addOrder <- function(portfolio, symbol, timestamp, qty, price, ordertype, side, threshold=NULL, status="open", statustimestamp='' , delay=.00001, tmult=FALSE, replace=TRUE, return=FALSE, ..., TxnFees=0,label='')
+addOrder <- function(portfolio, symbol, timestamp, qty, price, ordertype, side, orderset='', threshold=NULL, status="open", statustimestamp='' , delay=.00001, tmult=FALSE, replace=TRUE, return=FALSE, ..., TxnFees=0,label='')
 {
     # get order book
     #orderbook <- getOrderBook(portfolio)
@@ -268,15 +269,6 @@
 
     statustimestamp=NA # new orders don't have a status time
 
-    #handle order sets
-    #get the order set if length(price)>1
-    if(length(price)>1) {
-        order.set<-max(na.omit(getOrders(portfolio=portfolio, symbol=symbol, status='open', timespan=timespan, ordertype=NULL, side=NULL,which.i=FALSE)$Order.Set))
-        if(is.na(order.set)) order.set<-1
-    } else {    
-        order.set=NA
-    }
-
     #set up the other parameters
     if (!length(qty)==length(price)) qty <- rep(qty,length(price))
     if (!length(ordertype)==length(price)) ordertype <- rep(ordertype,length(price))
@@ -287,8 +279,8 @@
     if(is.timeBased(timestamp)) ordertime<-timestamp+delay
     else ordertime<-as.POSIXct(timestamp)+delay
     orders<-NULL
-    for (i in 1:length(price)){
-        neworder<-xts(as.matrix(t(c(qty[i], price[i], ordertype[i], side, threshold[i], status, statustimestamp, order.set,TxnFees,label))),order.by=(ordertime))
+    for (i in 1:length(price)) {
+        neworder<-xts(as.matrix(t(c(qty[i], price[i], ordertype[i], side, threshold[i], status, statustimestamp, orderset[i], TxnFees, label))), order.by=(ordertime))
         if(is.null(orders)) orders<-neworder
         else orders <- rbind(orders,neworder)
     }
@@ -335,6 +327,7 @@
 #' @param ordertype one of NULL, "market","limit","stoplimit", or "stoptrailing" default NULL
 #' @param side one of NULL, "long" or "short", default NULL 
 #' @param qtysign one of NULL, -1,0,1 ; could be useful when all qty's are reported as positive numbers and need to be identified other ways, default NULL
+#' @param set a tag identifying the orderset
 #' @param oldstatus one of NULL, "open", "closed", "canceled", or "replaced", default "open"
 #' @param newstatus one of "open", "closed", "canceled", or "replaced"
 #' @param statustimestamp timestamp of a status update, will be blank when order is initiated

Modified: pkg/quantstrat/R/ruleOrderProc.R
===================================================================
--- pkg/quantstrat/R/ruleOrderProc.R	2012-05-04 11:24:31 UTC (rev 1009)
+++ pkg/quantstrat/R/ruleOrderProc.R	2012-05-04 11:55:18 UTC (rev 1010)
@@ -57,14 +57,14 @@
     ordersubset <- orderbook[[portfolio]][[symbol]]
     
     # get open orders
-    procorders=NULL
-    procorders<-getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timespan, ordertype=ordertype, which.i=TRUE)
+    OpenOrders.i=NULL
+    OpenOrders.i<-getOrders(portfolio=portfolio, symbol=symbol, status="open", timespan=timespan, ordertype=ordertype, which.i=TRUE)
 
     if(hasArg(prefer)) prefer=match.call(expand.dots=TRUE)$prefer
     else prefer = NULL
 
     # check for open orders
-    if (length(procorders)>=1){
+    if (length(OpenOrders.i)>=1){
         # get previous bar
         prevtime  <- time(mktdata[last(mktdata[timespan, which.i = TRUE])-1]) 
         timestamp <- time(last(mktdata[timespan]))
@@ -77,7 +77,12 @@
         if( NROW(mktdataTimestamp) > 1 ) mktdataTimestamp <- last(mktdataTimestamp)
         isOHLCmktdata <- is.OHLC(mktdata)
         isBBOmktdata  <- is.BBO(mktdata)
-        for (ii in procorders ){
+        for (ii in OpenOrders.i ){
+		if(ordersubset[ii, "Order.Status"] != "open")	# need to check this bc sideeffects may have changed order.status in this loop
+		{
+			#print("@@@@@@@@ status changed from open")
+			next()
+		}
             txnprice=NULL
             txnfees=ordersubset[ii,"Txn.Fees"]
             orderPrice <- as.numeric(ordersubset[ii,"Order.Price"])
@@ -290,6 +295,12 @@
                                  TxnQty=orderQty, TxnPrice=txnprice , ...=..., TxnFees=txnfees)
                     ordersubset[ii,"Order.Status"]<-'closed'
                     ordersubset[ii,"Order.StatusTime"]<-as.character(timestamp)
+
+                    #close all other orders in the order set
+                    OrdersetTag = toString(ordersubset[ii,"Order.Set"])
+		    OpenInOrderset.i = which(ordersubset[,"Order.Status"] == 'open' & ordersubset[,"Order.Set"] == OrdersetTag)
+                    ordersubset[OpenInOrderset.i, "Order.Status"] = 'canceled'
+                    ordersubset[OpenInOrderset.i, "Order.StatusTime"]<-as.character(timestamp)
                 } 
             }
         } #end loop over open orders  

Modified: pkg/quantstrat/R/ruleSignal.R
===================================================================
--- pkg/quantstrat/R/ruleSignal.R	2012-05-04 11:24:31 UTC (rev 1009)
+++ pkg/quantstrat/R/ruleSignal.R	2012-05-04 11:55:18 UTC (rev 1010)
@@ -27,6 +27,7 @@
 #' @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 orderset tag to identify an orderset; if one order of the set is filled, all others are canceled
 #' @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 
@@ -43,7 +44,7 @@
 #' @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='')
+ruleSignal <- function(data=mktdata, timestamp, sigcol, sigval, orderqty=0, ordertype, orderside=NULL, orderset='', 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)
@@ -142,15 +143,17 @@
         
         ## now size the order
         #TODO add fancy formals matching for osFUN
-        if(!(ruletype=='risk') && (orderqty=='all'))
+        if(!(ruletype=='risk') && (orderqty=='all')){
             # Joe Dunn suggested if((ruletype != 'risk') && (orderqty !='all'))
             # but that didn't work either.  needs more investigation
-    
-        orderqty <- osFUN(strategy=strategy, data=data, timestamp=timestamp, orderqty=orderqty, ordertype=ordertype, orderside=orderside, portfolio=portfolio, symbol=symbol,...=...,ruletype=ruletype, orderprice=as.numeric(orderprice))
+            
+            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)
+            addOrder(portfolio=portfolio, symbol=symbol, timestamp=timestamp, qty=orderqty, price=as.numeric(orderprice), ordertype=ordertype, side=orderside, orderset=orderset, threshold=threshold, status="open", replace=replace , delay=delay, tmult=tmult, ...=..., TxnFees=TxnFees,label=label)
         }
     }
     if(sethold) hold <<- TRUE

Modified: pkg/quantstrat/demo/macd.R
===================================================================
--- pkg/quantstrat/demo/macd.R	2012-05-04 11:24:31 UTC (rev 1009)
+++ pkg/quantstrat/demo/macd.R	2012-05-04 11:55:18 UTC (rev 1010)
@@ -60,12 +60,12 @@
 
 #alternatives for risk stops:
 # simple stoplimit order, with threshold multiplier
-# add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.gt.zero",sigval=TRUE, orderqty='all', ordertype='stoplimit', orderside='long', threshold=-.05,tmult=TRUE),type='risk',label='risk',storefun=FALSE)
+add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.gt.zero",sigval=TRUE, orderqty='all', ordertype='stoplimit', orderside='long', threshold=-.05,tmult=TRUE, orderset='exit2'),type='risk',label='risk',storefun=FALSE)
 # alternately, use a trailing order, also with a threshold multiplier
-# add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.gt.zero",sigval=TRUE, orderqty='all', ordertype='stoptrailing', orderside='long', threshold=-.1,tmult=TRUE),type='risk',label='trailingexit')
+#add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.gt.zero",sigval=TRUE, orderqty='all', ordertype='stoptrailing', orderside='long', threshold=-.15,tmult=TRUE, orderset='exit2'),type='risk',label='trailingexit')
 
 # exit
-add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.lt.zero",sigval=TRUE, orderqty='all', ordertype='market', orderside='long', threshold=NULL),type='exit',label='exit')
+add.rule(strat.st,name='ruleSignal', arguments = list(sigcol="signal.lt.zero",sigval=TRUE, orderqty='all', ordertype='market', orderside='long', threshold=NULL,orderset='exit2'),type='exit',label='exit')
 
 #end rules
 ####



More information about the Blotter-commits mailing list