Exchange pubishes 30 days of 1m bar of histories, which helps to build 60m bars. When market is running, exchange will push ticks at frequency on 2 ticks per second, which could be used to build 1m bar or other time scale bars.
The strategy that I’m running is using 60m bars. There’re many ways on building 60m bars. For my case, I want to build 60m bars so that they follow the mainstream market data terminal definitions, so that it would be easier to check technical indicators for validation purpose.
Currently, the framework is using time’s minute field to check if it is divisible by 60 to conclude whether the 60m bar is completed. For example at 09:59:59.500, the next tick comes in as 10:00:00, which suggest that the 60m will be done and published to anyone who’s interested to receive the event and then start to build a new bar for the next 60m.
There’s nothing wrong with the default logic, just that the bars are different from mainstream market datda terminals. OHLCV show slightly different numbers, resulting that technical indicators are slightly different as well, which makes validation a bit difficult.
Mainstream market data terminals are using accumulation of 1m bar to 60 to build 1h bars. So basically, the 1m bars for a trading day needs to be group together with index from 1 to N. When the index is divisable by 60, the 60m bar will be published and notify any listeners who’s registered with such event.
Note that, when session closes (entering market close or breaks), the close event will be sent, and there won’t be any open event following that. When session opens (recovering from break or market just open), the open event will be triggered.
For 60m building process, we need to check its timestamp whether it’s closing time.
Scenario 1: Corn Sep 2021 Contract
Night market: [21:00, 23:00]
Day market: [09:00, 10:15], [10:30, 11:30], [13:30, 15:00]
Eve before the public holidays might not have night market, depending on announcement from exchanges.
1m Bar Count:
[2100, 2300]: 120 bars
[0900,1015]: 75 bars
[1030,1130]: 60 bars
[1330,1500]: 90 bars
60m Bar Building:
1 [2100,2200]: 60 bars, ending on 2101, 2102, 2103, till 2200.
2 (2200,2300]: 60 bars, ending on 2201, 2202, 2203, till 2300.
3 [0900,1000]: 60 bars, ending on 0901, 0902, till 1000.
4 (1000,1015], 15 bars, [1030,1115] 45 bars: totals up to 60bars.
5 (1115,1130], 15 bars, [1330,1415] 45 bars: totals up to 60bars.
6 (1415,1500]: 45 bars and market closes.
When there’s no night market, then there’ll be only index 3 till 6 will be built. Normally, it will be 1-6 bars for each trading session.
Scenario 2: Silver Jun 2021 Contract Listed on SHFE (AG2106)
Night market: [21:00, 02:30]
Day market: [09:00, 10:15], [10:30, 11:30], [13:30, 15:00]
1m Bar Count:
[2100, 0230]: 120 bars + 210 bars
[0900,1015]: 75 bars
[1030,1130]: 60 bars
[1330,1500]: 90 bars
60m Bar Building:
1 [2100,2200]: 60 bars, ending on 2101, 2102, 2103, till 2200.
2 (2200,2300]: 60 bars, ending on 2201, 2202, 2203, till 2300.
3 (2300,2400]: 60 bars, ending on 2301, 2302, till 2400.
4 (0000,0100]: 60 bars.
5 (0100,0200]: 60 bars.
6 (0200,0230], 30 bars, [0900,0930] 30 bars: totals up to 60 bars.
7 (0930,1015] 45 bars, (1030,1045] 15 bars: totals up to 60 bars.
8 (1045,1130] 45 bars, [1330,1345] 15 bars: totals up to 60 bars.
9 (1345,1445]: 60 bars.
10 (1445, 1500]: 15 bars and market closes.
Scenario 3: HS300 Index Future Jun 2021 Contract Listed on CFFEX (IF2106)
Night market: NIL
Day market: [09:30, 11:30], [13:00, 15:00]
1m Bar Count:
[0930,1130]: 120 bars
[1300,1500]: 120 bars
60m Bar Building:
1 [0930,1030]: 60 bars.
2 (1030,1130]: 60 bars.
3 [1300,1400]: 60 bars.
4 (1400,1500]: 60 bars.
Note that IF has no night session, and no 10am breaks. It follows the trading hour of stock market.
Close Event
For each of the time intervals listed in any of the above scenarios, we can trigger CloseEvent, which should recalculate all indicators, and also generate strategy signals. However, we should not just send out orders yet.
Open Event
Execute orders here.
The Open/Close events are quite complicated by itself, so I created another entry to analyze further.