VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 27
声望: 0
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
    super().__init__(cta_engine, strategy_name, vt_symbol, setting)

    # 创建5分钟K线合成器
    self.bg5 = BarGenerator(
        on_bar=self.on_bar,
        window=5,
        on_window_bar=self.on_5min_bar,
        interval=Interval.MINUTE
    )
    self.am5 = ArrayManager(size=100)  # 使用ArrayManager管理5分钟K线


tempam = self.am5
tempam.update_bar(self.bg5.bar)

    self.write_log(f"br0={self.bg5.bar.close_price}.BAR1={tempam.close_array[-2]},BAR2={tempam.close_array[-3]}")

    if self.am5 and self.bg5.bar:
        self.am5=self.am5[:-1] 


报错:

Traceback (most recent call last):
File ""D:\VeighNa_Studio\Lib\site-packages\vnpy_ctastrategy\engine.py"", line 613, in call_strategy_func
func(params)
~~^^^^^^^^
File ""D:\VeighNa_Studio\Lib\site-packages\vnpy_ctastrategy\strategies\my_strategy.py"", line 64, in on_tick
self.bg5.update_tick(tick)
~
~~~^^^^^^
File ""D:\VeighNa_Studio\Lib\site-packages\vnpy\trader\utility.py"", line 230, in update_tick
self.on_bar(self.bar)
~
~~^^^^^^^^^^
File ""D:\VeighNa_Studio\Lib\site-packages\vnpy_ctastrategy\strategies\my_strategy.py"", line 142, in on_bar
self.am5=self.am5[:-1]
~
~^^^^^
TypeError: 'ArrayManager' object is not subscriptable

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

你尝试对ArrayManager对象进行切片操作导致报错。ArrayManager本身不可直接切片,但可以通过其属性(如close_array)进行数组操作。

修改最后一行为:

self.am5.close_array = self.am5.close_array[:-1]

说明:

  1. ArrayManager对象包含close_array等属性用于存储具体数据
  2. 原始错误代码self.am5=self.am5[:-1]试图对整个对象切片,而ArrayManager未实现__getitem__方法
  3. 正确做法是直接操作其内部数组属性(如close_array

建议检查:

  • ArrayManager的其他数组属性(如open_array/high_array/low_array)
  • 是否需要同步更新其他技术指标计算
  • 数据截断对后续策略逻辑的影响
Member
avatar
加入于:
帖子: 27
声望: 0

VeighNa_AI wrote:

你尝试对ArrayManager对象进行切片操作导致报错。ArrayManager本身不可直接切片,但可以通过其属性(如close_array)进行数组操作。

修改最后一行为:

self.am5.close_array = self.am5.close_array[:-1]

说明:

  1. ArrayManager对象包含close_array等属性用于存储具体数据
  2. 原始错误代码self.am5=self.am5[:-1]试图对整个对象切片,而ArrayManager未实现__getitem__方法
  3. 正确做法是直接操作其内部数组属性(如close_array

建议检查:

  • ArrayManager的其他数组属性(如open_array/high_array/low_array)
  • 是否需要同步更新其他技术指标计算
  • 数据截断对后续策略逻辑的影响

非常感谢!又产生一个问题,发现aM 数列在莫名减少

def init(self, cta_engine, strategy_name, vt_symbol, setting):
super().init(cta_engine, strategy_name, vt_symbol, setting)

# 创建5分钟K线合成器
self.bg5 = BarGenerator(
    on_bar=self.on_bar,
    window=5,
    on_window_bar=self.on_5min_bar,
    interval=Interval.MINUTE
)
self.am5 = ArrayManager(size=15)  # 使用ArrayManager管理5分钟K线
self.hh_arry =[0.0]*10       # hh3
self.ll_arry =[0.0]*10       # hh3
self.top_arry =[0.0]*10       # hh3 
self.ma_arry =[0.0]*10       # hh3


def on_init(self):
"""策略初始化"""
self.write_log("策略初始化")
self.load_bar(5) # 加载10天历史数据

def on_stop(self):
"""策略停止"""
self.write_log("策略停止")

def on_tick(self, tick: TickData):
"""Tick数据更新"""
self.bg5.update_tick(tick)

def on_bar(self, bar: BarData):
"""1分钟K线更新"""
self.bg5.update_bar(bar)

    # 确保有足够数据计算
if not self.am5.inited:
    return

if self.bg5.bar is None:
    return
self.write_log(f" am={len(self.am5.high_array)}")  

tempam = self.am5
tempam.update_bar(self.bg5.bar)

try:
    self.write_log(f" tempam::{len(tempam.high_array)},am={len(self.am5.high_array)}")  
except:
     self.write_log(f"tempam is。。。 None")   

if len(tempam.high_array)<5:
    return
self.write_log(f"begin={self.am5.high_array[-1]}.HH1={self.am5.high_array[-2]},HH2={self.am5.high_array[-3]}") 
self.write_log(f"beginHH={tempam.high_array[-1]}.HH1={tempam.high_array[-2]},HH2={tempam.high_array[-3]}")      

if len(self.hh_arry)<3:
    return
self.write_log(f"HH{self.hh_arry[-1]}.HH1={self.hh_arry[-2]},HH2={self.hh_arry[-3]}") 
    self.write_log(f"A++HH={self.hh_arry[-1]}.HH1={self.hh_arry[-2]},HH2={self.hh_arry[-3]}") 
    if self.bg5.bar:
        self.am5.close_array=self.am5.close_array[:-1]
        self.am5.open_array=self.am5.open_array[:-1]
        self.am5.high_array=self.am5.high_array[:-1]
        self.am5.low_array=self.am5.low_array[:-1]
        self.am5.turnover_array=self.am5.turnover_array[:-1]
        self.am5.volume_array=self.am5.volume_array[:-1]
        self.am5.open_interest_array=self.am5.open_interest_array[:-1]

def on_5min_bar(self, bar: BarData):
"""5分钟K线更新"""

# 新K线开始时重置交易标志
if self.last_bar_time != bar.datetime:
    self.can_trade = True
    self.last_bar_time = bar.datetime

# 更新5分钟K线数据
self.am5.update_bar(bar)



self.put_event()
Member
avatar
加入于:
帖子: 27
声望: 0

输出日志显示:LEN(AM)不断减小

09:12:01.277,[ag] am=4
09:11:02.281,"[ag] tempam::4,am=4"
09:11:02.281,[ag] am=4
09:10:00.275,"[ag] tempam::4,am=4"
09:10:00.275,[ag] am=4
09:10:00.275,"[ag] HH=8896.0.HH1=8895.666666666666,HH2=8896.0"
09:10:00.275,"[ag] 5_min=: 8895.666666666666,am len=: 4 ,2025-06-11 09:05:00+08:00"
09:09:00.769,"[ag] pop HH=8895.666666666666.HH1=8896.0,HH2=8894.333333333334"
09:09:00.769,"[ag] A++HH=8895.666666666666.HH1=8896.0,HH2=8894.333333333334"
09:09:00.769,"[ag] HH8896.0.HH1=8894.333333333334,HH2=8894.0"
09:09:00.769,"[ag] beginHH=8909.0.HH1=8902.0,HH2=8876.0"
09:09:00.769,"[ag] begin=8909.0.HH1=8902.0,HH2=8876.0"
09:09:00.769,"[ag] tempam::5,am=5"
09:09:00.769,[ag] am=5
09:08:00.271,"[ag] pop HH=8896.0.HH1=8894.333333333334,HH2=8894.0"
09:08:00.271,"[ag] A++HH=8896.0.HH1=8894.333333333334,HH2=8894.0"
09:08:00.271,"[ag] HH8894.333333333334.HH1=8894.0,HH2=8892.0"
09:08:00.271,"[ag] beginHH=8910.0.HH1=8902.0,HH2=8876.0"
09:08:00.271,"[ag] begin=8910.0.HH1=8902.0,HH2=8876.0"
09:08:00.271,"[ag] tempam::6,am=6"
09:08:00.271,[ag] am=6
09:07:01.774,"[ag] pop HH=8894.333333333334.HH1=8894.0,HH2=8892.0"
09:07:01.774,"[ag] A++HH=8894.333333333334.HH1=8894.0,HH2=8892.0"
09:07:01.774,"[ag] HH8894.0.HH1=8892.0,HH2=8885.666666666666"
09:07:01.774,"[ag] beginHH=8905.0.HH1=8902.0,HH2=8876.0"
09:07:01.774,"[ag] begin=8905.0.HH1=8902.0,HH2=8876.0"
09:07:01.774,"[ag] tempam::7,am=7"
09:07:01.774,[ag] am=7
09:06:00.266,"[ag] pop HH=8894.0.HH1=8892.0,HH2=8885.666666666666"
09:06:00.266,"[ag] A++HH=8894.0.HH1=8892.0,HH2=8885.666666666666"
09:06:00.266,"[ag] HH8892.0.HH1=8885.666666666666,HH2=8884.0"
09:06:00.266,"[ag] beginHH=8904.0.HH1=8902.0,HH2=8876.0"
09:06:00.266,"[ag] begin=8904.0.HH1=8902.0,HH2=8876.0"
09:06:00.266,"[ag] tempam::8,am=8"
09:06:00.266,[ag] am=8
09:05:00.261,"[ag] pop HH=8892.0.HH1=8885.666666666666,HH2=8884.0"
09:05:00.261,"[ag] A++HH=8892.0.HH1=8885.666666666666,HH2=8884.0"
09:05:00.261,"[ag] HH8885.666666666666.HH1=8884.0,HH2=8884.0"
09:05:00.261,"[ag] beginHH=8898.0.HH1=8902.0,HH2=8876.0"
09:05:00.261,"[ag] begin=8898.0.HH1=8902.0,HH2=8876.0"
09:05:00.261,"[ag] tempam::9,am=9"
09:05:00.261,[ag] am=9
09:05:00.261,"[ag] HH=8885.666666666666.HH1=8884.0,HH2=8884.0"
09:05:00.261,"[ag] 5_min=: 8884.0,am len=: 9 ,2025-06-11 09:00:00+08:00"
09:04:00.282,"[ag] pop HH=8884.0.HH1=8884.0,HH2=8885.333333333334"
09:04:00.282,"[ag] A++HH=8884.0.HH1=8884.0,HH2=8885.333333333334"
09:04:00.282,"[ag] HH8884.0.HH1=8885.333333333334,HH2=8885.666666666666"
09:04:00.282,"[ag] beginHH=8897.0.HH1=8876.0,HH2=8879.0"
09:04:00.282,"[ag] begin=8897.0.HH1=8876.0,HH2=8879.0"
09:04:00.282,"[ag] tempam::10,am=10"
09:04:00.282,[ag] am=10
09:03:01.258,"[ag] pop HH=8884.0.HH1=8885.333333333334,HH2=8885.666666666666"
09:03:01.258,"[ag] A++HH=8884.0.HH1=8885.333333333334,HH2=8885.666666666666"
09:03:01.258,"[ag] HH8885.333333333334.HH1=8885.666666666666,HH2=8876.0"
09:03:01.258,"[ag] beginHH=8897.0.HH1=8876.0,HH2=8879.0"
09:03:01.258,"[ag] begin=8897.0.HH1=8876.0,HH2=8879.0"
09:03:01.258,"[ag] tempam::11,am=11"
09:03:01.258,[ag] am=11
09:02:00.276,"[ag] pop HH=8885.333333333334.HH1=8885.666666666666,HH2=8876.0"
09:02:00.276,"[ag] A++HH=8885.333333333334.HH1=8885.666666666666,HH2=8876.0"
09:02:00.276,"[ag] HH8885.666666666666.HH1=8876.0,HH2=8877.666666666666"
09:02:00.276,"[ag] beginHH=8901.0.HH1=8876.0,HH2=8879.0"
09:02:00.276,"[ag] begin=8901.0.HH1=8876.0,HH2=8879.0"
09:02:00.276,"[ag] tempam::12,am=12"
09:02:00.276,[ag] am=12
09:01:00.276,"[ag] pop HH=8885.666666666666.HH1=8876.0,HH2=8877.666666666666"
09:01:00.276,"[ag] A++HH=8885.666666666666.HH1=8876.0,HH2=8877.666666666666"
09:01:00.276,"[ag] HH8876.0.HH1=8877.666666666666,HH2=8877.666666666666"
09:01:00.276,"[ag] beginHH=8902.0.HH1=8876.0,HH2=8879.0"
09:01:00.276,"[ag] begin=8902.0.HH1=8876.0,HH2=8879.0"
09:01:00.276,"[ag] tempam::13,am=13"
09:01:00.276,[ag] am=13
09:00:10.975,"[ag] pop HH=8876.0.HH1=8877.666666666666,HH2=8877.666666666666"
09:00:10.975,"[ag] A++HH=8876.0.HH1=8877.666666666666,HH2=8877.666666666666"
09:00:10.975,"[ag] HH8877.666666666666.HH1=8877.666666666666,HH2=8879.0"
09:00:10.975,"[ag] beginHH=8873.0.HH1=8876.0,HH2=8879.0"
09:00:10.975,"[ag] begin=8873.0.HH1=8876.0,HH2=8879.0"
09:00:10.975,"[ag] tempam::14,am=14"
09:00:10.975,[ag] am=14
09:00:10.975,"[ag] HH=8877.666666666666.HH1=8877.666666666666,HH2=8879.0"
09:00:10.975,"[ag] 5_min=: 8877.666666666666,am len=: 14 ,2025-06-11 07:35:00+08:00"
08:59:00.768,"[ag] pop HH=8877.666666666666.HH1=8879.0,HH2=8880.333333333334"
08:59:00.768,"[ag] A++HH=8877.666666666666.HH1=8879.0,HH2=8880.333333333334"
08:59:00.768,"[ag] HH8879.0.HH1=8880.333333333334,HH2=8883.0"
08:59:00.768,"[ag] beginHH=8876.0.HH1=8879.0,HH2=8878.0"
08:59:00.768,"[ag] begin=8876.0.HH1=8879.0,HH2=8878.0"
08:59:00.768,"[ag] tempam::15,am=15"
08:59:00.768,[ag] am=15

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

根据你的代码和描述,问题出在 手动修改 ArrayManager 的内部数组属性(如 close_arrayhigh_array 等),这会破坏 ArrayManager 的自动管理机制。以下是详细分析和解决方案:


一、问题根源分析

  1. ArrayManager 的设计原则
    ArrayManager 的核心功能是自动维护固定长度的时间序列数据(默认长度 100),通过 update_bar 方法自动更新数据并保持数组长度不变。

    • 每次调用 update_bar(bar) 时,ArrayManager 会将新 K 线数据追加到数组末尾,并移除最早的一条数据(FIFO 原则)。
    • 手动修改 close_arrayhigh_array 等属性(如 self.am5.close_array[:-1])会直接破坏这种自动管理机制,导致数组长度异常减少。
  2. 代码中的错误操作
    on_bar 方法中,你执行了以下操作:

    self.am5.close_array = self.am5.close_array[:-1]
    self.am5.open_array = self.am5.open_array[:-1]
    # ... 其他数组截断操作
    

    这些操作会直接截断 ArrayManager 的内部数组,导致数据丢失和长度减少。ArrayManager 的数组属性(如 close_array)本质上是 NumPy 数组,切片操作会生成新数组,但 ArrayManager 无法感知这种外部修改,从而导致状态不一致。


二、解决方案

1. 移除手动截断代码

删除 on_bar 中所有对 close_arrayhigh_array 等属性的直接修改操作。ArrayManager 会自动管理数组长度,无需手动干预。
修改后的代码应如下:

def on_bar(self, bar: BarData):
       """1分钟K线更新"""
       self.bg5.update_bar(bar)

       if not self.am5.inited:
           return

       # 更新 ArrayManager
       tempam = self.am5
       tempam.update_bar(self.bg5.bar)

       # 直接使用 ArrayManager 提供的方法计算指标,无需手动截断
       if len(tempam.high_array) < 5:
           return

       self.write_log(f"begin={tempam.high_array[-1]}, HH1={tempam.high_array[-2]}, HH2={tempam.high_array[-3]}")

2. 正确使用 ArrayManager 的方法

ArrayManager 提供了丰富的内置方法(如 smaemaboll 等)用于计算技术指标,无需直接操作数组。例如:

# 计算 5 日简单移动平均线
   sma_value = tempam.sma(window=5)

3. 确保 update_bar 调用次数与数据流一致

  • on_bar 中调用 tempam.update_bar(self.bg5.bar) 后,不要在 on_5min_bar 中重复调用 self.am5.update_bar(bar),否则会导致数据重复更新。
  • 如果需要同时处理 1 分钟和 5 分钟 K 线,应确保 BarGeneratorArrayManager 的层级关系正确:

    def __init__(self, ...):
        # 1 分钟 K 线合成器
        self.bg1 = BarGenerator(on_bar=self.on_bar)
        # 5 分钟 K 线合成器
        self.bg5 = BarGenerator(
            on_bar=self.on_5min_bar,
            window=5,
            interval=Interval.MINUTE
        )
        # ArrayManager 用于管理 1 分钟 K 线
        self.am1 = ArrayManager(size=100)
        # ArrayManager 用于管理 5 分钟 K 线
        self.am5 = ArrayManager(size=100)
    
    def on_bar(self, bar: BarData):
        """1分钟K线更新"""
        self.bg5.update_bar(bar)  # 推送至 5 分钟合成器
        self.am1.update_bar(bar)  # 更新 1 分钟 ArrayManager
    
    def on_5min_bar(self, bar: BarData):
        """5分钟K线更新"""
        self.am5.update_bar(bar)  # 更新 5 分钟 ArrayManager
    

三、验证修复

  1. 日志输出检查
    on_baron_5min_bar 中添加日志,确认 ArrayManager 的数组长度是否稳定:

    self.write_log(f"Array length: {len(self.am5.high_array)}")
    

    正常情况下,数组长度应稳定在 size 参数指定的值(如 100)。

  2. 指标计算验证
    使用 ArrayManager 的内置方法计算指标(如 smaboll),确保结果符合预期。


四、注意事项

  • 避免直接操作数组属性:ArrayManager 的 close_arrayhigh_array 等属性应视为只读,任何修改都应通过 update_bar 方法完成。
  • 保持数据流一致性:确保 BarGeneratorArrayManager 的层级关系正确,避免重复更新或遗漏数据。
  • 合理设置 ArrayManager 长度size 参数应大于等于所需计算指标的最大周期(如计算 100 日均线时,size 至少为 100)。

通过以上修改,ArrayManager 的数组长度问题应得到解决。如果仍有疑问,请提供完整的策略代码片段以便进一步分析。

Member
avatar
加入于:
帖子: 27
声望: 0

非常感谢楼上的耐心讲解!

我现在面临的问题是:
在on_bar 中执行

更新 ArrayManager

   tempam = self.am5
   tempam.update_bar(self.bg5.bar)

如果不删除 on_bar 中所有对 close_array、high_array 等属性的直接修改操作,则5分钟周期内会产生5根5分钟的 am5 K线
正常应该是1根
如果 删除,则出现am5 数据不断减少的局面。这个困境难两全

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

沪公网安备 31011502017034号

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