💡 国内提示:Binance 官网在中国大陆无法直连,访问需自备网络工具;法币入金不支持银行卡,主要走 C2C(USDT↔CNY)通道完成。

合约交易里,盈利策略和亏损策略的区别,很多时候不是信号对不对,而是风控做没做。
一个好的入场信号配上差的风控,会在一次大波动里把所有收益吐回去。这篇文章专门讲合约风控的框架:你需要在哪些层次做控制,每层具体怎么设置。
三个层次的风控
层次 1:仓位管理 — 每次开多大的仓
层次 2:止损设置 — 单笔交易最多亏多少
层次 3:熔断机制 — 连续亏损后强制暂停
这三层缺一不可。仓位管理控制单次风险暴露,止损控制单笔最大损失,熔断防止在策略失效时持续亏损。
层次 1:仓位管理
固定比例法(推荐)
每次开仓金额 = 账户总权益 × 固定比例
def calc_position_size(equity: float, risk_pct: float, leverage: int,
entry_price: float) -> float:
"""
equity: 账户总权益(USDT)
risk_pct: 单次风险比例,如 0.02 = 2%
leverage: 杠杆倍数
entry_price: 开仓价格
返回: 合约张数(BTCUSDT 每张 = 0.001 BTC)
"""
risk_amount = equity * risk_pct # 实际愿意亏的金额
notional = risk_amount * leverage # 对应名义价值
qty = notional / entry_price
return qty
为什么用固定比例而不是固定金额?
固定金额(每次开 1000U)在账户增长后风险比例越来越小,在账户缩水后风险比例越来越大(正好反过来了)。固定比例则随账户规模自动调整。
合理的风险比例:
| 策略阶段 | 建议比例 |
|---|---|
| 测试期(验证策略) | 0.5% - 1% |
| 稳定运行期 | 1% - 2% |
| 高置信度策略 | 2% - 3% |
| 不建议超过 | 5% |
单次 5% 以上的风险比例,5 次连续亏损就是 25%+ 的回撤,很难心理承受也很难策略恢复。
Kelly 公式(进阶)
如果你有足够的历史数据,可以用 Kelly 公式计算理论最优仓位:
def kelly_fraction(win_rate: float, avg_win: float, avg_loss: float) -> float:
"""
win_rate: 历史胜率,如 0.55
avg_win: 平均盈利(比例),如 0.015 = 1.5%
avg_loss: 平均亏损(比例,正数),如 0.01 = 1%
"""
b = avg_win / avg_loss # 盈亏比
p = win_rate
q = 1 - p
kelly = (b * p - q) / b
# 实际使用半 Kelly,降低波动
return max(0, kelly * 0.5)
Kelly 公式给出的是理论最大化复利增长的仓位比例。实际使用时取"半 Kelly",在控制回撤的同时保持较好的增长。
层次 2:止损设置
止损有两种主要方式:
价格止损
在开仓时就确定止损价格,价格触及后平仓。
def set_stop_loss(symbol: str, side: str, entry_price: float,
stop_pct: float, client) -> dict:
"""
stop_pct: 止损距离,如 0.02 = 入场价的 2%
"""
if side == "BUY":
stop_price = entry_price * (1 - stop_pct)
sl_side = "SELL"
else:
stop_price = entry_price * (1 + stop_pct)
sl_side = "BUY"
# 下 STOP_MARKET 单(触发价达到后市价平仓)
order = client.futures_create_order(
symbol=symbol,
side=sl_side,
type="STOP_MARKET",
stopPrice=round(stop_price, 2),
closePosition=True, # 全部平仓
timeInForce="GTE_GTC"
)
return order
止损距离怎么设?
常见思路:
- 基于 ATR(Average True Range):止损 = 1-2 倍 ATR,适应当前波动率
- 基于支撑阻力位:设在技术上有意义的位置
- 固定比例:简单直接,易于风控计算
推荐用 ATR 方式,因为不同市场环境下波动率差异很大,固定比例在低波动期过松、高波动期过紧。
def calc_atr(highs, lows, closes, period=14):
"""计算 ATR"""
true_ranges = []
for i in range(1, len(closes)):
tr = max(
highs[i] - lows[i],
abs(highs[i] - closes[i-1]),
abs(lows[i] - closes[i-1])
)
true_ranges.append(tr)
return sum(true_ranges[-period:]) / period
追踪止损
随价格运动调整止损位,锁住浮盈:
def set_trailing_stop(symbol: str, callback_rate: float, client) -> dict:
"""
callback_rate: 回调比例(百分比),如 1.5 = 1.5%
价格从最高点回落 1.5% 时触发止损
"""
order = client.futures_create_order(
symbol=symbol,
side="SELL",
type="TRAILING_STOP_MARKET",
callbackRate=callback_rate,
quantity=你的持仓量,
reduceOnly=True
)
return order
追踪止损适合趋势行情,普通止损适合震荡行情。
层次 3:熔断机制
熔断机制在策略出现连续亏损时强制暂停,防止策略失效时持续消耗账户。
class CircuitBreaker:
def __init__(self,
max_daily_loss_pct: float = 0.05, # 单日最大亏损 5%
max_drawdown_pct: float = 0.15, # 最大回撤 15%
max_consecutive_losses: int = 5): # 连亏次数上限
self.max_daily_loss_pct = max_daily_loss_pct
self.max_drawdown_pct = max_drawdown_pct
self.max_consecutive_losses = max_consecutive_losses
self.consecutive_losses = 0
self.peak_equity = None
self.day_start_equity = None
def update(self, current_equity: float) -> bool:
"""
更新状态,返回 True 表示正常,False 表示触发熔断
"""
if self.peak_equity is None:
self.peak_equity = current_equity
if self.day_start_equity is None:
self.day_start_equity = current_equity
# 更新峰值
if current_equity > self.peak_equity:
self.peak_equity = current_equity
# 检查最大回撤
drawdown = (self.peak_equity - current_equity) / self.peak_equity
if drawdown >= self.max_drawdown_pct:
self._trigger("最大回撤触发", drawdown)
return False
# 检查单日亏损
daily_loss = (self.day_start_equity - current_equity) / self.day_start_equity
if daily_loss >= self.max_daily_loss_pct:
self._trigger("单日亏损触发", daily_loss)
return False
# 检查连亏次数
if self.consecutive_losses >= self.max_consecutive_losses:
self._trigger(f"连续亏损 {self.consecutive_losses} 次")
return False
return True
def record_trade(self, pnl: float):
"""记录一笔交易结果"""
if pnl < 0:
self.consecutive_losses += 1
else:
self.consecutive_losses = 0 # 盈利则重置连亏计数
def _trigger(self, reason: str, value: float = 0):
print(f"[熔断] {reason}: {value:.2%}")
# 在这里加 Telegram 告警
使用方式:
cb = CircuitBreaker(
max_daily_loss_pct=0.05,
max_drawdown_pct=0.15,
max_consecutive_losses=5
)
# 每次策略执行前检查
while True:
equity = get_account_equity()
if not cb.update(equity):
send_telegram("策略熔断,暂停交易")
break
# 执行策略逻辑
signal = strategy.check_signal()
if signal:
pnl = execute_trade(signal)
cb.record_trade(pnl)
完整风控集成示例
class RiskManager:
def __init__(self, client, equity: float):
self.client = client
self.equity = equity
self.circuit_breaker = CircuitBreaker()
def open_position(self, symbol: str, side: str, entry_price: float,
risk_pct: float = 0.01, leverage: int = 5):
"""带风控的开仓"""
# 1. 检查熔断
if not self.circuit_breaker.update(self.equity):
print("熔断状态,拒绝开仓")
return None
# 2. 计算仓位
qty = calc_position_size(self.equity, risk_pct, leverage, entry_price)
# 3. 开仓
order = self.client.futures_create_order(
symbol=symbol,
side=side,
type="MARKET",
quantity=qty
)
# 4. 同步设置止损(基于 ATR)
atr = self.get_atr(symbol)
stop_dist_pct = (atr * 1.5) / entry_price
set_stop_loss(symbol, side, entry_price, stop_dist_pct, self.client)
return order
常见风控错误
不设止损:最致命,没有讨论空间。
止损太紧:ATR 的 0.3 倍,频繁触发,胜率虚低。
止损太松:ATR 的 5 倍,单次亏损超出预期,破坏风险比例计算。
仓位固定不变:账户亏损后没有降低仓位,越亏越大。
熔断后手动覆盖:“就这一次”——每次都这么想的。熔断设了但自己手动关掉等于没设。
风控不是限制收益的枷锁,是保证策略能够长期持续运行的基础设施。设计好风控,才能在市场里活得足够久,让边际有优势的策略把期望收益跑出来。
→ 查看 Binance API 从申请到第一笔下单 → 查看 量化工具栈:Binance API + Grafana + 自动化告警 → 查看 北极星策略介绍
📷 封面图 · Flux Schnell AI 生成 · panshi.io 品牌风格