VNPY使用记录(3)--多周期bar合成策略

背景

vnpy官方不支持多周期复合策略,所以在不修改官方源码的情况下,无法实现通过分钟线、日线编写复杂的策略。下面修改vnpy,通过1m线合成 30m(可配置,window_mn), 1d线, 并完成三个策略

实现

30分钟线的实现:

BarGenerator有参数可以实现n分钟bar的更新和回调

:param on_bar: 1分钟回调
:param window: n分钟窗口大小, n必须可以被60整除2, 3, 5, 6, 10, 15, 20, 30
:param on_window_bar: n分钟回调
:param interval:默认是分钟

日线实现

  • BarGenerator增加一个方法update_bar_day_window, 增加一个属性 day_bar存储更新中的bar

  • 由于有夜盘的情况,夜盘属于下一个交易日的行情,所以,以每天15:00为界限,将完成的bar传递给回调函数 on_window_bar, 然后将 day_bar重新设置为None

  • 已经完成的bar的日期统一改成 15:00分钟bar的日期,不带时间、分钟、秒

策略代码

from vnpy.app.cta_strategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
)
from vnpy.trader.constant import Exchange, Interval
 
 
class DoubleDayM30M1Strategy(CtaTemplate):
    """
    使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略
    """
    author = "fsksf"
    window_mn = 30              # n分钟线
    fast_window_day = 3
    fast_window_m30 = 3
    fast_window_m1 = 3
    slow_window_day = 5
    slow_window_m30 = 5
    slow_window_m1 = 5
 
    fast_ma_day = 0.0
    fast_ma_m30 = 0.0
    fast_ma_m1 = 0.0
 
    slow_ma_day = 0.0
    slow_ma_m30 = 0.0
    slow_ma_m1 = 0.0
 
    parameters = ["fast_window_day", "fast_window_m30", "fast_window_m1",
                  "slow_window_day", "slow_window_m30", "slow_window_m1",
                  "window_mn"]
    variables = ["fast_ma_day", "slow_ma_day",
                 "fast_ma_m30", "slow_ma_m30",
                 "fast_ma_m1", "slow_ma_m1"]
 
    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
 		# daybar 生成器
        self.day_bar_gen = BarGenerator(lambda x: None, interval=Interval.DAILY, window=1, on_window_bar=self.on_day_bar)
        self.m30_bar_gen = BarGenerator(self.on_bar, interval=Interval.MINUTE, window=self.window_mn, on_window_bar=self.on_m30_bar)
        self.day_am = ArrayManager(size=self.slow_window_day+1)
        self.m30_am = ArrayManager(size=self.slow_window_m30+1)
        self.m1_am = ArrayManager(size=self.slow_window_m1+1)
 
    def on_m30_bar(self, bar):
        self.m30_am.update_bar(bar)
 
    def on_day_bar(self, bar):
        print(bar.__dict__)
        self.day_am.update_bar(bar)
 
    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(100)
 
    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()
 
    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
 
        self.put_event()
 
    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.m30_bar_gen.update_tick(tick)
 
    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        # if self.cta_engine.gateway_name == "BACKTESTING":
        # update window
        self.m30_bar_gen.update_bar(bar)
        self.day_bar_gen.update_bar(bar)
        self.m1_am.update_bar(bar)
        if not (self.day_am.inited and self.m30_am.inited and self.m1_am.inited):
            return
 
        # 最后一个bar实时更新的,计算ma后删除
        # self.day_am.update_bar(self.day_bar_gen.last_bar)
        fast_ma_day = self.day_am.sma(self.fast_window_day, array=True)
        slow_ma_day = self.day_am.sma(self.slow_window_day, array=True)
 
        # self.m30_am.update_bar(self.m30_bar_gen.last_bar)
        fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True)
        slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True)
 
        fast_ma_m1 = self.m1_am.sma(self.fast_window_m1, array=True)
        slow_ma_m1 = self.m1_am.sma(self.slow_window_m1, array=True)
 
        self.fast_ma_day = fast_ma_day[-1]
        self.fast_ma_m30 = fast_ma_m30[-1]
        self.fast_ma_m1 = fast_ma_m1[-1]
 
        self.slow_ma_day = slow_ma_day[-1]
        self.slow_ma_m30 = slow_ma_m30[-1]
        self.slow_ma_m1 = slow_ma_m1[-1]
 
        cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \
            fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] and \
            fast_ma_m1[-2] < slow_ma_m1[-2] and fast_ma_m1[-1] > slow_ma_m1[-1]
        cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \
            fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] and \
            fast_ma_m1[-2] > slow_ma_m1[-2] and fast_ma_m1[-1] < slow_ma_m1[-1]
 
        if cross_over:
            self.write_log(f'触发买入:{str(bar.datetime)}')
            # print(f'触发买入:{str(bar.datetime)}')
            self.write_log(f'day: ma_fast: {fast_ma_day[-2:]}, slow: {slow_ma_day[-2:]} close_price: {self.day_am.close_array}')
            self.write_log(f'30m: ma_fast: {fast_ma_m30[-2:]}, slow: {slow_ma_m30[-2:]} close_price: {self.m30_am.close_array}')
            self.write_log(f'1m: ma_fast: {fast_ma_m1[-2:]}, slow: {slow_ma_m1[-2:]} close_price: {self.m1_am.close_array}')
            if self.pos == 0:
                self.buy(bar.close_price, 1)
            elif self.pos < 0:
                self.cover(bar.close_price, 1)
                self.buy(bar.close_price, 1)
 
        elif cross_below:
            if self.pos == 0:
                self.short(bar.close_price, 1)
            elif self.pos > 0:
                self.sell(bar.close_price, 1)
                self.short(bar.close_price, 1)
 
        # self.day_am.remove_last_bar()
        # self.m30_am.remove_last_bar()
 
        self.put_event()
 
    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass
 
    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()
 
    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值