策略结构与回测

PythonGo 策略的本质是一个继承 BaseStrategy 的 Python 类。本章把这个骨架拆成三个零件:参数映射、 回调生命周期、回测引擎。掌握这些,再复杂的策略也只是在零件里填逻辑。

一、参数与状态映射

PythonGo 用 pydantic 风格的「映射模型」把变量接到界面上——参数能编辑、状态只读展示。

from typing import Literal
from pythongo.base import BaseParams, BaseState, Field


class Params(BaseParams):
    """参数映射模型——展示在参数栏,可编辑"""
    exchange: str = Field(default="", title="交易所代码")
    instrument_id: str = Field(default="", title="合约代码")
    order_volume: int = Field(default=1, title="报单手数", ge=1)
    order_direction: Literal["buy", "sell"] = Field(default="buy", title="报单方向")


class State(BaseState):
    """状态映射模型——展示在状态栏,只读"""
    order_id: int | None = Field(default=None, title="报单编号")

要点:

  • BaseParams 默认就带 exchangeinstrument_id 两个字段,建议仍显式写出来。
  • 类型注释必写——界面按类型自动解析转换。Literal["buy", "sell"] 限制只能填这两个值。
  • Fielddefault(默认值,必填)和 title(中文名,必填)最常用;ge=2 表示大于等于 2。

二、策略类与回调

策略类继承 BaseStrategy类名必须和文件名一致。以 on_ 开头的是回调函数,由无限易在特定时机调用:

from pythongo.base import BaseStrategy
from pythongo.classdef import OrderData, TickData


class DemoTest(BaseStrategy):
    """策略描述(会显示在策略列表)"""
    def __init__(self) -> None:
        super().__init__()
        self.params_map = Params()
        self.state_map = State()

    def on_start(self) -> None:
        super().on_start()          # 启动:设 trading=True、订阅行情
        self.output("策略启动")

    def on_stop(self) -> None:
        super().on_stop()           # 暂停:设 trading=False、取消订阅
        self.output("策略暂停")

    def on_tick(self, tick: TickData) -> None:
        super().on_tick(tick)       # 每个行情切片触发
        self.output(tick.last_price)

    def on_order(self, order: OrderData) -> None:
        super().on_order(order)     # 报单状态变化触发

    def on_trade(self, trade, log=False) -> None:
        super().on_trade(trade, log)  # 成交推送触发

    def on_error(self, error: dict) -> None:
        super().on_error(error)     # 报单或代码错误触发

所有回调都必须用 super() 调用父类同名方法,否则父类逻辑(如订阅行情、保存实例)会被跳过。

回调执行顺序

创建/加载实例 → on_init → 运行按钮 → on_start → on_tick(持续) → 暂停按钮 → on_stop

                                          on_order / on_trade / on_error / on_cancel

策略靠 on_tick 里源源不断的行情驱动——没行情就没触发。所以 on_start 里通常要先订阅合约(父类已自动处理 params_map 里的合约)。

三、代码规范要点

  • 导入顺序:标准库 → 第三方库 → 本地库(pythongo)。
  • 禁用星号导入 from pythongo import *
  • 参数超过两个的函数调用要带参数名send_order(exchange=..., volume=...) 而非位置参数。
  • None 判断用 is None,不要用 if foo:(因为 0 也算假值)。

四、回测引擎

PythonGo 自带 pythongo.backtesting 回测模块,用历史 Tick 数据撮合,支持所有实盘策略代码(无需改动)。前提是注册 QuantFair 账号并申请 AccessKey / AccessSecret,还要在「数据服务」里申请免费试用。

回测入口文件

pyStrategy/ 根目录新建 app.py(与 pythongo 目录同级):

from demo.DemoDMA import DemoDMA, Params
from pythongo.backtesting.engine import run
from pythongo.backtesting.models import Config


if __name__ == "__main__":
    params = Params(
        exchange="SHFE",
        instrument_id="ag2604",
        fast_period=5,
        slow_period=20
    )

    backtesting_config = Config(
        access_key="你的AccessKey",
        access_secret="你的AccessSecret"
    )

    run(
        config=backtesting_config,
        strategy_cls=DemoDMA(),          # 带括号:实例化后的类
        strategy_params=params,
        start_date="2025-08-01",         # yyyy-mm-dd
        end_date="2025-08-05",           # 不包含结束日期
        initial_capital=100_0000
    )

直接运行 python app.py 即可。Config 还可设 fee_rate(手续费率,默认 0.0023)、margin_rate(保证金率,默认 0.13)、show_progress(进度条)等。

回测注意事项

  • 只支持新版 PythonGO,使用 Tick 数据,撮合模式为见价成交
  • 没有 K 线图窗口self.widget 相关代码会被跳过。
  • 无法回测标准套利合约;结果仅供参考,不代表实盘。

小结

策略 = 参数映射模型 + 回调函数 + 业务逻辑;回测用 backtesting.engine.runConfig 跑历史 Tick。 接下来认识具体的数据接口——行情订阅、Tick 字段、K 线合成:行情接口