回测 - 风险管理规则
风控规则用于在策略信号的基础上叠加风险控制逻辑。规则可以全局应用,也可以按策略分别绑定。
基本用法
from jh_quant.backtest import backtestfrom jh_quant.backtest import ( StrategyTurtle, StopLossRule, TakeProfitRule, TrailingStopRule,)
# 方式一:全局规则(所有策略共用)trading_history, perf = backtest( strategies={"海龟": StrategyTurtle()}, price_data=stock_price, rules=[StopLossRule(0.05), TakeProfitRule(0.10)],)
# 方式二:按策略绑定不同规则trading_history, perf = backtest( strategies={"海龟": StrategyTurtle()}, price_data=stock_price, rules={ "海龟": [StopLossRule(0.05), TrailingStopRule(0.03)], },)
# 方式三:混合使用trading_history, perf = backtest( strategies={ "海龟": StrategyTurtle(entry_window=20), "激进海龟": StrategyTurtle(entry_window=10), }, price_data=stock_price, rules={ "海龟": [StopLossRule(0.05)], # "激进海龟" 不指定 → 无风控 },)规则总览
| 规则 | 触发条件 | 关键参数 |
|---|---|---|
| StopLossRule | 亏损超过固定比例 | pct |
| TakeProfitRule | 盈利超过固定比例 | pct |
| TrailingStopRule | 从最高点回撤超过比例 | pct |
| ATRTrailingStopRule | 从最高点回撤超过 ATR 倍数 | multiplier, window |
| MaxHoldingBarsRule | 持仓 K 线数超过限制 | bars |
| MaxConsecutiveRisingBarsRule | 连续上涨超过限制 | bars |
| MaxConsecutiveFallingBarsRule | 连续下跌超过限制 | bars |
StopLossRule
固定比例止损。
rule = StopLossRule(pct=0.05) # 亏损 5% 止损TakeProfitRule
固定比例止盈。
rule = TakeProfitRule(pct=0.10) # 盈利 10% 止盈TrailingStopRule
移动止损(回撤止盈)。从持仓期间的最高点回撤超过指定比例时卖出。
rule = TrailingStopRule(pct=0.03) # 从最高点回撤 3% 止损与 StopLossRule 的区别:StopLossRule 基于入场价,TrailingStopRule 基于持仓期间最高价。后者允许利润奔跑,只在趋势反转时离场。
ATRTrailingStopRule
基于 ATR(平均真实波幅)的移动止损。
rule = ATRTrailingStopRule( multiplier=2.0, # ATR 倍数 window=14, # ATR 计算窗口)MaxHoldingBarsRule
最大持仓 K 线数限制。
rule = MaxHoldingBarsRule(bars=20) # 最多持有 20 个交易日MaxConsecutiveRisingBarsRule
连续上涨超出限制后止盈。
rule = MaxConsecutiveRisingBarsRule(bars=5) # 连涨 5 天后卖出MaxConsecutiveFallingBarsRule
连续下跌超出限制后止损。
rule = MaxConsecutiveFallingBarsRule(bars=5) # 连跌 5 天后卖出规则执行顺序
当绑定多个规则时,按列表顺序依次检查。任一规则触发卖出,后续规则不再执行。建议将止损类规则放在最前面。
自定义规则
继承 RiskRule 基类:
from jh_quant.backtest import RiskRule, PositionStateimport pandas as pd
class GapDownStopRule(RiskRule): """跳空低开止损"""
def __init__(self, pct=0.03): self.pct = pct
def on_tick(self, i: int, df: pd.DataFrame, state: PositionState) -> bool: if i == 0 or not state.in_position: return False gap = (df.iloc[i]['open'] - df.iloc[i-1]['close']) / df.iloc[i-1]['close'] return gap <= -self.pct| 钩子方法 | 调用时机 | 返回值 |
|---|---|---|
on_enter(i, df, state) | 买入信号触发后 | True 阻止入场 |
on_tick(i, df, state) | 每个持仓交易日 | True 触发卖出 |
should_sell(i, df, state) | 卖出信号评估时 | True 确认卖出 |