Files
big-qmt/py-client/strategy/etf
2026-09-17 00:56:05 +08:00
..
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00
2026-09-17 00:56:05 +08:00

A 股 ETF 自适应网格策略

策略目录为 py-client/strategy/etf,入口名称 etf,独立配置为 py-client/etc/etf.yaml。每只 ETF 总持仓上限 10 手1000 份),默认每次买入 1 手。 这是常见均值回归与波动率网格方法的工程组合,尚未完成历史收益回测。

方法分析

方法 优点 局限 本策略选择
固定价差网格 简单直观 不适应不同价格与波动率 ATR 动态格距,设置百分比下限
均线回归 提供相对高低位置 单边下跌中均线会滞后 MA60 作中轴,设置仓位上限
BOLL 低吸 用价格分布寻找相对低位 触及下轨不代表跌势结束 下轨仅启动观察,反弹后再买
回撤止盈 上涨时跟随峰值 不能保证最高价退出 复用现有 GridTrailingTracker

ATR 反映波动幅度不判断方向BOLL 为均线加减标准差倍数。定义参考 Fidelity ATRFidelity BOLL。 默认参数是可调整的起点,不代表已经优化或保证收益。

指标与网格

历史日线直接读取 http://go.apinb.com/a/get_daily?code=<证券代码>,使用响应 details 中的 ts_code / trade_date / open / high / low / close。校验 code=0、 证券归属、日期和 OHLC 后,按日期排序,排除当天及未来数据,再取最近 120 根。 每个标的每天计算一次并缓存,至少需要 60 根ATR 周期为 60 时至少需要 61 根。 接口样本未声明复权口径,策略使用接口原始价格,不自行假定或执行前复权。

  • M = 最近60根收盘价平均值,固定 MA60。
  • TR = max(最高-最低, abs(最高-前收盘), abs(最低-前收盘))
  • ATR 默认 14 日:前 14 个 TR 平均作初值,后续按 ATR = (前ATR × 13 + 当日TR) / 14 进行 Wilder 平滑。
  • BOLL 默认 20 日、2 倍总体标准差:中轨=MA20上下轨=MA20 ± 2σ
  • 格距 G = max(ATR × atr_multiplier, M × min_grid_pct / 100, 0.001) 向上取整至 0.001 元。均线作中轴ATR 决定每格宽度。

重复日期、非正数或非有限价格、价格关系异常、日线不足均不交易。 最后日线超过 15 个自然日也不交易;该检查只排除明显过期,不能替代交易所日历。 接口数据应更新至上一交易日。获取失败的标的每 5 分钟重试。

买入规则

  1. 首仓在 现价 <= min(BOLL下轨, M-G) 时开始观察,不直接买入。
  2. 复用 DipWatch 防接飞刀:下跌刷新低点,从低点反弹默认 0.61% 后触发; 观察默认 600 秒过期重置。反弹可站回下轨上方,但不能超过 MA60。
  3. 加仓还须满足 现价 <= 上次实际买入成交均价-G,防止同价位连续补满。 初次接管已有仓位时,券商成本作为初始加仓基准。
  4. 每次买入 buy_hands × 100 份;若买后超过 max_hands × 100,整笔跳过, 不临时缩量。配置强制 1 <= buy_hands <= max_hands <= 10
  5. 买入预算为券商可用资金减账户现金安全线,再减所有本地待确认买单。 限价金额加预估佣金占用预算,多标的串行扣减。

示例MA60=4.00、G=0.05、下轨=3.90,价格进入 3.90 以下才观察;低点 3.88 反弹至 3.904 时超过 0.61%,可以提交固定手数。如果实际均价为 3.904 下一笔最高买价为 3.854,同时仍须满足低位触发和反弹确认。

止盈规则

  1. 现价 >= max(BOLL上轨, M+G, 成本+G),且满足 min_profit_pct、 预估价差收益大于买卖两侧佣金,才启动高位跟踪。
  2. 启动时冻结格距。盈利格编号为 floor((现价-成本)/冻结格距),复用 GridTrailingTracker 记录最高格;进入更高格更新峰值,跌回较低格时止盈。 这是跌破峰值格边界,不是从最高价回撤完整一个 ATR。
  3. 启动后,即使回落到 BOLL 上轨或启动价以下,也继续判断回撤;卖出时仍须满足 最低利润和费用门槛。止盈启动后暂停补仓,不同时发买卖单。
  4. 固定手数用于买入;止盈卖出当前全部可用整手份额,数量为 min(持仓, 券商可卖数量) 向下取整到 100 份。零股暂不处理。
  5. T+1 当天不可卖时继续记录峰值,翌日按券商 can_use_volume 判断。 清仓、实际成交改变仓位、外部数量或成本变化后重建基准;部分卖出后剩余仓位 重新等待高位启动,不把旧峰值带入新仓。

交易单位、0.001 元报价精度及股票 ETF 的 T+1 参考 上交所 ETF 常见问题。 本策略没有自动止损单边下跌可能满仓后长期持有10 手上限只限制数量。 佣金参数按券商实际情况调整。费用门槛是估算,不逐笔归集历史买入最低佣金; 若券商持仓成本已含费用,该估算会偏保守。

委托、持仓与持久化

  • 管理 codes 白名单内的已有持仓;excluded_codes 优先排除。配置外证券不买卖。
  • ETF-BUY-* / ETF-SELL-* 为本地编号,标签 etf,当前价按 0.001 元 精度提交限价。复用 OrderBook只自动撤销超时 120 秒的 ETF 前缀委托。
  • 同标的全账户买卖在途、未知委托状态或在途份额都会阻止新单。 行情缺少 timetag、不是当天或超过默认 90 秒,也不交易。
  • 下单前原子保存意图HTTP 成功、超时或失败均不会自动解除锁。 必须收到终态53/54/56/57并且券商持仓与累计成交量相符才能继续。 部分成交按实际数量核对,买入必须取得实际成交均价才推进下一格。
  • 状态位于 {qmt_data_dir}/etf/{账户SHA256}/state.json,保存实际买入基准、 止盈峰值、冻结格距和未确认委托;重启恢复,损坏不静默覆盖。
  • 同一 ETF 不适合同时由人工或其他策略频繁交易。在途期间外部改变持仓,会暂停核对。 若跨日后柜台不再返回未确认订单,则持续暂停该标的,需要核对历史订单与持仓后 人工处理状态,不按超时自动重发。有未确认委托的标的不能直接从配置移除。

启用

  1. 修改 etc/etf.yaml 的标的及参数。示例仅示范格式,请选择实际交易的 A 股股票 ETF 代码形态检查不验证基金投资范围。

  2. 主机对应的账户 YAML 设置:

    strategy: etf
    etf_config_path: etf.yaml
    enable_auto_ipo: false
    

    路径相对账户配置目录,也支持绝对路径;不填默认 etc/etf.yamlaccount_idmin_cash_ratio 继续生效。公共校验仍要求 buy_valuegrid_step_pct 为正,但 ETF 不用它们计算数量或格距。 关闭 IPO 是此处示例选择ETF 决策不依赖 IPO 或远端股票信号。

  3. 无需修改 QMT 服务端或 sdk/。历史接口适配完全位于 strategy/etf/data.py 实时行情、持仓和交易继续使用已有 QMT SDK。

  4. 确认外部接口提供配置 ETF 的足量、最新日线。HTTP 错误、业务失败、空列表、 证券代码不一致或数据异常都会跳过该标的,不改用其他证券数据。 2026-09-17 联通验证中,股票样本 600584.SH 成功返回 200 条,示例 ETF 510300.SH 返回 404需要数据服务覆盖实际配置的 ETF 后才能正常运行。

  5. 按现有方式运行 python main.py。每 30 秒执行午休暂停15:00 退出。

本次新增不会自动切换已有实盘账户,也没有进行实盘委托。

离线验证

py-client 中运行:

python -m unittest discover -s tests -p test_etf.py -v
python -m unittest discover -s tests -v

覆盖指标、未收盘日线排除、反弹确认、固定手数、限仓、资金共享、部分成交、拒单、 快照延迟、T+1、重启防重、峰值恢复、状态损坏、外部日线接口与异常响应。 离线行为验证不等同于历史收益回测或实盘联调。