VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 1
声望: 0

多信号在实务中应该是很常用的,很多时候是多个信号叠加,才确定交易信号。
但MultiSignalStrategy的模版,我发现每个信号都各自on_tick和on_bar,都要运行bg和am,如果各信号的周期数据一样的时候,可以共享tick和bar,就不用每个信号都额外做一次,但这样感觉又不便于代码更新和修改,是否有其他模版或建议适用多信号呢?

Super Moderator
avatar
加入于:
帖子: 77
声望: 8

在多信号策略中,确实存在多个信号各自处理 on_tickon_bar 的情况,这会导致重复计算和资源浪费,尤其是在各信号的周期数据相同时。针对这个问题,以下是一些优化建议和解决方案:


1. 共享 BarGeneratorArrayManager

  • 优化思路:如果多个信号使用相同的 K 线周期,可以共享 BarGeneratorArrayManager,避免重复计算。
  • 实现方法

    • 在主策略中初始化一个 BarGeneratorArrayManager
    • on_tickon_bar 中统一处理数据,然后将处理后的数据分发给各个信号。
    • 示例代码:

      class MultiSignalStrategy(TargetPosTemplate):
          def __init__(self):
              super().__init__()
              # 共享的 BarGenerator 和 ArrayManager
              self.bg = BarGenerator(self.on_bar)
              self.am = ArrayManager()
      
              # 初始化信号
              self.rsi_signal = RsiSignal()
              self.cci_signal = CciSignal()
              self.ma_signal = MaSignal()
      
          def on_tick(self, tick: TickData):
              # 统一处理 Tick 数据
              self.bg.update_tick(tick)
      
          def on_bar(self, bar: BarData):
              # 统一处理 Bar 数据
              self.am.update_bar(bar)
              if not self.am.inited:
                  return
      
              # 将数据分发给各个信号
              self.rsi_signal.on_bar(bar, self.am)
              self.cci_signal.on_bar(bar, self.am)
              self.ma_signal.on_bar(bar, self.am)
      
              # 计算目标仓位
              self.calculate_target_pos()
      

2. 信号类优化

  • 优化思路:将信号类的 on_tickon_bar 方法改为接收主策略传递的数据,而不是自己处理。
  • 实现方法
    • 在信号类中移除 BarGeneratorArrayManager,改为接收主策略传递的 BarDataArrayManager
    • 示例代码:
      class RsiSignal:
          def on_bar(self, bar: BarData, am: ArrayManager):
              # 使用主策略传递的 ArrayManager 计算 RSI
              rsi_value = am.rsi(self.rsi_window)
              # 生成信号
              if rsi_value >= self.rsi_long:
                  self.set_signal_pos(1)
              elif rsi_value <= self.rsi_short:
                  self.set_signal_pos(-1)
              else:
                  self.set_signal_pos(0)
      

3. 使用事件驱动机制

  • 优化思路:通过事件驱动机制,在主策略中统一处理数据,然后触发事件通知各个信号。
  • 实现方法

    • 在主策略中定义事件,当 on_bar 数据更新时触发事件。
    • 各个信号类监听事件,接收到事件后执行信号计算。
    • 示例代码:

      from vnpy.event import Event, EventEngine
      
      class BarUpdateEvent(Event):
          def __init__(self, bar: BarData, am: ArrayManager):
              super().__init__("BAR_UPDATE")
              self.bar = bar
              self.am = am
      
      class MultiSignalStrategy(TargetPosTemplate):
          def __init__(self, event_engine: EventEngine):
              super().__init__()
              self.event_engine = event_engine
              self.bg = BarGenerator(self.on_bar)
              self.am = ArrayManager()
      
          def on_bar(self, bar: BarData):
              self.am.update_bar(bar)
              if not self.am.inited:
                  return
      
              # 触发事件
              event = BarUpdateEvent(bar, self.am)
              self.event_engine.put(event)
      
      class RsiSignal:
          def __init__(self, event_engine: EventEngine):
              event_engine.register("BAR_UPDATE", self.on_bar_update)
      
          def on_bar_update(self, event: BarUpdateEvent):
              bar = event.bar
              am = event.am
              # 计算 RSI 信号
              rsi_value = am.rsi(self.rsi_window)
              # 生成信号
              if rsi_value >= self.rsi_long:
                  self.set_signal_pos(1)
              elif rsi_value <= self.rsi_short:
                  self.set_signal_pos(-1)
              else:
                  self.set_signal_pos(0)
      

4. 使用策略组合模式

  • 优化思路:将每个信号封装为独立的策略,然后通过组合模式将多个策略组合在一起。
  • 实现方法

    • 每个信号类继承 CtaTemplate,独立处理数据。
    • 在主策略中管理多个子策略,汇总信号结果。
    • 示例代码:

      class MultiSignalStrategy(TargetPosTemplate):
          def __init__(self):
              super().__init__()
              self.rsi_strategy = RsiStrategy()
              self.cci_strategy = CciStrategy()
              self.ma_strategy = MaStrategy()
      
          def on_bar(self, bar: BarData):
              # 分发给子策略
              self.rsi_strategy.on_bar(bar)
              self.cci_strategy.on_bar(bar)
              self.ma_strategy.on_bar(bar)
      
              # 汇总信号
              target_pos = (
                  self.rsi_strategy.get_signal_pos() +
                  self.cci_strategy.get_signal_pos() +
                  self.ma_strategy.get_signal_pos()
              )
              self.set_target_pos(target_pos)
      

总结

在多信号策略中,可以通过以下方式优化:

  1. 共享 BarGeneratorArrayManager,避免重复计算。
  2. 优化信号类,使其接收主策略传递的数据。
  3. 使用事件驱动机制,统一处理数据并通知信号。
  4. 使用策略组合模式,将每个信号封装为独立策略。

根据实际需求和代码复杂度,选择最适合的优化方案。如果信号数量较多且逻辑复杂,建议使用事件驱动机制或策略组合模式,以提高代码的可维护性和扩展性。

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】