Skip to content

fix: SEL生产引擎读取K线接口参数序列错位, 取数恒为空或访问越界 - #178

Open
xukanshan wants to merge 6 commits into
wondertrader:devfrom
xukanshan:pr-fix-sel-get-bars-ismain
Open

fix: SEL生产引擎读取K线接口参数序列错位, 取数恒为空或访问越界#178
xukanshan wants to merge 6 commits into
wondertrader:devfrom
xukanshan:pr-fix-sel-get-bars-ismain

Conversation

@xukanshan

Copy link
Copy Markdown

问题背景:
SEL策略通过SelContext.stra_get_bars/stra_prepare_bars获取K线,底层经
WtWrapper.sel_get_bars调用porter导出函数。porter导出的sel_get_bars为5参数
签名(id, code, period, count, 回调),不含isMain——SEL接口无主K线概念;
而回测端WtBtWrapper.sel_get_bars同样为4参签名。

问题表现:
生产SEL引擎下策略读取任何标的的K线均失败,且存在两种故障形态:

  1. 默认调用链抛TypeError(sel_get_bars missing 1 required positional
    argument: 'isMain'),被策略侧异常处理吞掉后表现为所有标的无数据、
    选股结果恒为空;
  2. 一旦按生产wrapper签名传入isMain,布尔实参在C调用约定下错位到回调
    指针形参位,触发access violation读写异常。

问题原因:
porter导出函数、生产版WtWrapper、回测版WtBtWrapper三层对isMain的约定
互不一致:WtWrapper多出一个porter不支持的形参,SelContext又完全未传,
任何一条路径都无法同时满足三层的期望。

问题修复:

  • SelContext.stra_get_bars/stra_prepare_bars补充isMain可选参数(默认False),
    内部按wrapper签名探测(_sel_bars_wants_ismain)自动适配生产/回测两端;
  • WtWrapper.sel_get_bars

copy_bins_win.bat 运行后会在 wtpy/wrapper 目录生成大量 *.dll 动态库构建产物。这些二进制文件此前被 git 追踪,每次构建都会导致仓库出现大量修改,且二进制文件不宜入库。

本次修改在 .gitignore 中新增 *.dll 忽略规则,并通过 git rm --cached 将这些已追踪的 .dll 从索引中移除(保留工作区文件),彻底停止追踪,避免日后误提交。
【问题背景】
wtpy 在Windows平台下通过 PlatformHelper.auto_encode 对所有日志消息做编码转换,
该函数是控制台日志乱码问题的唯一字节出口(策略日志/引擎日志均经由此函数)。

【问题表现】
在现代终端(Windows Terminal / VS Code / opencode CLI 等, 默认UTF-8解码)中运行,
控制台中文全部显示为乱码(如 �ֲ�ӯ��:0.0), 英文正常。

【问题原因】
auto_encode 的Windows分支将消息强制转为GBK字节:
    bytes(s, encoding=utf-8).decode(utf-8).encode(gbk)
这是为传统cmd(代码页936)设计的兼容逻辑。UTF-8终端按UTF-8解码GBK字节必然乱码;
英文为纯ASCII, 两种编码字节相同所以不受影响。而引擎日志文件本身以UTF-8写入,
GBK转换仅影响控制台路径, 无存在必要。

【问题修复】
删除平台分支判断, Windows与Linux统一直接返回UTF-8字节流:
    return bytes(s, encoding=utf-8)
若需在传统cmd(代码页936)下查看, 先执行 chcp 65001 切换终端到UTF-8即可。
【问题背景】
实盘/仿真引擎通过WtWrapper注册扩展数据加载器(BaseExtDataLoader),
C++侧在K线初始化时经FUNC_LOAD_HISBARS回调Python层获取历史数据,
该回调签名在WtCoreDefs.py中定义为CFUNCTYPE(c_bool, c_char_p, c_char_p)。

【问题表现】
实盘引擎下通过 load_final_his_bars / load_raw_his_bars 提供的历史数据
始终加载失败, 引擎反复回退到其他数据源; 相同的加载器与配置在回测下正常。

【问题原因】
WtWrapper.on_load_fnl_his_bars 与 on_load_raw_his_bars 调用loader后
漏写return, 函数返回None。ctypes的CFUNCTYPE(c_bool, ...)回调会把None
自动折叠为False传给C++侧, 导致cacheFinalBarsFromLoader永远判定加载失败。
对照实现: 回测版WtBtWrapper同名回调带显式return, 故回测不受影响。

【问题修复】
与回测版对齐, 两个回调补写return并标注 -> bool 返回类型注解:
    return loader.load_final_his_bars(...)
    return loader.load_raw_his_bars(...)
【问题背景】
实盘引擎经 WtEngine.add_exetended_parser 注册 BaseExtParser 扩展行情解析器。
底层 create_ext_parser 内部 ParserAdapter.initExt 会同步执行 parser->init(NULL)
并触发 EVENT_PARSER_INIT 事件回调, Python侧 WtWrapper.on_parser_event 收到该
事件后经 engine.get_extended_parser(id) 查字典找到parser并调用 parser.init(engine),
后者负责把engine赋给 parser.__engine__。

【问题表现】
注册完成后解析器内部的 __engine__ 始终为 None,
push_quote_from_extended_parser 等依赖该引用的链路全部失效,
扩展解析器的行情数据无法推进引擎。

【问题原因】
原实现顺序颠倒: 先调用 __wrapper__.create_extended_parser(id) 向底层注册并同步
触发 INIT 回调, 之后才把 parser 存入自身 __ext_parsers__ 字典。回调先于入字典
发生, get_extended_parser 查询扑空直接return, parser.init(engine) 从未执行。
对照实现: WtDtEngine.add_exetended_parser 数据引擎版即为正确的先入字典顺序。

【问题修复】
对齐WtDtEngine的已验证写法, 调整为: 先将parser存入__ext_parsers__,
再向底层create_extended_parser, 创建失败时从字典移除兜底:
    self.__ext_parsers__[id] = parser
    if not self.__wrapper__.create_extended_parser(id):
        self.__ext_parsers__.pop(id)
问题背景:
SEL策略通过SelContext.stra_get_bars/stra_prepare_bars获取K线,底层经
WtWrapper.sel_get_bars调用porter导出函数。porter导出的sel_get_bars为5参数
签名(id, code, period, count, 回调),不含isMain——SEL接口无主K线概念;
而回测端WtBtWrapper.sel_get_bars同样为4参签名。

问题表现:
生产SEL引擎下策略读取任何标的的K线均失败,且存在两种故障形态:
1) 默认调用链抛TypeError(sel_get_bars missing 1 required positional
   argument: 'isMain'),被策略侧异常处理吞掉后表现为所有标的无数据、
   选股结果恒为空;
2) 一旦按生产wrapper签名传入isMain,布尔实参在C调用约定下错位到回调
   指针形参位,触发access violation读写异常。

问题原因:
porter导出函数、生产版WtWrapper、回测版WtBtWrapper三层对isMain的约定
互不一致:WtWrapper多出一个porter不支持的形参,SelContext又完全未传,
任何一条路径都无法同时满足三层的期望。

问题修复:
- SelContext.stra_get_bars/stra_prepare_bars补充isMain可选参数(默认False),
  内部按wrapper签名探测(_sel_bars_wants_ismain)自动适配生产/回测两端;
- WtWrapper.sel_get_bars的isMain改为默认参数且不再向porter透传,
  仅保留形参做兼容。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant