Merge pull request #1660 from vnpy/hour_bar

[Add]support hour bar generation
This commit is contained in:
vn.py 2019-05-05 14:33:49 +08:00 committed by GitHub
commit 768e24368c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -10,7 +10,7 @@ import numpy as np
import talib
from .object import BarData, TickData
from .constant import Exchange
from .constant import Exchange, Interval
def extract_vt_symbol(vt_symbol: str):
@ -113,21 +113,33 @@ class BarGenerator:
"""
For:
1. generating 1 minute bar data from tick data
2. generateing x minute bar data from 1 minute data
2. generateing x minute bar/x hour bar data from 1 minute data
Notice:
1. for x minute bar, x must be able to divide 60: 2, 3, 5, 6, 10, 15, 20, 30
2. for x hour bar, x can be any number
"""
def __init__(
self, on_bar: Callable, xmin: int = 0, on_xmin_bar: Callable = None
self,
on_bar: Callable,
window: int = 0,
on_window_bar: Callable = None,
interval: Interval = Interval.MINUTE
):
"""Constructor"""
self.bar = None
self.on_bar = on_bar
self.xmin = xmin
self.xmin_bar = None
self.on_xmin_bar = on_xmin_bar
self.interval = interval
self.interval_count = 0
self.window = window
self.window_bar = None
self.on_window_bar = on_window_bar
self.last_tick = None
self.last_bar = None
def update_tick(self, tick: TickData):
"""
@ -172,32 +184,60 @@ class BarGenerator:
"""
Update 1 minute bar into generator
"""
if not self.xmin_bar:
self.xmin_bar = BarData(
# If not inited, creaate window bar object
if not self.window_bar:
# Generate timestamp for bar data
if self.interval == Interval.MINUTE:
dt = bar.datetime.replace(second=0, microsecond=0)
else:
dt = bar.datetime.replace(minute=0, second=0, microsecond=0)
self.window_bar = BarData(
symbol=bar.symbol,
exchange=bar.exchange,
datetime=bar.datetime,
datetime=dt,
gateway_name=bar.gateway_name,
open_price=bar.open_price,
high_price=bar.high_price,
low_price=bar.low_price
)
# Otherwise, update high/low price into window bar
else:
self.xmin_bar.high_price = max(
self.xmin_bar.high_price, bar.high_price)
self.xmin_bar.low_price = min(
self.xmin_bar.low_price, bar.low_price)
self.window_bar.high_price = max(
self.window_bar.high_price, bar.high_price)
self.window_bar.low_price = min(
self.window_bar.low_price, bar.low_price)
self.xmin_bar.close_price = bar.close_price
self.xmin_bar.volume += int(bar.volume)
# Update close price/volume into window bar
self.window_bar.close_price = bar.close_price
self.window_bar.volume += int(bar.volume)
if not (bar.datetime.minute + 1) % self.xmin:
self.xmin_bar.datetime = self.xmin_bar.datetime.replace(
second=0, microsecond=0
)
self.on_xmin_bar(self.xmin_bar)
# Check if window bar completed
finished = False
self.xmin_bar = None
if self.interval == Interval.MINUTE:
# x-minute bar
if not (bar.datetime.minute + 1) % self.window:
finished = True
elif self.interval == Interval.HOUR:
if self.last_bar and bar.datetime.hour != self.last_bar.datetime.hour:
# 1-hour bar
if self.window == 1:
finished = True
# x-hour bar
else:
self.interval_count += 1
if not self.interval_count % self.window:
finished = True
self.interval_count = 0
if finished:
self.on_window_bar(self.window_bar)
self.window_bar = None
# Cache last bar object
self.last_bar = bar
def generate(self):
"""