策略结构与回测
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默认就带exchange和instrument_id两个字段,建议仍显式写出来。- 类型注释必写——界面按类型自动解析转换。
Literal["buy", "sell"]限制只能填这两个值。 Field里default(默认值,必填)和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.run 配 Config 跑历史 Tick。
接下来认识具体的数据接口——行情订阅、Tick 字段、K 线合成:行情接口。