程序员量化交易实战 19:从目标权重生成调仓计划
原创 · 约 7 分钟阅读 · 阅读 --
Last updated on

程序员量化交易实战 19:从目标权重生成调仓计划

作者: Alex Xiang


程序员量化交易实战 19:从目标权重生成调仓计划

古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。

模拟盘里最容易混淆的一件事,是把“策略目标”直接当成“账户执行”。

第 19 篇刻意在两者之间加一层:调仓计划。它只给出买卖建议,不直接修改账户状态。

ZiCode 工程师规划模拟盘调仓

调仓计划的输入

第 19 章新增 app/rebalance_plan.py

输入包括:

  • 当前模拟盘账户。
  • 最新价格。
  • 目标权重。
  • 最小调仓金额。

目标权重可以来自很多地方:等权组合、因子打分排序、风险预算、人工指定白名单,或者后面更复杂的组合优化。无论来源是什么,进入账户层之前都应该先变成调仓计划。这样策略层只表达“想要多少权重”,账户层再处理价格、手数、最小交易金额和风控。

输出买卖建议

输出对象是 RebalancePlan,里面包含一组 RebalanceOrderPlan

@dataclass(frozen=True)
class RebalanceOrderPlan:
    symbol: str
    side: str
    shares: int
    price: float
    target_weight: float
    current_weight: float
    delta_value: float

它保留当前权重、目标权重和差额金额,方便后续解释为什么建议买入或卖出。

为什么不直接下单

调仓计划不是执行器。

它不扣现金,不改持仓,也不假装成交。真实系统里,计划还要经过风控、人工确认、可交易性检查和撮合执行。即使在模拟盘里,把计划和执行分开也能减少很多调试成本。

A 股一手约束

计划函数会把股数压到 100 股一手:

def _lot_shares(raw_shares: float) -> int:
    lots = int(abs(raw_shares) // 100)
    return lots * 100

这和第 4 篇的交易规则保持一致。后续如果要支持卖出零股或更细的交易规则,可以在这一层继续扩展。

当前主线联动运行

风控发现单票过高后,paper-flow 会继续根据目标权重生成调仓计划:

uv run python -m scripts.chapter_examples paper-flow

真实输出如下:

第 19 篇调仓计划真实运行截图

当前持仓权重是 80.74%,目标权重是 45.00%,因此计划卖出 2800 股。这里仍然只是计划,不会直接修改账户。后续执行层要再检查可用持仓、价格、费用和风控状态。

本章更新与代码仓库

本章更新内容:

  • 新增 app/rebalance_plan.py
  • 实现基于当前权重和目标权重的调仓计划。
  • 支持最小调仓金额过滤、缺失价格跳过和 A 股 100 股一手约束。
  • 新增 tests/test_rebalance_plan.py,覆盖买卖建议和小额变动跳过。
  • 补充当前主线联动示例的调仓计划真实运行截图。
  • 补充目标权重来源和策略层、账户层职责边界。

代码仓库:

https://github.com/ax2/zi-quant-platform

本章代码:

git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-19
uv sync --extra dev
uv run pytest tests/test_rebalance_plan.py

第 19 章提交为 b655c37,tag 为 chapter-19

本篇小结

策略目标不能直接等同于账户动作。

第 19 篇把目标权重转换成可解释、可测试、尚未执行的调仓计划。下一篇会把账户快照、风控报告和调仓计划合成一条模拟盘日报。

微信公众号

欢迎关注「字与码」

如果这篇文章对你有用,也欢迎在微信里继续关注后续更新。

微信公众号字与码二维码