feat: 网格策略核心能力升级 — 层级循环复用、Triple Barrier 风控、Decimal 精度、PnL 追踪#90
feat: 网格策略核心能力升级 — 层级循环复用、Triple Barrier 风控、Decimal 精度、PnL 追踪#90loadchange merged 7 commits intomainfrom
Conversation
loadchange
commented
Mar 23, 2026
- 层级循环复用:实现 5 态状态机,层级成交后自动挂反向平仓单,完成后 reset 重新挂单,消除全撤全建的裸露窗口
- 增量同步:新增 sync_grid_incremental(),小变化走增量状态机,仅结构性变化触发全量重建
- Triple Barrier 风控:新增 GridBarrierMonitor,支持止损/止盈/时限/追踪止损/双边限价五重屏障
- Decimal 精度:新增 precision.py,核心路径全面使用 Decimal,仅 API 边界转 float
- PnL 追踪:新增 GridPnLTracker,双轨记账(已实现+未实现),逐轮记录盈亏和手续费
- 状态持久化:grid_state.json 扩展为层级级别,支持崩溃恢复
- 配置扩展:config.grid.yaml 新增 risk_management 段
- 测试:新增 test_grid_barrier / test_grid_pnl / test_grid_level_lifecycle
- 层级循环复用:实现 5 态状态机,层级成交后自动挂反向平仓单,完成后 reset 重新挂单,消除全撤全建的裸露窗口 - 增量同步:新增 sync_grid_incremental(),小变化走增量状态机,仅结构性变化触发全量重建 - Triple Barrier 风控:新增 GridBarrierMonitor,支持止损/止盈/时限/追踪止损/双边限价五重屏障 - Decimal 精度:新增 precision.py,核心路径全面使用 Decimal,仅 API 边界转 float - PnL 追踪:新增 GridPnLTracker,双轨记账(已实现+未实现),逐轮记录盈亏和手续费 - 状态持久化:grid_state.json 扩展为层级级别,支持崩溃恢复 - 配置扩展:config.grid.yaml 新增 risk_management 段 - 测试:新增 test_grid_barrier / test_grid_pnl / test_grid_level_lifecycle
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求对网格交易策略的核心能力进行了重大升级。它引入了强大的层级循环复用机制,通过增量同步而非全量重建来更高效地管理网格层级。同时,实现了一个全面的三重屏障风险管理系统,为策略提供了多维度的保护。为了确保计算的准确性,所有核心路径现在都使用 Decimal 类型进行高精度计算。此外,新增的 PnL 追踪器提供了详细的盈亏和费用核算。这些改进旨在提升策略的稳定性、准确性和风险控制能力,并增强了崩溃恢复时的状态持久化。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
本次 PR 是一次重大的功能升级,引入了层级循环复用、Triple Barrier 风控、全面的 Decimal 精度和 PnL 追踪,极大地提升了网格策略的健壮性和精细度。代码结构清晰,新增的模块如 grid_barrier、grid_pnl 和 precision 设计良好,并且附有非常全面的单元测试,这值得称赞。
我的审查主要集中在以下几个方面:
- 代码可读性与维护性:对
config.grid.yaml.example中的注释提出了修改建议,使其更清晰,避免用户误解。同时建议重构grid_barrier.py中重复的配置加载逻辑。 - 代码健壮性:在
grid_manager.py中,建议为被忽略的异常添加日志记录,以避免潜在问题被隐藏。 - 精度:为了贯彻本次升级的核心目标,建议在
grid_manager.py中使用Decimal的ln/exp函数进行几何网格计算,以避免浮点数转换带来的精度损失。
总体而言,这是一次高质量的提交,上述建议旨在做一些锦上添花的改进。
| # 止损:整个网格的 PnL% 低于此值 -> 全部平仓 | ||
| # 设置为 null 可禁用 |
| def from_config(cls, config: dict[str, Any]) -> "TripleBarrierConfig": | ||
| """从 config.grid.yaml 的 risk_management 段构建。""" | ||
| if not config: | ||
| return cls() | ||
|
|
||
| barrier = cls() | ||
|
|
||
| if "stop_loss_pct" in config: | ||
| val = config["stop_loss_pct"] | ||
| barrier.stop_loss_pct = to_decimal(val) if val is not None else None | ||
|
|
||
| if "take_profit_pct" in config: | ||
| val = config["take_profit_pct"] | ||
| barrier.take_profit_pct = to_decimal(val) if val is not None else None | ||
|
|
||
| if "time_limit_seconds" in config: | ||
| val = config["time_limit_seconds"] | ||
| barrier.time_limit_seconds = int(val) if val is not None else None | ||
|
|
||
| if "trailing_stop_activation_pct" in config: | ||
| val = config["trailing_stop_activation_pct"] | ||
| barrier.trailing_stop_activation_pct = to_decimal(val) if val is not None else None | ||
|
|
||
| if "trailing_stop_delta_pct" in config: | ||
| val = config["trailing_stop_delta_pct"] | ||
| barrier.trailing_stop_delta_pct = to_decimal(val) if val is not None else None | ||
|
|
||
| if "price_lower_limit" in config: | ||
| val = config["price_lower_limit"] | ||
| barrier.price_lower_limit = to_decimal(val) if val is not None else None | ||
|
|
||
| if "price_upper_limit" in config: | ||
| val = config["price_upper_limit"] | ||
| barrier.price_upper_limit = to_decimal(val) if val is not None else None | ||
|
|
||
| return barrier |
There was a problem hiding this comment.
from_config 方法中的一系列 if 判断语句存在较多重复。可以利用一个映射表来循环处理,使代码更简洁且易于未来扩展。
@classmethod
def from_config(cls, config: dict[str, Any]) -> "TripleBarrierConfig":
"""从 config.grid.yaml 的 risk_management 段构建。"""
if not config:
return cls()
barrier = cls()
# 字段名到转换函数的映射
converters = {
"stop_loss_pct": to_decimal,
"take_profit_pct": to_decimal,
"time_limit_seconds": int,
"trailing_stop_activation_pct": to_decimal,
"trailing_stop_delta_pct": to_decimal,
"price_lower_limit": to_decimal,
"price_upper_limit": to_decimal,
}
for field, converter in converters.items():
if field in config:
value = config[field]
setattr(barrier, field, converter(value) if value is not None else None)
return barrier| if d_lower <= 0 or d_upper <= 0: | ||
| return [float(d_lower.quantize(tick))] | ||
| # Decimal 不直接支持分数幂,借助 float 做幂运算再转回 | ||
| ratio = float(d_upper / d_lower) ** (1.0 / (num - 1)) |
There was a problem hiding this comment.
| except Exception: | ||
| pass |
| except Exception: | ||
| pass |
# Conflicts: # src/trading/grid_manager.py