Root README now points at the auto-trading shell and research pipeline; AGENTS.md gains a keep-docs-in-sync rule; trading/README.md maps every method from the two research docs to trading/risk and documents manage_position; research/README.md documents the backtest hook and --backtest CLI. Co-Authored-By: Claude Code <noreply@anthropic.com>
53 KiB
止损方法梳理与平台无关伪代码
目的:从 MQL5 知识库中提炼出常见的止损方法,去除所有 MQL5 平台特性(
PositionModify、iATR、SymbolInfoDouble、MqlTradeRequest、TRADE_RETCODE、SymbolInfoInteger、_Point/_Digits、CTrade、PositionGet*、PositionSelectByTicket等),改写为 Python-like 伪代码,便于向 Python、JavaScript、C++、其他交易框架移植时作为灵感参考。所有代码均使用统一的抽象层,如
position、broker、account、indicator、get_last_price()、modify_stop_loss()、close_position()等。每个方法末尾会列出核心参数含义与实现注意点。
0. 抽象层约定(供全文伪代码复用)
# 统一抽象对象(不同平台对应不同实现)
class Position:
ticket: int
symbol: str
side: str # "buy" 或 "sell"
open_price: float
open_time: datetime
size: float # 合约数量
stop_loss: float # 0 表示未设置
take_profit: float # 0 表示未设置
current_price: float
unrealized_pnl: float
magic_number: int
comment: str
class Broker:
point: float # 最小价格单位(1 个 tick)
pip: float # 1 pip 对应的价格单位
digits: int # 报价小数位
stop_level_points: int # 止损最小距离(点)
freeze_level_points: int # 冻结价距离
volume_min: float
volume_max: float
volume_step: float # 手数步长
tick_size: float
tick_value: float
def normalize(price: float) -> float: ...
def current_ask(symbol: str) -> float: ...
def current_bid(symbol: str) -> float: ...
class Account:
balance: float
equity: float
margin: float
free_margin: float
# 常用动作抽象
def modify_stop_loss(pos: Position, new_sl: float): bool: ...
def close_position(pos: Position): bool: ...
def close_partial(pos: Position, size: float): bool: ...
def get_indicator(symbol: str, name: str, period: int, shift: int = 0) -> float: ...
def get_bars(symbol: str, timeframe: str, count: int) -> list: ...
1. 方法总览表
| # | 方法 | 触发条件 | 计算逻辑核心 | 典型使用场景 |
|---|---|---|---|---|
| 1 | 固定点数止损 | 开仓时 | SL = open ± fixed_pips * pip |
通用;新手 EA |
| 2 | 固定金额止损(按风险反推手数) | 开仓时 | lots = risk_amount / loss_per_lot |
稳健风控 |
| 3 | ATR 倍数止损 | 开仓时 | SL = open ∓ atr * multiplier |
趋势/波动跟随 |
| 4 | 波动率范围过滤止损 | 开仓前 | if atr < min or atr > max: 拒绝 |
规避极端行情 |
| 5 | 结构位止损(Swing 高/低点) | 开仓时 | SL = open ∓ (price - swing_extreme) |
S/R 打法 |
| 6 | 一目均衡云图结构止损 | 开仓时 | SL = 前引带 A/B 或基准线 |
一目策略 |
| 7 | 移动平均线止损(MA Trailing) | 每 tick | if price 穿越 MA: 平仓;否则 SL = MA |
趋势跟踪 |
| 8 | 吊灯止损(Chandelier Exit) | 每 tick | SL = max(high_N) - k * ATR |
趋势跟随 |
| 9 | PSAR 止损 | 每 tick | SL = PSAR 值 |
反转识别 |
| 10 | 经典移动止损(Trail Start/Stop/Step) | 每 tick | 触发→距离→步长 三层控制 | 通用追踪 |
| 11 | ATR 移动止损 | 每 tick | SL = current ∓ ATR * mult,仅收紧 |
波动自适应追踪 |
| 12 | 激进 R 倍数追踪止损 | 每 tick | 盈利达 N×R 后启动,短距离追踪 | 剥头皮 |
| 13 | 保本止损(固定阈值) | 每 tick | if profit_pips >= trigger: SL = open |
通用 |
| 14 | 保本止损(带偏移) | 每 tick | if profit >= trigger: SL = open + offset |
锁盈 |
| 15 | 分批止盈/分批止损(阶梯 TP) | 每 tick | 分档比例平仓,剩余上移 SL | 波段策略 |
| 16 | 时间止损 | 每 tick | if hold_time > max_minutes: 平仓 |
剥头皮/日内 |
| 17 | 动量反转退出 | 每 tick | if momentum 反转: 市价平仓 |
剥头皮 |
| 18 | 网格/金字塔对冲止损 | 每次加仓 | 每层 SL=上一层开仓价;RR 决定 TP | 逆势策略 |
| 19 | 账户净值追踪止损 | 每 tick | equity <= peak - trail * peak: 全平 |
账户级 |
| 20 | 账户最大回撤止损 | 每 tick | equity/equity_peak - 1 <= -max_drawdown: 全平 |
账户级 |
| 21 | 每日亏损百分比止损 | 每 tick | if daily_pnl/balance <= -limit: 停止交易 |
账户级 |
| 22 | 交易次数限制 | 开仓前 | 按日/会话/小时限制 | 账户级 |
| 23 | 冷却时间止损 | 开仓前 | 亏损后/开仓后 N 分钟内禁开 | 账户级 |
| 24 | 时段过滤 | 开仓前 | 只在允许会话内开仓 | 账户级 |
| 25 | 点差上限过滤 | 开仓前 | if spread > max_spread: 拒绝 |
账户级 |
| 26 | 新闻/事件止损 | 每 tick | 事件窗口内全平+关闭交易 | 宏观事件 |
2. 初始止损类(开仓时确定)
2.1 固定点数止损
最简单的形式,开仓时按点数决定 SL 位置。
def set_fixed_point_stop(pos: Position, broker: Broker, pips: int):
if pos.side == "buy":
new_sl = pos.open_price - pips * broker.pip
else:
new_sl = pos.open_price + pips * broker.pip
new_sl = broker.normalize(new_sl)
modify_stop_loss(pos, new_sl)
参数:pips = 止损距离(pips)。
知识点:MQL5 中常见写法 Ask - 100 * _Point,100 点通常按 5 位小数的 10 个 pip 换算,跨品种需要判断 digits 是否为 3 或 5。移植时建议直接用 pip 单位,屏蔽 point/pip 换算。
2.2 固定金额止损(风险百分比仓位)
以"愿意亏多少钱"倒推手数与止损的组合。
def calc_lot_by_risk_percent(account: Account, broker: Broker,
open_price: float, sl_price: float,
risk_percent: float) -> float:
sl_distance = abs(open_price - sl_price)
if sl_distance <= 0 or broker.tick_value <= 0 or broker.tick_size <= 0:
return 0.0
risk_amount = account.balance * risk_percent / 100.0
loss_per_lot = (sl_distance / broker.tick_size) * broker.tick_value
if loss_per_lot <= 0:
return 0.0
lots = risk_amount / loss_per_lot
lots = max(broker.volume_min, min(lots, broker.volume_max))
if broker.volume_step > 0:
lots = math.floor(lots / broker.volume_step) * broker.volume_step
return broker.normalize(lots, 2)
参数:
risk_percent:单笔风险占总资金的百分比(常见 0.5%~3%)。- 返回值:建议手数,最终需与实际止损一起使用才能锁定风险。
知识点:这是几乎所有成熟交易系统的基石。原 MQL5 代码中 lossPerLot = (slDist / tickSize) * tickValue 是最核心的公式,跨品种通用。
2.3 ATR 倍数止损
按真实波幅 ATR 决定 SL 距离,自动适应波动。
def set_atr_stop(pos: Position, broker: Broker,
symbol: str, atr_period: int = 14,
atr_mult: float = 1.5, shift: int = 1):
atr = get_indicator(symbol, "ATR", atr_period, shift)
if atr <= 0:
return
sl_distance = atr * atr_mult
# 强制不低于经纪商最小止损距离
sl_distance = max(sl_distance, broker.stop_level_points * broker.point)
if pos.side == "buy":
new_sl = pos.open_price - sl_distance
else:
new_sl = pos.open_price + sl_distance
modify_stop_loss(pos, broker.normalize(new_sl))
参数:
atr_period:ATR 周期(默认 14)。atr_mult:ATR 倍数(0.8 紧致,1.5~3 宽松)。shift:ATR 取哪根 K 线(1 = 已收盘的前一根,最常用)。
知识点:
shift=1避免用未收盘 K 线的 ATR(数值不稳定)。- 必须强制 ≥
stop_level_points,否则经纪商会拒单。
2.4 ATR + 结构位止损(取最大者)
在剥头皮/激进模式下,把 ATR 止损与最近 N 根 K 线的高低点结构位合并,取距离更大者(更保守)。
def set_atr_or_swing_stop(pos: Position, broker: Broker,
symbol: str, timeframe: str,
atr_mult: float = 0.8, atr_period: int = 14,
lookback_bars: int = 10):
atr = get_indicator(symbol, "ATR", atr_period, 1)
atr_distance = atr * atr_mult
bars = get_bars(symbol, timeframe, lookback_bars)
last_price = broker.current_ask(symbol) if pos.side == "buy" \
else broker.current_bid(symbol)
if pos.side == "buy":
swing_low = min(b.low for b in bars)
swing_distance = last_price - swing_low
else:
swing_high = max(b.high for b in bars)
swing_distance = swing_high - last_price
sl_distance = max(atr_distance, swing_distance)
sl_distance = max(sl_distance, broker.stop_level_points * broker.point)
new_sl = last_price - sl_distance if pos.side == "buy" else last_price + sl_distance
modify_stop_loss(pos, broker.normalize(new_sl))
知识点:这是"机械止损 + 结构位"的组合。MathMax(atr_dist, swing_dist) 是关键,避免止损被随机噪声或局部波动打掉。
2.5 一目均衡云图结构止损
用一目均衡表(Ichimoku)的前引带 A/B 与基准线确定 SL 位置。
def set_ichimoku_stop(pos: Position, broker: Broker,
senkou_span_a: float, senkou_span_b: float,
kijun: float):
if pos.side == "buy":
# 前引带 B < 前引带 A,且基准线在中间 → 结构清晰,SL 放到前引带 B
if senkou_span_b < senkou_span_a and senkou_span_b < kijun < senkou_span_a:
new_sl = senkou_span_b
# 前引带 A < 前引带 B,且基准线在中间 → SL 放到前引带 A
elif senkou_span_a < senkou_span_b and kijun > senkou_span_a and kijun < senkou_span_b:
new_sl = senkou_span_a
else:
new_sl = kijun # 结构不清时退化为基准线止损
else:
# SELL 方向对称逻辑(略)
...
modify_stop_loss(pos, broker.normalize(new_sl))
知识点:结构位止损在趋势明确时能提供比固定点数更好的风控,因为止损位置在自然支撑/阻力之外。
3. 波动率类过滤(开仓前拦截)
3.1 ATR 上下限过滤
只在合理波动区间内开仓,避免极端行情。
def volatility_guard(symbol: str, atr_period: int = 14,
min_atr: float = 0.0003, max_atr: float = 0.003) -> bool:
atr = get_indicator(symbol, "ATR", atr_period, 1)
if atr <= 0:
return False
return min_atr <= atr <= max_atr
参数:
min_atr:过低会缺乏机会,或触发"死水"行情。max_atr:过高说明已进入异常波动,风险放大。
3.2 ADR / 波动带过滤(拓展思路)
def volatility_band_guard(symbol: str, timeframe: str,
lookback: int = 20,
low_pct: float = 0.2, high_pct: float = 0.8):
"""取最近 N 根 K 线的振幅作为波动区间,
当前振幅应在历史 [low_pct, high_pct] 分位之间才允许交易。"""
bars = get_bars(symbol, timeframe, lookback)
ranges = [(b.high - b.low) for b in bars]
current_range = ranges[-1]
sorted_ranges = sorted(ranges)
low_threshold = sorted_ranges[int(low_pct * len(sorted_ranges))]
high_threshold = sorted_ranges[int(high_pct * len(sorted_ranges))]
return low_threshold <= current_range <= high_threshold
4. 移动止损类(持仓期调整)
4.1 经典移动止损(Trail Start / Trail Stop / Trail Step)
三层控制:触发启动 → 距离跟踪 → 步长保护。
def update_classic_trailing(pos: Position, broker: Broker,
trail_start_pips: float,
trail_stop_pips: float,
trail_step_pips: float):
if pos.stop_loss <= 0 and pos.unrealized_pnl <= 0:
return # 无初始 SL 时通常依赖 EA 首次触发
start_dist = trail_start_pips * broker.pip
stop_dist = trail_stop_pips * broker.pip
step_dist = trail_step_pips * broker.pip
current_price = broker.current_bid(symbol=pos.symbol) if pos.side == "buy" \
else broker.current_ask(symbol=pos.symbol)
open_dist = abs(current_price - pos.open_price)
if pos.side == "buy":
# 只有价格上涨超过启动距离才启动追踪
if open_dist < start_dist:
return
candidate = current_price - stop_dist
# 候选必须优于当前 SL(BUY 时更高)
if candidate <= pos.stop_loss:
return
# 步长保护:不足一个 step 时,推进一个 step
if pos.stop_loss > 0 and (candidate - pos.stop_loss) < step_dist:
candidate = pos.stop_loss + step_dist
else:
if open_dist < start_dist:
return
candidate = current_price + stop_dist
if candidate >= pos.stop_loss:
return
if pos.stop_loss > 0 and (pos.stop_loss - candidate) < step_dist:
candidate = pos.stop_loss - step_dist
candidate = broker.normalize(candidate)
modify_stop_loss(pos, candidate)
参数:
trail_start_pips:触发距离。价格离开开仓价多少才启动追踪(如 50 pip)。trail_stop_pips:跟踪距离。SL 与现价之间的固定距离(如 20 pip)。trail_step_pips:步长。一次修改 SL 的最小幅度(如 10 pip),抑制高频修改。
知识点:
- 单向收紧是隐含规则:BUY 只上移,SELL 只下移。
- 步长保护能显著降低服务器请求与手续费。
- 修改前必须
new_sl严格优于pos.stop_loss,否则跳过。
4.2 ATR 移动止损
用 ATR 动态决定 SL 与现价的距离,波动大时距离远,波动小时距离近。
def update_atr_trailing(pos: Position, broker: Broker,
atr_period: int = 14, atr_mult: float = 1.0,
atr_shift: int = 1):
atr = get_indicator(pos.symbol, "ATR", atr_period, atr_shift)
if atr <= 0:
return
if pos.side == "buy":
bid = broker.current_bid(symbol=pos.symbol)
candidate = bid - atr * atr_mult
# 必须满足经纪商最小止损距离
if candidate > bid - broker.stop_level_points * broker.point:
return
# 只上移
if candidate <= pos.stop_loss:
return
else:
ask = broker.current_ask(symbol=pos.symbol)
candidate = ask + atr * atr_mult
if candidate < ask + broker.stop_level_points * broker.point:
return
# 只下移
if candidate >= pos.stop_loss:
return
# 按 tick_size 对齐精度
if broker.tick_size > 0:
candidate = round(candidate / broker.tick_size) * broker.tick_size
modify_stop_loss(pos, broker.normalize(candidate))
参数:
atr_period:ATR 周期。atr_mult:倍数。倍数为 1 时 SL 距离 ≈ 平均波动幅度。
知识点:
- 相比固定 pip 追踪,ATR 追踪能自动适应不同品种和时间段。
- 一定要对齐
tick_size,避免精度错误被经纪商拒绝。
4.3 移动平均线止损(MA Trailing)
将 SL 挂到 MA 值;如果价格已穿越 MA,则直接市价平仓。
def update_ma_trailing(pos: Position, broker: Broker,
symbol: str, ma_period: int,
ma_shift: int = 1):
ma = get_indicator(symbol, "MA", ma_period, ma_shift)
if ma <= 0:
return
current_price = broker.current_bid(symbol) if pos.side == "buy" \
else broker.current_ask(symbol)
# 触发条件:价格已穿越均线(趋势反转)
if pos.side == "buy" and ma > current_price:
close_position(pos)
return
if pos.side == "sell" and ma < current_price:
close_position(pos)
return
# 否则把 SL 挂到 MA 值(仅当与当前 SL 不同时才修改)
if abs(pos.stop_loss - ma) > broker.point:
modify_stop_loss(pos, broker.normalize(ma))
参数:
ma_period:均线周期(如 20、50、200)。ma_shift:取哪根 K 线的均线值(1 = 已收盘前一根)。
知识点:
- "穿越均线 = 市价平仓" 是趋势反转的强势信号,比继续持有到止损更果断。
- 均线追踪天然具备单向收紧特性(BUY 时 MA 越上移 SL 越高)。
4.4 吊灯止损(Chandelier Exit)
以最近 N 根 K 线最高价(或最低价)为基准,减去/加上 k × ATR 得到 SL。
def update_chandelier(pos: Position, broker: Broker,
symbol: str, timeframe: str,
chandelier_period: int = 22,
atr_period: int = 22,
chandelier_mult: float = 3.0):
bars = get_bars(symbol, timeframe, chandelier_period)
atr = get_indicator(symbol, "ATR", atr_period, 1)
if not bars or atr <= 0:
return
if pos.side == "buy":
highest = max(b.high for b in bars)
candidate = highest - chandelier_mult * atr
else:
lowest = min(b.low for b in bars)
candidate = lowest + chandelier_mult * atr
# 只收紧
if pos.side == "buy" and candidate <= pos.stop_loss:
return
if pos.side == "sell" and candidate >= pos.stop_loss:
return
modify_stop_loss(pos, broker.normalize(candidate))
参数:
chandelier_period:回看 K 线数(常见 22)。chandelier_mult:倍数(常见 2~3)。
知识点:吊灯止损本质是"结构位 + ATR"的融合,兼顾了止损的自然支撑属性和波动自适应。适合趋势跟踪策略。
4.5 PSAR 止损
用 Parabolic SAR 值作为 SL,一旦价格突破 SAR 即反向平仓。
def update_psar_stop(pos: Position, broker: Broker,
symbol: str, timeframe: str):
psar = get_indicator(symbol, "PSAR", 0, shift=0) # 取当前值
psar_prev = get_indicator(symbol, "PSAR", 0, shift=1)
if psar <= 0 or psar_prev <= 0:
return
if pos.side == "buy":
# 价格跌破 SAR → 平仓
if broker.current_bid(symbol) < psar:
close_position(pos)
return
if psar <= pos.stop_loss:
return # 只收紧
else:
if broker.current_ask(symbol) > psar:
close_position(pos)
return
if psar >= pos.stop_loss:
return
modify_stop_loss(pos, broker.normalize(psar))
4.6 激进 R 倍数追踪止损(剥头皮)
先在盈利达到 N 个 R 后启动,然后用极小距离+步长追踪。
def update_aggressive_trailing(pos: Position, broker: Broker,
initial_risk: float, # 开仓时记录的初始风险距离
activate_r: float = 0.5,
trail_pips: float = 3.0,
step_pips: float = 1.0):
if initial_risk <= 0:
return
profit_pips = (pos.unrealized_pnl / broker.tick_value) / broker.tick_size
if pos.side == "sell":
profit_pips = -profit_pips
activate_threshold = initial_risk * activate_r
if profit_pips * broker.pip < activate_threshold:
return # 盈利未达阈值
stop_dist = trail_pips * broker.pip
step_dist = step_pips * broker.pip
current_price = broker.current_bid(symbol=pos.symbol) if pos.side == "buy" \
else broker.current_ask(symbol=pos.symbol)
if pos.side == "buy":
candidate = current_price - stop_dist
if candidate <= pos.stop_loss:
return
if pos.stop_loss > 0 and (candidate - pos.stop_loss) < step_dist:
candidate = pos.stop_loss + step_dist
else:
candidate = current_price + stop_dist
if candidate >= pos.stop_loss:
return
if pos.stop_loss > 0 and (pos.stop_loss - candidate) < step_dist:
candidate = pos.stop_loss - step_dist
modify_stop_loss(pos, broker.normalize(candidate))
参数:
initial_risk:开仓时记录的初始 SL 距离(R 的定义)。activate_r:启动倍数,如 0.5 表示盈利 0.5R 后启动。trail_pips、step_pips:小数值,用于剥头皮级别的紧致追踪。
知识点:一定要在开仓时把 initial_risk 存到持仓的结构体或注释里,因为保本/移动止损会把 SL 移走,之后再算就失去"原始 R" 的含义。
5. 保本止损类
5.1 固定盈利阈值保本
浮盈达到阈值后立即把 SL 移到开仓价。
def update_breakeven_simple(pos: Position, broker: Broker,
trigger_pips: float):
trigger_dist = trigger_pips * broker.pip
if pos.side == "buy":
profit_dist = broker.current_bid(symbol=pos.symbol) - pos.open_price
else:
profit_dist = pos.open_price - broker.current_ask(symbol=pos.symbol)
if profit_dist >= trigger_dist:
# 已经保本就跳过(BUY: SL >= open 即可)
if pos.side == "buy" and pos.stop_loss >= pos.open_price:
return
if pos.side == "sell" and pos.stop_loss <= pos.open_price:
return
# 目标:SL = open_price
modify_stop_loss(pos, broker.normalize(pos.open_price))
参数:
trigger_pips:触发保本所需浮盈(如 5 pip)。
知识点:
- 判断"是否已保本"要比较 SL 与 open_price,而不是判断是否已修改过——因为可能已经用移动止损把 SL 移到了更远的位置。
- 常见变体是"用金额"触发(
profit >= 0.5 美元),跨品种一致性差,不推荐。
5.2 保本 + 偏移(锁定小利)
保本之上再加一段偏移,确保平掉时是净盈利。
def update_breakeven_offset(pos: Position, broker: Broker,
trigger_pips: float, offset_pips: float):
trigger_dist = trigger_pips * broker.pip
offset_dist = offset_pips * broker.pip
if pos.side == "buy":
bid = broker.current_bid(symbol=pos.symbol)
if (bid - pos.open_price) < trigger_dist:
return
target = pos.open_price + offset_dist
if target <= pos.stop_loss:
return
else:
ask = broker.current_ask(symbol=pos.symbol)
if (pos.open_price - ask) < trigger_dist:
return
target = pos.open_price - offset_dist
if target >= pos.stop_loss:
return
modify_stop_loss(pos, broker.normalize(target))
参数:
offset_pips:超过开仓价的额外锁利距离。
5.3 分批保本(阶梯保本)
在多个盈利档位分别把 SL 移到 open + level × pip。
def update_stepped_breakeven(pos: Position, broker: Broker,
levels: list):
"""levels = [(trigger_pips, target_pips), ...]
例:[(5, 0), (15, 8), (30, 20)]"""
if pos.side == "buy":
bid = broker.current_bid(symbol=pos.symbol)
profit_pips = (bid - pos.open_price) / broker.pip
else:
ask = broker.current_ask(symbol=pos.symbol)
profit_pips = (pos.open_price - ask) / broker.pip
for trigger_pips, target_pips in levels:
if profit_pips >= trigger_pips:
if pos.side == "buy":
target = pos.open_price + target_pips * broker.pip
if target <= pos.stop_loss:
return # 已达成,且后续 tier 距离更远,停止处理
else:
target = pos.open_price - target_pips * broker.pip
if target >= pos.stop_loss:
return
modify_stop_loss(pos, broker.normalize(target))
return # 每 tick 只处理最近触发的一档
6. 分批平仓 / 阶梯止盈
6.1 分批止盈 + SL 上移(保留剩余单继续跑)
class StepManager:
"""每个持仓关联一个 StepManager,记录已触发档位。"""
def __init__(self):
self.done_levels: set = set()
def check_partial_take_profit(pos: Position, broker: Broker,
step_mgr: StepManager,
steps: list):
"""steps = [(rr, partial_pct), ...]
rr = 相对初始风险的回报倍数(R 倍数)
partial_pct = 该档位平掉的持仓比例
"""
initial_risk = pos.initial_risk # 开仓时存下的初始 SL 距离
if initial_risk <= 0:
return
if pos.side == "buy":
profit_pips = (broker.current_bid(symbol=pos.symbol) - pos.open_price) / broker.pip
else:
profit_pips = (pos.open_price - broker.current_ask(symbol=pos.symbol)) / broker.pip
current_r = (profit_pips * broker.pip) / initial_risk
for level_idx, (rr_threshold, partial_pct) in enumerate(steps):
if level_idx in step_mgr.done_levels:
continue
if current_r < rr_threshold:
break
close_size = pos.size * partial_pct
close_size = max(broker.volume_min,
math.floor(close_size / broker.volume_step) * broker.volume_step)
if close_size >= pos.size:
close_position(pos)
return
if close_partial(pos, close_size):
step_mgr.done_levels.add(level_idx)
# 剩余部分 SL 上移到本档止盈价附近,实现"锁利"
lock_sl = pos.open_price + (rr_threshold * initial_risk - broker.stop_level_points * broker.point) \
if pos.side == "buy" else \
pos.open_price - (rr_threshold * initial_risk + broker.stop_level_points * broker.point)
modify_stop_loss(pos, broker.normalize(lock_sl))
知识点:
- 每次成功平仓后立刻把剩余仓位的 SL 上移/下移,避免回吐。
- 关闭后记得更新 step 状态,避免下个 tick 重复触发。
6.2 网格/金字塔对冲止损
网格策略中,每一层持仓都有独立 SL(上一层的开仓价)与 TP(按 RR 计算)。总层数达到上限时切换到"止损+止盈"保守模式。
class GridStopLoss:
def __init__(self, symbol: str, magic: int,
max_layers: int = 7,
rr: float = 2.0,
lot_chain: list = None):
self.symbol = symbol
self.magic = magic
self.max_layers = max_layers
self.rr = rr
self.lot_chain = lot_chain or [0.01]
def process(self, positions: list, broker: Broker):
# positions 已按开仓时间排序,layer=1 是最早一单
if not positions:
return
layers = len(positions)
last = positions[-1]
if layers >= self.max_layers:
# 达到上限:切换到保护模式,为第 1 单设置 SL/TP
self._enforce_final_sl_tp(positions[0], broker)
return
# 计算下一层的入场价与止损
layer_no = layers + 1
# 对称网格:偶数层挂在第 1 单开仓价,奇数层挂在第 2 单开仓价
if layer_no == 2:
entry = last.stop_loss # 用最后一层的止损做反向挂单
elif layer_no % 2 == 0:
entry = positions[0].open_price
else:
entry = positions[1].open_price if len(positions) > 1 else last.open_price
# 每层 SL = 上一层的开仓价
layer_sl = positions[-2].open_price if layers > 1 else last.open_price
# TP = 开仓价 ± SL 距离 × RR
if last.side == "buy":
sl_dist = last.open_price - layer_sl
tp = last.open_price + sl_dist * self.rr
else:
sl_dist = layer_sl - last.open_price
tp = last.open_price - sl_dist * self.rr
lot = self.lot_chain[layer_no - 1] if layer_no - 1 < len(self.lot_chain) else self.lot_chain[-1]
# 发送反向挂单 (略)
def _enforce_final_sl_tp(self, first_pos, broker):
# 达到最大层数后,为最早的仓位重新设置 SL/TP 以锁定最终风险
...
知识点:
- 网格的核心是"每层 SL = 上一层开仓价",保证单笔亏损可控。
- 到最大层后必须停止加仓并启用保护性 SL/TP,否则回撤会失控。
- 用 RR 决定 TP,是网格策略常见做法。
7. 时间类与信号类退出
7.1 时间止损
持仓超过指定分钟数即平仓,适用于剥头皮/日内。
def update_time_stop(pos: Position, broker: Broker,
max_hold_minutes: int = 30):
hold_seconds = (now() - pos.open_time).total_seconds()
if hold_seconds >= max_hold_minutes * 60:
close_position(pos)
参数:max_hold_minutes = 0 表示禁用。
知识点:
- 时间止损特别适合剥头皮,防止"死锁"持仓。
- 也可结合"持仓 N 分钟未盈利则平仓"的变体:
if hold_time > threshold and unrealized_pnl <= 0: close。
7.2 动量反转退出
def update_momentum_exit(pos: Position, broker: Broker,
symbol: str, threshold: float = 0.0003):
momentum = get_indicator(symbol, "MOM", 14, shift=0) # 或自研动量指标
if pos.side == "buy" and momentum < -threshold:
close_position(pos)
elif pos.side == "sell" and momentum > threshold:
close_position(pos)
参数:threshold 单位通常是百分比。
8. 账户级风控止损(全局视角)
8.1 账户净值追踪止损(隐藏 SL 线)
跟踪账户权益峰值,跌破 peak × (1 - trail%) 则全平所有仓位。
class EquityTrailingStop:
def __init__(self, trail_percent: float = 5.0,
trail_amount: float = 0.0):
self.peak_equity = 0.0
self.trail_percent = trail_percent # 百分比模式
self.trail_amount = trail_amount # 金额模式(美元/本币)
def process(self, account: Account, positions: list, broker: Broker):
if account.equity > self.peak_equity:
self.peak_equity = account.equity
if self.trail_percent > 0:
stop_line = self.peak_equity * (1 - self.trail_percent / 100)
elif self.trail_amount > 0:
stop_line = self.peak_equity - self.trail_amount
else:
return
if account.equity <= stop_line:
for pos in positions:
close_position(pos)
参数:trail_percent = 5% 表示允许从峰值回撤 5% 后强制平仓。
知识点:
- 这是"止损放在账户层"而不是"放在订单层"的思路,对防止爆仓非常有效。
- 通常与"日亏损百分比"、"最大回撤百分比"组合使用。
8.2 每日亏损百分比止损
class DailyLossStop:
def __init__(self, max_daily_loss_percent: float = 3.0):
self.day_start_balance = 0.0
self.current_day = None
self.max_daily_loss_percent = max_daily_loss_percent
def process(self, account: Account, positions: list) -> bool:
today = now().date()
if today != self.current_day:
self.current_day = today
self.day_start_balance = account.balance
if self.day_start_balance <= 0:
return True
daily_pnl = account.equity - self.day_start_balance
max_loss = self.day_start_balance * self.max_daily_loss_percent / 100
if daily_pnl < -max_loss:
# 触发:平仓并今日停止交易
for pos in positions:
close_position(pos)
return False # 不允许继续交易
return True
知识点:
- 日初余额应记在"当天第一次 tick",而不是账户启动时。
- 触发后不仅平仓,还应在当日剩余时间内禁开仓。
8.3 交易次数限制(日/会话/小时)
class TradeCountGuard:
def __init__(self, max_per_day=30, max_per_session=10, max_per_hour=20):
self.per_day = 0
self.per_session = 0
self.per_hour = 0
self.max_per_day = max_per_day
self.max_per_session = max_per_session
self.max_per_hour = max_per_hour
self.current_day = None
self.current_session = None
self.current_hour = None
self.day_start_balance = 0.0
def rollover(self, account: Account):
today = now().date()
session = current_session() # Asia / London / NY / Overlap / None
hour = now().hour
if today != self.current_day:
self.current_day = today
self.per_day = 0
self.day_start_balance = account.balance
if session != self.current_session:
self.current_session = session
self.per_session = 0
if hour != self.current_hour:
self.current_hour = hour
self.per_hour = 0
def can_open(self) -> bool:
if self.per_day >= self.max_per_day:
return False
if self.per_session >= self.max_per_session:
return False
if self.per_hour >= self.max_per_hour:
return False
return True
def on_open(self):
self.per_day += 1
self.per_session += 1
self.per_hour += 1
知识点:三层计数器独立重置,会话切换时只重置 session 计数器。
8.4 冷却时间止损
亏损后或开仓后一段时间内禁止开仓。
class CooldownGuard:
def __init__(self, min_seconds_between_trades: int = 300,
loss_cooldown_minutes: int = 30):
self.last_trade_time = None
self.last_loss_time = None
self.min_seconds_between_trades = min_seconds_between_trades
self.loss_cooldown_seconds = loss_cooldown_minutes * 60
def can_open(self) -> bool:
now_t = now().timestamp()
if self.last_trade_time and \
now_t < self.last_trade_time + self.min_seconds_between_trades:
return False
if self.last_loss_time and \
now_t < self.last_loss_time + self.loss_cooldown_seconds:
return False
return True
def on_open(self):
self.last_trade_time = now().timestamp()
def on_loss_closed(self):
self.last_loss_time = now().timestamp()
8.5 会话/时段过滤
只在指定交易时段开仓(Asia/London/NY/Overlap)。
SESSIONS = {
"asia": (0, 0, 8, 0), # GMT
"london": (7, 0, 16, 0),
"ny": (13, 0, 21, 0),
"overlap":(12, 0, 16, 0),
}
def in_session(gmt_minutes: int, session_name: str) -> bool:
sh, sm, eh, em = SESSIONS[session_name]
s = sh * 60 + sm
e = eh * 60 + em
return s <= gmt_minutes < e
def current_session(now_gmt_minutes: int, enabled: set) -> str:
if "overlap" in enabled and in_session(now_gmt_minutes, "overlap"):
return "overlap"
for s in ["asia", "london", "ny"]:
if s in enabled and in_session(now_gmt_minutes, s):
return s
return None
知识点:
- 使用 GMT 时间而非本地时间,避免夏令时问题。
- "Overlap"(伦敦-纽约重叠时段)通常是波动最剧烈的时段,很多策略只在此时段交易。
8.6 点差过滤
def spread_guard(symbol: str, broker: Broker, max_spread_points: int) -> bool:
spread = broker.current_ask(symbol) - broker.current_bid(symbol)
spread_points = spread / broker.point
return spread_points <= max_spread_points
9. 事件类止损
9.1 新闻止损(Event Stopper)
在重大经济事件窗口内强制平仓 + 关闭自动交易,事件结束后自动恢复。
class NewsStopper:
def __init__(self,
min_before: int = 5, # 事件前 N 分钟开始平仓
min_before_zero: int = 60, # 事件前 N 分钟开始"零利润平仓"窗口
min_after: int = 45, # 事件后 N 分钟内保持关闭
keywords: list = None,
currencies: list = None,
close_profit: float = 1.0,
update_interval_hours: int = 2):
self.min_before = min_before * 60
self.min_before_zero = min_before_zero * 60
self.min_after = min_after * 60
self.keywords = keywords or ["CPI", "FOMC", "Non-Farm", "NFP", "GDP", "PCE", "PMI", "Retail"]
self.currencies = currencies or ["USD", "EUR", "GBP", "JPY", "CAD"]
self.close_profit = close_profit
self.update_interval = update_interval_hours * 3600
self.last_fetch = 0
self.allow_trade = True
self.events = [] # list of (currency, title, time, impact)
def fetch_calendar(self):
# 从财经日历 API 拉取未来 24 小时的高影响事件
self.events = external_calendar_fetch(self.currencies, self.keywords)
self.last_fetch = now().timestamp()
def _find_active_event(self) -> str:
now_t = now().timestamp()
for currency, title, event_time, impact in self.events:
if event_time - self.min_before <= now_t <= event_time + self.min_after:
return currency
return None
def _in_zero_profit_window(self) -> str:
now_t = now().timestamp()
for currency, title, event_time, impact in self.events:
if event_time - self.min_before_zero <= now_t <= event_time:
return currency
return None
def process(self, account: Account, positions: list, broker: Broker):
if now().timestamp() - self.last_fetch >= self.update_interval:
self.fetch_calendar()
# 阶段 1:零利润提前平仓
zero_pair = self._in_zero_profit_window()
if zero_pair and self.allow_trade and account.equity - account.balance >= self.close_profit:
target = [p for p in positions if p.symbol == zero_pair] if zero_pair else positions
for pos in target:
close_position(pos)
self.allow_trade = False
# 可关闭自动交易(略)
# 阶段 2:事件窗口全平
active = self._find_active_event()
if active and self.allow_trade:
for pos in positions:
close_position(pos)
self.allow_trade = False
# 阶段 3:事件结束恢复
if not active and not self.allow_trade:
self.allow_trade = True
参数:
min_before/min_after:事件窗口边界。min_before_zero:更宽松的"零利润平仓"窗口,允许在事件前较长时间就把浮盈仓位提前平仓。keywords:按标题过滤,只关注真正高影响的事件。currencies:按货币过滤,只关心与自己持仓相关的事件。close_profit:零利润平仓所需的最小利润(默认 1 美元,保证交易成本后仍略盈利)。
知识点:
- 三层时机非常关键:
min_before_zero→min_before→min_after,从宽到窄逐级收紧。 - 平仓后应立即关闭自动交易,防止新单在事件期间被打。
- 恢复交易要在
min_after之后,且要重新检查账户状态。
10. 主循环装配(推荐调用顺序)
把所有止损方法组合成"入场 → 持仓管理 → 账户风控"的三层调度:
def on_tick(account, broker, symbol, positions, config):
# ============= 第 1 层:账户级风控(每 tick) =============
# 1.1 会话/时段切换(重置计数器)
session = current_session(...)
if session != last_session:
trade_guard.on_session_change()
last_session = session
# 1.2 每日亏损检查(触发即全平并停止交易)
if not daily_loss_stop.process(account, positions):
halt_trading_today = True
# 1.3 账户净值追踪止损
if equity_trailing_stop.process(account, positions, broker):
halt_trading_today = True
# 1.4 交易次数限制
if not trade_guard.can_open():
halt_trading_today = True
# 1.5 冷却时间
if not cooldown_guard.can_open():
halt_trading_today = True
# 1.6 新闻窗口
if not news_stopper.process(account, positions, broker):
halt_trading_today = True
# ============= 第 2 层:持仓管理(每 tick) =============
for pos in positions:
# 2.1 时间止损(优先,简单粗暴)
if config.scalping_mode and config.max_hold_minutes > 0:
update_time_stop(pos, broker, config.max_hold_minutes)
# 2.2 动量退出(剥头皮)
if config.scalping_mode and config.use_momentum_exit:
update_momentum_exit(pos, broker, symbol, config.momentum_threshold)
# 2.3 移动止损(互斥:激进追踪 vs 经典追踪)
if config.aggressive_mode and config.use_aggressive_trailing:
update_aggressive_trailing(pos, broker,
pos.initial_risk,
config.aggr_activate_r,
config.aggr_trail_pips,
config.aggr_step_pips)
elif config.use_trailing:
update_classic_trailing(pos, broker,
config.trail_start_pips,
config.trail_stop_pips,
config.trail_step_pips)
# 2.4 ATR 追踪(可与经典追踪二选一)
if config.use_atr_trailing:
update_atr_trailing(pos, broker,
config.atr_period, config.atr_mult)
# 2.5 吊灯 / PSAR 追踪(互斥)
if config.use_chandelier:
update_chandelier(pos, broker, symbol, config.timeframe,
config.chandelier_period, config.atr_period,
config.chandelier_mult)
# 2.6 保本(独立,可与追踪并存)
if config.use_break_even:
update_breakeven_offset(pos, broker,
config.be_trigger_pips,
config.be_offset_pips)
# 2.7 分批止盈
if config.use_partial_tp:
step_mgr = get_step_mgr(pos.ticket)
check_partial_take_profit(pos, broker, step_mgr, config.steps)
# 2.8 均线跟随(趋势策略专用)
if config.use_ma_trailing:
update_ma_trailing(pos, broker, symbol, config.ma_period)
# ============= 第 3 层:入场判断 =============
if not halt_trading_today and signal:
# 3.1 波动率过滤
if not volatility_guard(symbol, config.atr_period,
config.min_atr, config.max_atr):
return
# 3.2 点差过滤
if not spread_guard(symbol, broker, config.max_spread_points):
return
# 3.3 初始止损(三选一)
if config.use_atr_stop:
initial_sl = calc_initial_sl_atr(open_price, symbol, broker,
config.atr_period, config.atr_mult)
elif config.use_swing_stop:
initial_sl = calc_initial_sl_swing(open_price, symbol, broker,
config.timeframe, config.lookback_bars)
else:
initial_sl = calc_initial_sl_fixed(open_price, broker, config.fixed_sl_pips)
# 3.4 强制不低于 stop_level
if open_price - initial_sl < broker.stop_level_points * broker.point:
initial_sl = open_price - broker.stop_level_points * broker.point
# 3.5 风险百分比算手数
lots = calc_lot_by_risk_percent(account, broker, open_price, initial_sl,
config.risk_percent)
# 3.6 发送订单(略)
11. 移植注意事项
11.1 单向收紧规则(最重要)
规则:BUY 单只上移 SL,SELL 单只下移 SL。任何时候都不能把 SL 移动得比当前更"不利"。
# BUY: 只有新 SL > 旧 SL 才允许
if pos.side == "buy" and new_sl <= pos.stop_loss:
return # 不允许
# SELL: 只有新 SL < 旧 SL 才允许
if pos.side == "sell" and new_sl >= pos.stop_loss:
return
违反此规则会导致:
- 服务器返回
10016/ERR_TRADE_INVALID_STOP_PRICE。 - 更糟糕的是,如果实盘里出现 SL 被"回退",一次反向波动就可能爆仓。
11.2 最小止损距离(StopLevel)
规则:SL 与当前价之间的距离必须 ≥ 经纪商的最小止损距离(SYMBOL_TRADE_STOPS_LEVEL)。
def ensure_min_stop_distance(new_sl, current_price, broker, buffer=1.0):
min_dist = broker.stop_level_points * broker.point * buffer
if abs(new_sl - current_price) < min_dist:
# 二选一:要么拉远到 min_dist,要么放弃本次修改
if new_sl < current_price:
new_sl = current_price - min_dist
else:
new_sl = current_price + min_dist
return new_sl
建议:加一个 buffer=1.0~2.0 的安全系数,避免因市场跳动越过 min_dist。
11.3 冻结价距离(FreezeLevel)
部分经纪商不允许在接近冻结价距离内修改 SL/TP。
if abs(new_sl - current_price) < broker.freeze_level_points * broker.point:
# 跳过本次修改,等待价格走远
return
11.4 精度对齐
- SL/TP 必须对齐到报价精度(
SYMBOL_DIGITS)。 - 修改值必须对齐到
tick_size,否则会被拒绝。
def normalize_sl(new_sl, broker):
if broker.tick_size > 0:
new_sl = round(new_sl / broker.tick_size) * broker.tick_size
new_sl = round(new_sl, broker.digits)
return new_sl
11.5 Point vs Pip
MQL5 中 _Point 是"最小价格单位",但用户习惯用 pip:
- 4 位小数货币对(如 EURUSD=1.1000):1 pip = 10 point。
- 2 位小数货币对(如 USDMXN=17.89):1 pip = 1 point。
- JPY 货币对(如 EURJPY=140.500):1 pip = 10 point。
移植建议:所有参数用 pip 表达,内部通过 broker.pip 统一换算,屏蔽 point/pip 差异。
11.6 修改频率与服务器请求限制
频繁修改 SL 会导致:
- 服务器拒绝(
ERR_TRADE_TOO_MANY_REQUESTS)。 - 手续费累积(部分经纪商按修改次数收费)。
- 回测与实盘偏差(回测按 tick 处理,实盘可能被限流)。
缓解:
- 用
step_pips步长控制(新 SL 与旧 SL 差距不足一个 step 就不修改)。 - 时间间隔控制(如每 5 秒最多修改一次)。
- 修改前比较新旧 SL,一致时跳过。
if abs(new_sl - pos.stop_loss) <= broker.point:
return # 无变化,跳过
11.7 回测 vs 实盘差异
| 差异点 | 回测行为 | 实盘行为 | 影响 |
|---|---|---|---|
| Tick 精度 | 通常 1 秒 M1 tick | 可能几秒才一 tick | 止损触发延迟 |
| 滑点 | 可配置为 0 | 通常 1~5 pip | 移动止损精度下降 |
| StopLevel | 通常不强制 | 严格强制 | 回测止损位置可能实盘无法下单 |
| 冻结价 | 通常不建模 | 严格 | 修改 SL 可能失败 |
| 服务器限流 | 无 | 有 | 高频修改被拒 |
| 数据源 | 经纪商历史 | 实时报价 | 指标值可能微差 |
建议:回测时用 tick data + 模拟 StopLevel/FreezeLevel,最贴近实盘。
11.8 初始风险存储
关键:开仓时记录 initial_risk = |open_price - initial_sl| 到持仓结构体(或注释中)。
原因:
- 保本止损会立刻把 SL 移到 open_price,导致后续再算"当前 R"变成 0。
- R 倍数追踪、分批止盈等依赖"初始 R"的计算必须用它。
# 开仓成功后立刻记录
pos.initial_risk = abs(pos.open_price - pos.stop_loss)
# 或用 magic + 注释的方式记录到订单上,便于重启 EA 后恢复
11.9 从后往前遍历持仓
修改或关闭持仓时,务必从最后一个往前遍历,避免索引错乱。
for i in range(PositionsTotal() - 1, -1, -1):
...
11.10 事件循环与幂等性
每个止损函数应当是幂等的:多次调用不会产生副作用(除了实际的 SL 修改)。
def update_breakeven_simple(pos, broker, trigger_pips):
# 已保本就直接返回,不重复调用 modify
if pos.side == "buy" and pos.stop_loss >= pos.open_price:
return
11.11 魔术号(Magic Number)隔离
多 EA 共存时,务必用 magic 区分订单,避免误改他 EA 的 SL。
if pos.magic_number != my_magic:
continue
11.12 品种精度差异
不同品种的 SL 精度、tick size 差异巨大:
- EURUSD:digits=5, tick_size=0.00001
- USDJPY:digits=3, tick_size=0.001
- XAUUSD(黄金):digits=2, tick_size=0.01
统一使用 broker.normalize() 与 broker.tick_size 处理,避免手工计算出错。
11.13 移动止损与分批平仓的顺序
推荐顺序(从后往前):
- 时间/动量退出(简单直接,先执行)
- 移动止损(激进/经典/ATR/吊灯,二选一)
- 保本(独立,与移动止损可共存)
- 分批止盈(在 SL 已锁定后再执行分批)
理由:先移动 SL 保证剩余仓位有基础保护,再触发分批止盈时,即使后续波动也能保住已锁定部分。
12. 常见策略组合模板
12.1 趋势跟踪(黄金/股票/加密)
初始止损 = ATR × 2
移动止损 = 吊灯(22, 3.0)
保本 = 触发 1.5R 后 SL = open + 0.5 pip
分批止盈 = [2R: 30%, 3R: 30%]
账户级 = 净值追踪 10% + 日亏损 3%
12.2 日内剥头皮
初始止损 = ATR × 0.8 或 M1 结构位取大
移动止损 = 激进追踪(激活 0.5R,距离 3 pip,步长 1 pip)
保本 = 触发 5 pip 后 SL = open
分批止盈 = [1R: 50%, 2R: 全部]
时间止损 = 30 分钟
动量退出 = 阈值 0.03%
账户级 = 日亏损 4% + 每会话最多 10 笔
12.3 波段(周/日线)
初始止损 = 结构位(目一云图或 N 周高低点)
移动止损 = 长期均线(60 MA)或吊灯(55, 3.0)
保本 = 触发 20 pip 后 SL = open
分批止盈 = [1.5R: 25%, 3R: 25%, 5R: 50%]
账户级 = 净值追踪 15% + 日亏损 2%
12.4 网格/对冲
初始止损 = 上一层开仓价
移动止损 = 无(网格策略本身承担波动)
分批止盈 = 按 RR=2 计算每层 TP
总层数 = 7(达到上限强制止损+止盈)
账户级 = 净值追踪 20% + 日亏损 5%
13. 关键参数速查表
| 参数 | 含义 | 典型值 |
|---|---|---|
atr_period |
ATR 周期 | 14 |
atr_mult |
ATR 倍数 | 0.8 / 1.5 / 3 |
trail_start_pips |
追踪启动距离 | 20~50 |
trail_stop_pips |
追踪距离 | 10~30 |
trail_step_pips |
追踪步长 | 2~10 |
be_trigger_pips |
保本触发 | 3~10 |
be_offset_pips |
保本偏移 | 0~5 |
risk_percent |
单笔风险 % | 0.5~3 |
max_daily_loss_percent |
日亏损 % | 2~5 |
equity_trail_percent |
净值追踪 % | 5~15 |
max_trades_per_day |
日交易次数 | 5~30 |
max_spread_points |
最大点差 | 3~10 |
min_atr / max_atr |
ATR 过滤 | 视品种 |
max_hold_minutes |
最大持仓分钟 | 15~120 |
chandelier_period |
吊灯周期 | 22 |
chandelier_mult |
吊灯倍数 | 2~3 |
14. 常见陷阱与调试清单
- SL 移动方向错误:检查单向收紧规则(11.1)。
- 止损被经纪商拒绝:检查 StopLevel(11.2)与 FreezeLevel(11.3)。
- 手数计算溢出:
loss_per_lot为 0 时会导致lots = inf,必须先做边界判断。 - 精度对齐错误:所有修改前的价格必须
normalize + tick_size 对齐。 - 回测过于乐观:回测必须加 StopLevel、FreezeLevel、滑点、tick 精度。
- 移动止损被覆盖:多个移动止损同时生效会互相覆盖,需互斥或明确优先级。
- 保本后忘记原始风险:分批止盈依赖初始 R,必须开仓时存储。
- 新闻窗口恢复错误:事件结束后应显式重置
allow_trade = True。 - 会话/日切换丢失计数器:日初/会话初要主动清零计数器。
- 持仓数组索引错乱:从后往前遍历。
附:素材来源文件(知识库中)
本文件的方法总结源自以下 MQL5 知识库文件:
| 文件 | 主要贡献 |
|---|---|
Risk.mqh |
ATR 止损、风险百分比仓位、会话/点差/次数/日亏损/冷却/波动率过滤 |
TrailingMoving.mqh |
均线跟随止损(穿越 MA 平仓) |
UsingTrailing.mqh |
移动止损开关与类型枚举 |
Break_Even.mq5 |
简单保本止损 |
Trade.mqh |
通用交易与修改 API 封装 |
TradeManager.mqh |
综合管理器(移动/保本/分批组合) |
Account Protector.mqh |
账户净值追踪、日亏损百分比、按风险算手数 |
E_EntriesManagement.mqh |
一目均衡云图结构位止损、订单发送重试 |
Hedge.mqh |
网格/金字塔对冲止损 |
MQLTA MT5 ATR Trailing Stop |
ATR 移动止损、tick_size 对齐、StopLevel 检查 |
DSUPERNATURAL1 UNIVERSAL TRAILING STOP |
经典追踪(Start/Stop/Step)、魔术号解析 |
News Stopper MT5 |
新闻事件止损(三层时机窗口) |
| 综合 EA(激进模式) | 吊灯/激进追踪/分批/动量退出/时间止损的完整组合 |
文档版本:v1.0 · 2026-09-19