settings.py 是一个 Python 文件,里面定义一个 settings 字典。大部分时候你当 JSON 写就行——只有需要动态逻辑时才用到 Python 特性。
大体结构一览
settings = {
"is_enabled": True,
"meta": { ... },
"market_profile": "china_a_stock",
"core": { ... },
"data": { ... },
"simulation": { ... },
"goal": { ... },
"sampling": { ... },
"portfolio": { ... },
"scanner": { ... },
"fees": { ... },
"analysis": { ... },
}下面逐块说明。
meta
策略元信息。
"meta": {
"key": "rsi_v1", # 策略唯一标识
"display_name": "RSI 超卖反弹", # 显示名
"description": "RSI 低于 30 时买入", # 描述
"category": "mean_reversion", # 分类
"keywords": ["rsi", "oversold"], # 关键词
}key 是最重要的字段——CLI 命令用 --strategy rsi_v1 找到策略。改了 key 等于换了一个策略,历史版本不会自动关联。
core
策略私有参数。你想配什么就配什么,通过 self.core_int(ctx.settings, key) 在钩子里读取。
"core": {
"rsi_period": 14,
"rsi_threshold": 30,
"rebalance_period": "year",
}data
声明策略需要什么数据。
"data": {
"base": {
"data_key": "stock.kline.daily", # 基础 K 线数据
"params": {},
"indicators": { # 可选:给 K 线附加指标
"macd": [{"fast": 12, "slow": 26, "signal": 9}],
},
},
"required": [ # 可选:附加数据源
{"data_key": "stock.finance.quarterly"},
{"data_key": "macro.cpi"},
],
"min_required_records": 100, # 最少需要多少根 K 线
}base 是策略的主数据,has_opportunity 里 ctx.data("stock.kline.daily") 读的就是这个。required 里的数据通过 ctx.data("stock.finance.quarterly") 读取。indicators 会自动计算并注入到 K 线数据里。
simulation
回测执行配置。
"simulation": {
"execution": {
"start_date": "20220101",
"end_date": "20241231",
"mode": "slice_based", # 或 "entity_based"
},
"assumption": {
"template": "custom", # 或 "standard"/"strict"/"ideal"/"extreme"/"none"
"tradability": {
"monitor_price": "close",
"enter_price": "next_open", # 次日开盘价买入
"exit_price": "close", # 收盘价卖出
"slippage": {"enter_bps": 0.0, "exit_bps": 0.0},
"edges": {
"allow_enter_at_limit_up": False, # 涨停不买
"allow_exit_at_limit_down": False, # 跌停不卖
},
},
"target_check_order": ["check_stop_loss", "check_take_profit", "check_expiration"],
},
"risk_control": {
"skip_enter_when": ["st", "star_st"], # ST 股不买
"force_exit_when": ["st"], # 持仓变 ST 强平
"pending_enter": {
"max_wait_open_days": 5,
"max_entry_drift": None,
"abort_enter_when": ["st"],
},
},
"retention": {"max_output_versions": 5},
}execution.mode
模式 | 逻辑 | 适用 |
slice_based | 按时间切片,每片处理全部股票 | 多股票、中等时间窗口 |
entity_based | 按股票分组,每组独立跑完整时间线 | 少股票、长时间窗口 |
assumption.template
模板 | 说明 |
standard | 标准假设:次日开盘买入,收盘卖出 |
strict | 严格假设:涨停不买、跌停不卖、无滑点 |
ideal | 理想假设:任意价格买卖,无限制 |
extreme | 极端假设:最高卖最低买 |
custom | 自定义 tradability 各字段 |
none | 不设假设 |
tradability 字段
字段 | 可选值 | 说明 |
monitor_price | close | 盯盘用什么价格 |
enter_price | next_open / touch / open / close | 进场价 |
exit_price | next_open / open / close / high / low | 出场价 |
slippage.enter_bps | float | 进场滑点(基点) |
slippage.exit_bps | float | 出场滑点(基点) |
edges.allow_enter_at_limit_up | bool | 涨停是否允许买 |
edges.allow_exit_at_limit_down | bool | 跌停是否允许卖 |
liquidity.max_participation_rate | float | 最大参与率 |
liquidity.participation_on_exceed | clip / skip | 超量时砍量还是跳过 |
delisted_exit_price | last_tradable_close / same_tick_close | 退市时用什么价格平仓 |
goal
止盈止损过期规则。这是策略最核心的配置。
简单目标:固定止盈止损
"goal": {
"stop_loss": {
"stages": [
{"ratio": -0.10, "close_invest": True}, # 亏 10% 全部止损
],
},
"take_profit": {
"stages": [
{"ratio": 0.30, "close_invest": True}, # 涨 30% 全部止盈
],
},
}多段目标:分批止盈 + 移动止损
"goal": {
"expiration": {"fixed_window_in_days": 100, "mode": "trading_day"},
"stop_loss": {
"stages": [
{"ratio": -0.20, "close_invest": True}, # 亏 20% 全部止损
],
},
"take_profit": {
"stages": [
# 涨 15%:不卖,把止损抬到成本价
{"ratio": 0.15, "exit_ratio": 0, "actions": ["set_protect_loss"]},
# 涨 30%:卖掉原始仓位的 50%
{"ratio": 0.30, "exit_ratio": 0.5},
# 涨 50%:再卖掉 40%,剩余交给动态止损
{"ratio": 0.50, "exit_ratio": 0.4, "actions": ["set_dynamic_loss"]},
],
},
"protect_loss": {"ratio": 0, "close_invest": True},
"dynamic_loss": {"ratio": -0.15, "close_invest": True},
}stage 字段
字段 | 类型 | 说明 |
ratio | float | 触发比例。正数止盈,负数止损。与 custom 互斥 |
custom | str | 自定义触发条件名。会调用钩子的 is_stop_loss / is_take_profit |
close_invest | bool | True = 整笔退出 |
exit_ratio | float | 退出比例(0~1),相对初始总仓位。close_invest=True 时等于 1.0 |
actions | list | 触发后的附加动作:set_protect_loss、set_dynamic_loss |
expiration 字段
字段 | 类型 | 说明 |
fixed_window_in_days | int | 持仓多少天后强制平仓 |
mode | str | open_day(开仓日算起)/ trading_day(交易日)/ natural_day(日历日) |
sampling
股票池采样。开发时只跑一部分股票,正式回测跑全量。
"sampling": {
"use_sampling": True,
"strategy": "pool", # uniform / stratified / random / pool / blacklist
"sampling_amount": 500,
"pool": {
"stock_ids": ["000001.SZ", "000002.SZ"],
},
}不用采样时设 "use_sampling": False 即可。
portfolio
资金管理配置。
"portfolio": {
"initial_capital": 1000000,
"allocation": {
"mode": "equal_capital", # equal_capital / equal_shares / kelly / custom
"max_portfolio_size": 10, # 最多同时持有 10 只
"max_weight_per_stock": 0.3, # 单只最多占 30%
"lots_per_trade": 1, # 每次交易 1 手
"kelly_fraction": 0.5, # kelly 模式下的比例
"skip_trade_when_insufficient": False,
},
"output": {
"save_trades": True, # 保存逐笔成交
"save_equity_curve": True, # 保存净值曲线
},
}scanner
扫描模式配置。
"scanner": {
"adapters": ["console"], # 结果输出方式
"use_strict_previous_trading_day": True, # 严格交易日检查
"max_cache_days": 10, # 扫描结果保留天数
"watch_list": "", # 关注列表
}fees
手续费。
"fees": {
"commission_rate": 0.0003, # 佣金万三
"min_commission": 5.0, # 最低 5 元
"stamp_duty_rate": 0.001, # 印花税千一(卖出收)
"transfer_fee_rate": 0.00001, # 过户费万零点一
}analysis
归因分析开关。
"analysis": {
"enabled": False, # True 则回测后自动收集归因数据
}顶层字段
字段 | 类型 | 说明 |
is_enabled | bool | 策略是否启用。禁用的策略不被批量扫描和回测选中 |
market_profile | str | 市场画像,如 china_a_stock |
动态 settings - 但不是很建议这么用,建议还是把您的参数放入settings.core中
如果某些参数需要根据条件动态决定,可以在 settings.py 里写 Python 逻辑:
import os
settings = {
"meta": {
"key": "rsi_v1",
},
"core": {
"rsi_period": 14,
"rsi_threshold": int(os.environ.get("RSI_THRESHOLD", "30")),
},
# ... 其他配置
}一般用户当 JSON 写就行。需要动态参数的高级用法才用 Python 特性。