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

  • ptunneyptunney Posts: 246
    Answer ✓

    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_dt

    class 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()
    

    `

Sign In or Register to comment.