支撑压力位与风险预算策略¶
sr_risk_budget 是一个固定参数、只做多的沪深主板日线研究策略,入口为 examples/25_sr_risk_budget.py。它复用已有支撑压力研究模块中的 ATR 和历史区间计算,但独立管理订单和逐日风险,不覆盖原来的 ashare_sr_leader 策略。
本策略尚未证明持续盈利。 风险参数是计划约束,不是收益承诺或实际亏损上限;测试通过只证明被测试的代码行为。
买卖规则¶
- 沪深 300 收盘价高于 120 日均线,且均线高于 20 个交易日前,才允许新开仓。条件不满足或指数数据缺失时,提交清仓请求。
- 个股站上不下降的 60 日均线,收阳且收盘高于上一日;过去 20 日估算日均成交额至少 5000 万元,ATR/股价不超过 6%。成交额估算使用
close × volume,成交量单位必须为股。 - 两种入场:回踩前 60 日最低价形成的支撑并收回;或在此前 5 日出现放量突破,随后回踩突破前冻结的 60 日压力位。压力位由突破前的数据确定,不使用未来拐点。
- 初始止损取“支撑减 0.5 ATR”和“买入限价减 1.5 ATR”中较低者;计划止损距离必须在 1.5%—8% 之间。
- 支撑反弹以原压力位下方 0.3 ATR 为目标。突破回踩参考突破前的历史上方压力;没有上方压力时,使用明确标为推算值的 3R 目标。预期盈亏比小于 1.8 的交易放弃。
- 止损只会上移:持仓最高收盘价减 3 ATR。收盘触及止损、达到目标或持仓满 40 个交易日时提交卖出请求。卖出后等待 5 个交易日再考虑同一股票。
仓位与组合保护¶
| 参数 | 默认值 | 含义 |
|---|---|---|
risk_per_trade |
0.5% | 单笔计划风险,按止损距离并预留费用估算 |
max_open_risk |
2% | 新开仓时,已有风险与待成交买单合计预算 |
max_stock_weight |
15% | 单只股票新开仓金额上限 |
max_exposure |
60% | 新开仓时的组合股票市值上限 |
max_positions |
5 | 最大持仓数量 |
volume_participation |
0.5% | 买单不超过过去 20 日日均成交股数的该比例 |
halt_drawdown |
10% | 从本次风控周期净值高点回撤达到阈值,提交全部退出请求 |
halt_days |
20 | 熔断后至少等待 20 个交易日,且已空仓、大盘过滤恢复才重新交易 |
下单股数取风险、现金、个股仓位、组合仓位和历史流动性五项约束的最小值,再向下取整到 100 股。最低佣金纳入现金和风险预留。待卖仓位在真正成交前继续占用资金与风险,存在退出订单时不新开仓。
市价波动会使实际权重突破计划权重;本策略不为维持固定比例而每日机械调仓。熔断恢复时重置的是下一次风险周期的高点,不会重置报告中的累计净值和最大回撤。
信号与成交时序¶
只使用日线 after_trading_end 回调。在 15:00 后,将 attribute_history 返回的昨日及更早历史,与 data[code] 的当日已完成 K 线合并。不能把这个回调挪到早盘。
- T 日收盘形成信号;最早在 T+1 日开盘撮合。
- 买入采用不高于信号收盘价约 0.5% 的限价,撮合后的滑点价格也必须满足限价。
- 买单仅尝试下一次开盘;当天收盘取消未成交余量。部分成交只管理真实持仓。
- 止损和止盈是收盘信号,不是盘中保证成交的止损单。买入当日不能卖出;跌停、停牌和跳空可能让实际亏损明显超过预算。
- 被引擎取消的卖单,只要退出意图未完成,就在下一次收盘重新提交;部分成交卖单保留剩余数量。
运行与输入数据¶
在仓库根目录执行:
pip install -e ".[dev]"
python examples/25_sr_risk_budget.py --download --start 2021-01-01 --end 2025-12-31
python examples/25_sr_risk_budget.py --stress --start 2021-01-01 --end 2025-12-31
--download 会下载并覆盖 data/sr_risk_budget/ 中的快照。重复评估时不加此选项,可以保持输入不变。默认股票池直接采用 examples/_defaults.py 的 8 只股票,属于自选观察名单,并非历史时点的指数成分。
也可以提供 CSV:
文件名为 <code>_daily_qfq.csv,包括 000300.XSHG_daily_qfq.csv。首列为日期索引,至少包含 open,high,low,close,volume,价格为同一口径的前复权人民币价格,股票成交量为股。--download 将 eqlib 主板股票接口的成交量从手乘以 100 转为股;已提供的 CSV 不会再转换。指数成交量保留源单位,不参与策略的流动性计算。文件必须覆盖测试末日,并在开始日前提供至少 config.history_bars 根有效日线(默认 140 根)。重复、乱序、非有限数值、错误 OHLC、基准缺交易日或时间覆盖不足都会报错,不会悄悄缩短测试区间。股票缺失交易日会记录在清单中,不会凭空补成交。
离线运行使用打包交易日历,并把引擎和报告的读取绑定到同一份 CSV,避免回测结束时又下载另一版指数数据。这一示例适配器作用于当前 Python 进程;不要在同一个进程中并发运行它。
默认使用统一佣金 0.025%、每笔最低 5 元,卖出印花税由引擎按日期处理;基础滑点为单边 0.1%。--stress 再跑一次双倍佣金及最低佣金、单边 0.3% 滑点。税率减半生效日期可查税务总局公告。
输出目录 reports/sr_risk_budget/:
| 文件 | 用途 |
|---|---|
summary.json |
固定参数、成本、各输入文件 SHA-256、完整区间及逐年指标、费用压力测试 |
equity.csv |
每日净值、现金、持仓比例、熔断状态 |
trades.csv |
引擎实际成交及费用 |
events.csv |
买入限价、支撑、止损、目标、退出原因、熔断与恢复事件 |
逐年指标来自同一条连续持仓路径,使用前一个观察点的净值计算边界收益;不把每年重置成现金,也不把这些切片称为独立样本外测试。该示例单次运行不做参数搜索。不得挑出表现最好的年份宣称稳定盈利。
仅在验证合成行情时使用 --synthetic,报告会标记为执行测试,不作为真实收益证据。
在其他策略中使用¶
from eqlib import run_backtest
from eqlib.strategies import SRRiskConfig, make_sr_risk_budget_strategy
initialize = make_sr_risk_budget_strategy(
["601398", "601318", "600276", "601088"],
config=SRRiskConfig(),
)
result = run_backtest(initialize, "2023-01-01", "2025-12-31", starting_cash=1_000_000)
可传入 eligible(code, date),使用当时已知的股票池成员与 ST 状态过滤,并在标的失去资格后提交退出请求。不传时明确使用静态股票池;不能把今天的名称或今日 ST 状态当成历史事实。API 为 EXPERIMENTAL,仅支持主板日线研究,未提供实盘券商适配。
验证边界¶
回归测试覆盖支撑反弹、突破回踩、未来行情变动不影响历史信号、费用与整手限制、同步资金占用、隔日撮合、部分成交、跳空穿越止损、跌停卖出重试、熔断恢复及 CSV 截断。合成行情只用于验证这些行为,不作为收益证据。
当前版本仍继承引擎的研究近似:前复权价格参与撮合、按日成交量限制撮合规模、估算板块涨跌停,没有完整的历史 ST/退市清单、真实开盘集合竞价队列或公司行为现金与股数账本。因此,既不能保证“稳定赚钱”,也不能仅靠此回测把策略认定为可实盘。
在收益判断前,应冻结参数和历史时点股票池,在未参与设计的新数据上记录净收益、回撤、完整交易数量、不同市况及成本压力表现,再进行模拟盘。任何门槛不通过都应保留失败结果。
交易约束核对来源:上交所现行交易规则、上交所整手及零股申报说明、港交所互联互通 FAQ。
可选突破规则与 2026 年 9 月研究记录¶
SRRiskConfig() 保留原行为。新增三个严格布尔参数:
| 参数 | 默认值 | 行为 |
|---|---|---|
allow_breakout |
False |
支撑反弹和回踩均未触发时,允许直接突破此前 level_window 日最高价 |
require_market_slope |
True |
设为 False 只取消大盘均线斜率要求,仍须收盘高于均线 |
exit_on_market_filter |
True |
设为 False 不因大盘过滤失效直接清仓;新开仓过滤、个股止损、持仓期限、资格退出和组合熔断继续生效 |
直接突破使用不包含信号日的历史最高价,收盘须超过该价格 0.1 ATR,且不超过 1.5 ATR,成交量至少达到此前 20 日均量。它沿用原有止损、盈亏比、费用预留和次日限价撮合;上方历史压力只使用信号日前已知数据,没有历史压力时的 3R 目标是推算值。默认不启用,因为下面的验证未通过。
python examples/25_sr_risk_budget.py --allow-breakout --stress \
--start 2020-01-01 --end 2026-09-10 \
--data-dir /path/to/frozen-inputs --output reports/sr_breakout
原策略在同一份固定 8 股历史上的平均仓位仅 2.34%,完成 26 轮交易,其中 6 轮盈利。接近此前 60 日最低价、同时站上不下降的 60 日均线等条件叠加后,整个区间没有支撑反弹信号,剩下 38 个突破回踩候选。这解释了低交易频率和资金闲置;增加信号本身不保证提高胜率。
本轮先声明候选再运行,进行了三轮、共 11 个配置(含原策略)。开发期为 2020—2022,验证期为 2023—2024;每段以 100 万元独立开始,用之前的日线预热。后两轮利用过验证结果,因此存在重复选择偏差。全部结果如下:
| 候选 | 开发期净收益 | 验证期净收益 | 验证期最大回撤 |
|---|---|---|---|
baseline |
-0.76% | -1.30% | 1.78% |
short_levels |
+1.32% | -1.30% | 2.10% |
breakout |
+7.34% | -0.78% | 2.19% |
trend_exit |
+0.84% | -0.30% | 1.80% |
early_market |
+7.27% | -5.19% | 6.04% |
long_trend |
+6.84% | -4.90% | 5.98% |
early_trend_exit |
+0.28% | -1.56% | 2.74% |
channel60 |
+7.97% | -0.49% | 1.44% |
stock_exits |
+8.17% | -1.05% | 3.28% |
channel60_stock_exits |
+8.80% | -1.46% | 3.21% |
patient_exits |
+8.02% | -0.67% | 2.19% |
原定门槛为两段净收益均大于零、最大回撤均小于 12%、成交数多于原策略,再检查加倍佣金及 0.3% 滑点。没有配置通过收益门槛,没有可晋级策略。 channel60 仅作为改动最少的后续比较候选,在查看后段前冻结;它等于 SRRiskConfig(allow_breakout=True)。没有因完整区间上涨而修改门槛。
| 检查 | 原策略 | channel60 |
|---|---|---|
| 2020-01-02—2026-09-10 连续净收益 | -0.11% | +5.07% |
| 同期年化收益(244 个交易日/年) | -0.02% | +0.75% |
| 同期最大回撤 | 3.96% | 3.72% |
| 同期实际成交 / 完成轮次 | 52 / 26 | 98 / 49 |
| 同期平均仓位 | 2.34% | 3.66% |
| 2025-01-02—2026-09-10 独立后段净收益 | +2.37% | -2.39% |
| 候选完整区间费用压力净收益 | — | +4.09% |
同期沪深 300 价格指数收益 +11.03%。候选完整区间年化夏普为 -1.04(扣除 3% 年无风险基准;现金不计息)。候选验证期费用压力净收益 -0.70%,后段费用压力 -2.45%,仍不通过。完整区间有改善,但后段变差,收益主要来自早期行情;默认配置保持原样,两个版本都没有建立持续盈利证据。
此前已经看过原策略的完整历史,因此后段检查不是经认证的全新样本外数据。独立重置的分段收益不能简单相乘还原连续持仓路径。费用压力会改变限价成交和数量,因此交易路径可能不同。
数据口径和复现¶
所有候选共享同一份 2019-01-02—2026-09-10 快照,股票池、风险预算和佣金一致,没有按赢家换股票。中国神华有 2025-08-04—2025-08-15 的 10 个停牌交易日,未补造成交;可核对公司复牌公告。
这次历史包不是原生腾讯前复权:原生神华前复权在部分早期日期出现非正数,因而全部八股统一采用腾讯后复权乘以终点参考价格的固定比例,文件名仅为兼容保留 _daily_qfq.csv。成交量为股。公式为 input_OHLC[t] = hfq_OHLC[t] × qfq_close[2026-09-10] / hfq_close[2026-09-10]。终点归一化会影响绝对价格过滤和整手买入;缺少未复权成交价格、除权除息现金/股数账本、历史 ST 和时点成分,不能把结果当成可投资净收益。基准为价格指数,也没有统一分红再投资账本。
仓库 research/sr_risk_budget_2026_09/results.json 保存声明时间、所有参数、失败门槛、分段和逐年指标、输入 SHA-256。行情 CSV 不随代码发布;复现数字需要原归档快照,新下载或不同归一化数据属于不同实验。
python scripts/research_sr_risk_budget.py --candidate channel60 --period full \
--data-dir /path/to/frozen-inputs --output reports/replay
python scripts/research_sr_risk_budget.py --candidate channel60 --period full --stress \
--data-dir /path/to/frozen-inputs --output reports/replay
--candidate 可选表中 11 个名字;--period 可选 development、validation、later_check、full。每次只运行一个配置和区间,不自动寻找最优参数,不覆盖已有结果。辅助在线指数图省略,基准指标仍从本地快照计算。脚本保存实际成交、净值、事件、参数、费用及源文件摘要。
下一步应优先补齐时点股票池和原始价格/公司行为数据,再预先声明新的信号假设与标准,用未参与设计的数据或模拟盘检验。继续在已看过的年份调参不会产生新的独立证据。大量尝试会放大选择偏差,参见 Bailey 等关于回测过拟合的研究。本轮没有计算 PBO 或声称统计显著性。