Mariner Backtesting - bar_size

Minute Bar Size Overview:

In this lesson, we will learn how works and tips to help avoid faulty data.

What does bar_size do?
 bar.minute(start=-1, bar_size=1)
  • Bar size determines how large a bar you will receive from the minute() method call
  • For example: a bar size of 1 contains 1 minute worth of data.
  • Requesting a 2 minute bar does not return data for the last two minutes, it returns the most recently competed 2 minute bar.
Precautions:

Using bars with a size larger than 1 can be dangerous.

For example: if you request a two minute bar at 9:35:00, you will receive data from 9:32-9:34 (the most recently completed 2 minute bar). If you are not careful, you could end up using out of date information.

Here we request the most recently completed 3 minute bar in a timer at 9:36 and print the time.

bar_3m = bar.minute(start=-1, bar_size=3)
print("bar_3m data starts at " + service.time_to_string(self.bar_3m.timestamp[0])[11:19] + "\n")

You can see that the time is accurate, a 3 minute bar will go start 3 minutes before 9:36.

bar data starts at 09:33:00

However, the same code executed at 9:35 will have bar data from 9:30.

bar data starts at 09:30:00

This is why 1 minute bars are the most reliable, especially in on_trade. With 1 minute bars you don't need to worry as much about your data being outdated.

Working Example:

Link to the code in CQ to clone

 # Copyright Cloudquant, LLC. All right reserved.
# Like on_minute_bar, rolled minute bars are not available right after the last bar completes, best to wait 5 seconds, hence self.delay
# some symbols will update before that but if a symbol has no new print(after 5 seconds the previous bar will be created anyway.
# Or you can just trigger in on_minute_bar and check the time yourself.
# If you look at the most recent 3 minute bar at 9:36:05 the timestamp for the start of the bar will be 9:33
# If you look at the most recent 3 minute bar at 9:35:05 the timestamp for the start of the bar will be 9:30
# Here we set up two repeating timer callbacks and attempt to roll up bars at those time
# In the Fifteen callback we look at bars in this trading day, back into premarket, this trading day and yesterday as well as one for today and yesterday including premarket

from cloudquant.interfaces import Strategy

class RollYourOwnMinuteBars(Strategy):

    @classmethod
    def is_symbol_qualified(cls, symbol, md, service, account):
        return symbol == "AAPL"

    def on_start(self, md, order, service, account):
#        self.delay = service.time_interval(milliseconds=1) # can't go off at 9:45 and get prev 15 minute bar, add a delay
        self.delay = service.time_interval(seconds=5) # can't go off at 9:45 and get prev 15 minute bar, add a delay
        self.fifteenMin = service.time_interval(minutes=15)
        self.oneHour = service.time_interval(hours=1)
        service.clear_event_triggers()
        service.add_time_trigger(md.market_open_time+self.fifteenMin+self.delay,repeat_interval=self.fifteenMin,timer_id="Fifteen")
        service.add_time_trigger(md.market_open_time+self.oneHour+self.delay,repeat_interval=self.oneHour,timer_id="Hour")
        return 

    def on_timer(self, event, md, order, service, account): # called every 30 mins from 10am by timer set up above
        print("On_Timer, Call Time",service.time_to_string(event.timestamp)[11:19],"Event ID :",event.timer_id)

        if event.timer_id=="Fifteen":
            bar15m = md.bar.minute(start=-100, bar_size=15,)
            bar15m_pre = md.bar.minute(start=-100, bar_size=15,include_extended=True)
            bar15m_yest = md.bar.minute(start=-300, bar_size=15,today_only=False)
            bar15m_pre_and_yest = md.bar.minute(start=-300, bar_size=15,include_extended=True,today_only=False)
            if len(bar15m.close)>0: # very thin symbols may have no bars in the 15m
                print("Last three close prices for normal bar",bar15m.close[-3:])
                # the [11:16] pulls out characters 11 to 16 from the time string, effectively HH:MM
                print("Start time for most recent bar normal ",service.time_to_string(bar15m.timestamp[-1])[11:16])
                print("Oldest bar start time normal          ",service.time_to_string(bar15m.timestamp[-len(bar15m.timestamp)]),"# of bars",len(bar15m.close))
            if len(bar15m_pre.close)>0: # very thin symbols may have no bars in the 15m incl pre
                print("Oldest bar start time inc pre         ",service.time_to_string(bar15m_pre.timestamp[-len(bar15m_pre.timestamp)]),"# of bars",len(bar15m_pre.close))
            print("Oldest bar start time inc yest        ",service.time_to_string(bar15m_yest.timestamp[-len(bar15m_yest.timestamp)]),"# of bars",len(bar15m_yest.close))
            print("Oldest bar start time inc pre and yest",service.time_to_string(bar15m_pre_and_yest.timestamp[-len(bar15m_pre_and_yest.timestamp)]),"# of bars",len(bar15m_pre_and_yest.close))
            print()

        if event.timer_id=="Hour":
            print("**************  HALF PAST THE HOUR!  **************")
            bar60m = md.bar.minute(start=-100, bar_size=60,)
            print("Last three close prices for hour bar",bar60m.close[-3:])
            print("Start time for most recent hour bar " + service.time_to_string(bar60m.timestamp[-1])[11:16] )
            print("Oldest hour bar start time          ",service.time_to_string(bar60m.timestamp[-len(bar60m.timestamp)]),"# of bars",len(bar60m.close))
            print()

Console

 On_Timer, Call Time 09:45:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.50999451]
Start time for most recent bar normal 09:30
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 1
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 23
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 79
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 215

On_Timer, Call Time 10:00:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.50999451  167.88000488]
Start time for most recent bar normal 09:45
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 2
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 24
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 80
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 216

On_Timer, Call Time 10:15:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.50999451  167.88000488  167.42500305]
Start time for most recent bar normal 10:00
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 3
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 25
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 81
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 217

On_Timer, Call Time 10:30:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.88000488  167.42500305  167.21000671]
Start time for most recent bar normal 10:15
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 4
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 26
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 82
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 218


On_Timer, Call Time 10:30:00 Event ID : Hour
**************  HALF PAST THE HOUR!  **************
Last three close prices for hour bar [ 167.21000671]
Start time for most recent hour bar 09:30
Oldest hour bar start time           2018-02-01 09:30:00.000000 # of bars 1


On_Timer, Call Time 10:45:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.42500305  167.21000671  167.1000061 ]
Start time for most recent bar normal 10:30
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 5
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 27
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 83
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 219

On_Timer, Call Time 11:00:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.21000671  167.1000061   167.1499939 ]
Start time for most recent bar normal 10:45
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 6
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 28
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 84
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 220

On_Timer, Call Time 11:15:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.1000061   167.1499939   167.08999634]
Start time for most recent bar normal 11:00
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 7
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 29
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 85
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 221

On_Timer, Call Time 11:30:00 Event ID : Fifteen
Last three close prices for normal bar [ 167.1499939   167.08999634  167.19000244]
Start time for most recent bar normal 11:15
Oldest bar start time normal           2018-02-01 09:30:00.000000 # of bars 8
Oldest bar start time inc pre          2018-02-01 04:00:00.000000 # of bars 30
Oldest bar start time inc yest         2018-01-29 09:30:00.000000 # of bars 86
Oldest bar start time inc pre and yest 2018-01-29 04:00:00.000000 # of bars 222

On_Timer, Call Time 11:30:00 Event ID : Hour
**************  HALF PAST THE HOUR!  **************
Last three close prices for hour bar [ 167.21000671  167.19000244]
Start time for most recent hour bar 10:30
Oldest hour bar start time           2018-02-01 09:30:00.000000 # of bars 2

etc...
Working Example 2 :
 from cloudquant.interfaces import Strategy


class BarSize(Strategy):

    @classmethod
    def is_symbol_qualified(cls, symbol, md, service, account):

        # only run the script on AAL
        return symbol == "AAL"

    def on_start(self, md, order, service, account):
        pass

    def on_minute_bar(self, event, md, order, service, account, bar):
        print '---------- in on_minute_bar() ' + service.time_to_string(event.timestamp)[11:19]

        # check that the time is between 9:35 and 9:36.
        if event.timestamp > service.time(9,35) and event.timestamp < service.time(9,36):

            # request the most recent 3 minute bar
            bar_3m = bar.minute(start=-1, bar_size=3)

            # print bar information; 3 minute bars
            # [11:19] on a timestamp returns only the time
            print("\nbar start time: " + service.time_to_string(bar_3m.timestamp[0])[11:19] + "\n")

        # check that the time is after 9:36 and terminate()
        elif event.timestamp > service.time(9, 36):

            # request the most recent 3 minute bar
            bar_3m = bar.minute(start=-1, bar_size=3)

            # print bar information; 3 minute bars
            print("\nbar start time: " + service.time_to_string(bar_3m.timestamp[0])[11:19] + "\n")

            service.terminate()

Console 2

---------- in on_minute_bar() 09:30:00
---------- in on_minute_bar() 09:31:00
---------- in on_minute_bar() 09:32:00
---------- in on_minute_bar() 09:33:00
---------- in on_minute_bar() 09:34:01
---------- in on_minute_bar() 09:35:00

bar start time: 09:30:00

---------- in on_minute_bar() 09:36:00

bar start time: 09:33:00