Is there a limitation on the number of historical bars that can be referenced?
Why does self.advvol4 and self.decvol4 lists not get populated in running this code? Use SPY and test date of 7/27/18 Core and Extended hours. The behavior suggests 2880 bars is a limitation?
from cloudquant.interfaces import Strategy
from cloudquant.util import dt_from_muts, muts_from_dt
import pandas as pd
import numpy as np
import datetime
import talib
class CQd1826011c83d4a2e807470883da168a5(Strategy):
########################################################################################
#
# high level strategy - start/finish
#
########################################################################################
# called when the strategy starts (aka before anything else)
@classmethod
def on_strategy_start(cls, md, service, account):
pass
# called when the strategy finish (aka after everything else has stopped)
@classmethod
def on_strategy_finish(cls, md, service, account):
pass
########################################################################################
#
# symbol universe
#
########################################################################################
# note that this doesn't start with "self" because it's a @classmethod
@classmethod
def is_symbol_qualified(cls, symbol, md, service, account):
sp500=service.symbol_list.in_list(service.symbol_list.get_handle('9a802d98-a2d7-4326-af64-cea18f8b5d61'),symbol) # list.in_list ( sp500 list for today, current symbol)
nasdaq=service.symbol_list.in_list(service.symbol_list.get_handle('18305bb4-9bf4-4032-835c-1c9e0dd203c3'),symbol) # list.in_list (NASDAQ List for today, current symbol)
#return symbol== 'SPY' or sp500
#return symbol== 'QQQ' or nasdaq
return symbol== 'SPY'
#return symbol in ('MSFT','FB','IBM','AAPL','WMT')
#return symbol in ('SPY','QQQ','IWM','DIA')
#return True
# used to load other symbols data not in is_symbol_qualified(). Only used in backtesting
@classmethod
def backtesting_extra_symbols(cls, symbol, md, service, account):
return False
########################################################################################
#
# start/finish instance related methods
#
########################################################################################
# used to pass external parameters for each instance (same for values for every instance)
def __init__(self): #, **params - if passing in parameters is desired
pass
# called at the beginning of each instance
def on_start(self, md, order, service, account):
self.advvol1 = []
self.decvol1 = []
self.advvol2 = []
self.decvol2 = []
self.advvol3 = []
self.decvol3 = []
self.advvol4 = []
self.decvol4 = []
#Get 4 Days of 1 Minute Bar Data to Include Pre and After Market
mb4 = md.bar.minute(start=-3840,end=None,include_empty=True,include_extended=True,bar_size=1,today_only=False)
opn = mb4.open
close = mb4.close
volume = mb4.volume
ts = mb4.timestamp
for x in range(len(close)) :
bar = close[x] - opn[x]
print x,"Time Stamp",service.time_to_string(ts[x]),"Open",opn[x],"Close",close[x],"Net",bar,"Volume",volume[x]
# Day 1
if bar >= 0 and x >= 0 and x <= 959:
self.advvol1.append(volume[x])
#print "Advancing Volume",self.advvol1
elif bar < 0 and x >= 0 and x < 959:
self.decvol1.append(volume[x])
#print "Decling Volume",self.decvol1
# Day 2
elif bar >= 0 and x >=960 and x <= 1919:
self.advvol2.append(volume[x])
#print "Advancing Volume",self.advvol2
elif bar < 0 and x >=960 and x <= 1919:
self.decvol2.append(volume[x])
#print "Decling Volume",self.decvol2
# Day 3
elif bar >= 0 and x >= 1920 and x <= 2879:
self.advvol3.append(volume[x])
#print "Advancing Volume",self.advvol3
elif bar < 0 and x >= 1920 and x <= 2879:
self.decvol3.append(volume[x])
#print "Decling Volume",self.decvol3
# Day 4
elif bar >= 0 and x >= 2880 and x <= 3839:
self.advvol4.append(volume[x])
#print "Advancing Volume",self.advvol4
elif bar < 0 and x >= 2880 and x <= 3839:
self.decvol4.append(volume[x])
#print "Decling Volume",self.decvol4
#print "Advancing Volume",self.advvol
self.sumadvvol1 = sum(self.advvol1)
self.sumadvvol2 = sum(self.advvol2)
self.sumadvvol3 = sum(self.advvol3)
self.sumadvvol4 = sum(self.advvol4)
print "Sum Adv Vol Day 1",self.sumadvvol1
print "Sum Adv Vol Day 2",self.sumadvvol2
print "Sum Adv Vol Day 3",self.sumadvvol3
print "Sum Adv Vol Day 4",self.sumadvvol4
#print "Declining Volume",self.decvol
self.sumdecvol1 = sum(self.decvol1)
self.sumdecvol2 = sum(self.decvol2)
self.sumdecvol3 = sum(self.decvol3)
self.sumdecvol4 = sum(self.decvol4)
print "Sum Dec Vol Day 1",self.sumdecvol1
print "Sum Dec Vol Day 2",self.sumdecvol2
print "Sum Dec Vol Day 3",self.sumdecvol3
print "Sum Dec Vol Day 4",self.sumdecvol4
# Total Volume
self.sumvol1 = (self.sumadvvol1 + self.sumdecvol1)
self.sumvol2 = (self.sumadvvol2 + self.sumdecvol2)
self.sumvol3 = (self.sumadvvol3 + self.sumdecvol3)
self.sumvol4 = (self.sumadvvol4 + self.sumdecvol4)
self.totalvol = (self.sumvol1 + self.sumvol2 + self.sumvol3 + self.sumvol4)
print "Total Volume",self.totalvol
# Calculate Day 1 - Day 4 Adv/Dec Volume %
self.onedayvolper1 = round((self.sumadvvol1*1.0 / self.sumvol1)*100,2)
self.onedayvolper2 = round((self.sumadvvol2*1.0 / self.sumvol2)*100,2)
self.onedayvolper3 = round((self.sumadvvol3*1.0 / self.sumvol3)*100,2)
self.onedayvolper4 = round((self.sumadvvol4*1.0 / self.sumvol4)*100,2)
print "Day 1 Volume Percentage",self.onedayvolper1
print "Day 2 Volume Percentage",self.onedayvolper2
print "Day 3 Volume Percentage",self.onedayvolper3
print "Day 4 Volume Percentage",self.onedayvolper4
# Calculate 4 Day Volume % Avg
self.fourdayvolper = round(((self.onedayvolper1+self.onedayvolper2+self.onedayvolper3+self.onedayvolper4)/4),2)
print "One Day Volume Avg Percent", self.onedayvolper1
print "Four Day Volume Avg Percent",self.fourdayvolper
# if running with an instance per symbol, call when an instance is terminated
def on_finish(self, md, order, service, account):
pass
########################################################################################
#
# timer method
#
########################################################################################
# called in timer event is received
def on_timer(self, event, md, order, service, account):
pass
########################################################################################
#
# market data related methods
#
########################################################################################
# called every minute before the first on_trade of every new minute, or 5 seconds after a new minute starts
def on_minute_bar(self, event, md, order, service, account, bar):
pass
# called when time and sales message is received
def on_trade(self, event, md, order, service, account):
pass
# called when national best bid offer (nbbo) prices change (not size)
def on_nbbo_price( self, event, md, order, service, account ):
pass
# called when arca imbalance message is received
def on_arca_imbalance(self, event, md, order, service, account):
pass
# called when nasdaq imbalance message is received
def on_nasdaq_imbalance(self, event, md, order, service, account):
pass
# called when nyse/amex/nsye mkt/openbook message is received
def on_nyse_imbalance(self, event, md, order, service, account):
pass
########################################################################################
#
# order related methods
#
########################################################################################
# called when order considered pending by the system
def on_ack(self, event, md, order, service, account):
pass
# called when an order is rejected (locally or other parts of the order processes e.g. the market)
def on_reject(self, event, md, order, service, account):
pass
# called when the position changes in this account and symbol (whether manually or automated)
def on_fill(self, event, md, order, service, account):
pass
# called when the market has confirmed an order has been canceled
def on_cancel(self, event, md, order, service, account):
pass
Best Answer
-
ptunney Posts: 246
J
You seem to be scanning the minute bars, if the open>close then it is an advancing volume minute, if open<close then it is a declining volume minute.
If the time is within day 1's range you are appending the volume to day1s adv/dec data and so on up to day 4 but you are running out of data.The simple answer is yes, we keep 2880 minute bars for each backtest day 4am to 8pm = 3 days of minute bars.
Up to now we have not had anyone want to go back more than that.
Daily bars max is 252 days or 1 year. The daily bars can be extended but at a cost to your backtest time.We keep these (adjusted) bars in with each day's backtest data so that they are point-in-time, they look how they would have looked at that time in the market.
Extending the number of minute bars available would not be a trivial matter (we would have to recreate that file for every symbol for every date) and is not in high demand.Now, the absolute ideal would be that we already had adv/dec data available in some fundamental data within CloudQuant. We are trying hard to get to that point but quality point-in-time fundamental data is surprisingly hard to come by. Watch this space.
For your current situation, you have a few potential solutions :
1) Go without the 4th day! Easiest solution, adapt yourself to the data available.
2) Write a script that you run for every day calculating its adv/dec and store that data in a file. Then read in the dates you need at the start of each backtest. That way you only ever run this adv/dec once for each day and from then on you are simply reading the data in, this can be much faster for you in the long run
3) Similar to 2 but find the data in some fundamental data, store it in a file and read it in.
4) Request that we extend the number of minute bars available. If this was regularly requested I could imagine it getting a priority but it seems unlikely.Hope this helps!
Paul
`
from cloudquant.interfaces import Strategy
from cloudquant.util import dt_from_muts, muts_from_dtclass jliljekrans(Strategy): @classmethod def is_symbol_qualified(cls, symbol, md, service, account): return symbol== 'SPY' def on_start(self, md, order, service, account): mb4 = md.bar.minute(start=-6000,include_empty=True,include_extended=True,today_only=False) print len(mb4.close) for x in range(len(mb4.close)) : print service.time_to_string(mb4.timestamp[x]) db4 = md.bar.daily(start=-6000) print len(db4.close) service.terminate()
`