Here is an example of a strategy with several timeframes on which I am working with quantstrate. Is this the right way to implement a strategy with multiple timeframes, or am I doing it all wrong? I have not come across any other examples making multi-timeframes in quantumstrat demonstrations or from googling.
To simplify the strategy (this is not a strategy that someone will trade) and focus on the multi-timeframe aspect, I will demonstrate a simple strategy that uses tick data and 5-minute OHLC data. The logic of the strategy is to buy when tick data intersects with a 30-second SMA from 5-minute data and close the position when tick data intersects below the same SMA.
For example: if the strategy is flat, the time is 13:02, and the previous observed 30-period SMA from 5-minute data is 90.55 (for the period 12:55 - end 13:00) and the tick data intersects below 90.55 and above (90,56) this is a purchase, and when the tick data closes below it again, it goes out of position.
To achieve this, I need to get the tick data and the 5-minute 30-period SMA in the same object to process the quantstrate. I get 5 minute OHLC xts and compute a 30 period SMA. Then I combine this into a tick data xts object, which will give me an object with all the tick data, and then every 5 minutes I will get a line with the last 5 minute 30-period SMA observed.
If at 13:00 there is a 30-period SMA value, it will be in 5 minutes 12: 55-13: 00. Since the next SMA update is 5 minutes, I need to fill in the lines to the next value (at 13:05) and so on.
Here's the head of the tick data (tick data does not include milliseconds, but I made the lines unique using make.index.unique(clemtick) :
head(clemtick) Price Volume 2013-01-15 09:00:00 93.90 1 2013-01-15 09:00:00 93.89 1 2013-01-15 09:00:00 93.89 1 2013-01-15 09:00:00 93.88 2 2013-01-15 09:00:00 93.89 1 2013-01-15 09:00:00 93.89 2
Here is the head 1-minute data (each minute represents the previous minute of data, for example, a timestamp of 09:01:00 == data from 09:00:00 to 09:01:00):
head(clemin) Open High Low Close Volume 2013-01-15 09:01:00 93.90 94.04 93.87 93.97 1631 2013-01-15 09:02:00 93.97 93.98 93.90 93.91 522 2013-01-15 09:03:00 93.91 93.97 93.90 93.96 248 2013-01-15 09:04:00 93.95 93.98 93.93 93.95 138 2013-01-15 09:05:00 93.95 93.96 93.91 93.92 143 2013-01-15 09:06:00 93.93 93.97 93.91 93.91 729
Convert 1 minute data to 5 minute data:
cle5min <- to.minutes5(clemin) clemin.Open clemin.High clemin.Low clemin.Close clemin.Volume 2013-01-15 09:04:00 93.90 94.04 93.87 93.95 2539 2013-01-15 09:09:00 93.95 93.97 93.81 93.89 2356 2013-01-15 09:14:00 93.90 94.05 93.86 93.89 4050 2013-01-15 09:19:00 93.90 94.03 93.84 94.00 2351 2013-01-15 09:24:00 93.99 94.21 93.97 94.18 3261 2013-01-15 09:29:00 94.18 94.26 94.18 94.19 1361
You will notice that the first OHLC is 09:04:00, this is due to how the to.minutes5 function works in this thread . Essentially the first stamp 09:04:00 == OHLC 4 minutes of data from 09:00:00 to 09:04:00. 09:09:00 time stamp next full 5 minutes from 09:04:00 - 09:09:00. Ideally, I would like each time stamp to be 5, 10, 15, etc., But I have not yet developed how to do this.
To get 30 SMA from 5min data into tick data
clemtick$sma30 <- SMA(cle5min$clemin.Close, 30)
This creates a new column with SMA. The SMA requires 30 periods to calculate the first value, and the SMA will only be displayed every 5 minutes (11:29:00, 11:34:00, 11:39, ...). It looks like this:
clemtick["2013-01-15 11:28:59::2013-01-15 11:29:00"] Price Volume SMA30 2013-01-15 11:28:59 93.87 1 NA 2013-01-15 11:28:59 93.87 1 NA 2013-01-15 11:28:59 93.88 1 NA 2013-01-15 11:29:00 93.87 1 93.92633 2013-01-15 11:29:00 93.87 1 NA 2013-01-15 11:29:00 93.88 1 NA 2013-01-15 11:29:00 93.88 1 NA
Now I need to populate the SMA30 column SMA30 duplicate value. The value for SMA30 at 11:29:00 for OHLC from 11:24:00 to 11:29:00. The next update of this value will not be until 11:34:00, so I need to fill in the lines to the next value, since this will be a link to the strategy when processing line by line.
clemtick <- na.locf(clemtick)
Now, if I request this object again,
clemtick["2013-01-15 11:33:58::2013-01-15 11:34:01"] Price Volume SMA30 2013-01-15 11:33:58 93.84 1 93.92633 2013-01-15 11:34:00 93.84 1 93.92267 2013-01-15 11:34:00 93.85 1 93.92267 2013-01-15 11:34:01 93.84 1 93.92267
Now that we have the final object, we run the strategy:
require(quantstrat) options("getSymbols.warning4.0"=FALSE) rm(list=ls(.blotter), envir=.blotter) Sys.setenv(TZ="UTC") symbols <- "clemtick" currency('USD') stock(symbols, currency="USD", multiplier=1) account.st <- 0 strategy.st <- portfolio.st <- account.st <- "multi" rm.strat(portfolio.st) rm.strat(strategy.st) initDate <- "1980-01-01" tradeSize <- 1000 initEq <- tradeSize*length(symbols) initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD') initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD', initEq=initEq) initOrders(portfolio.st, initDate=initDate) strategy(strategy.st, store=TRUE) add.signal(strategy.st, name="sigCrossover", arguments=list(columns=c("Price", "sma30"), relationship="gt"), label="golong") add.signal(strategy.st, name="sigCrossover", arguments=list(columns=c("Price", "sma30"), relationship="lt"), label="exitlong") #enter rule add.rule(strategy.st, name="ruleSignal", arguments=list(sigcol="golong", sigval=TRUE, ordertype="market", orderside="long", replace=TRUE, prefer="Price", orderqty=1), type="enter", path.dep=TRUE, label="long") #exit rule add.rule(strategy.st, name = "ruleSignal", arguments=list(sigcol="exitlong", sigval=TRUE, ordertype="market", orderside="long", replace=TRUE, prefer="Price", orderqty=-1), type="exit", path.dep=TRUE, label="exitlong") #apply strategy t1 <- Sys.time() out2 <- applyStrategy(strategy=strategy.st, portfolios=portfolio.st, debug=TRUE) t2 <- Sys.time() print(t2-t1) head(mktdata) nrow(mktdata)
So, to summarize, is this the best way to make multiple time strategies?