[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