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

Trader analyzing stock market data on smartphone and phone

合约交易里,盈利策略和亏损策略的区别,很多时候不是信号对不对,而是风控做没做。

一个好的入场信号配上差的风控,会在一次大波动里把所有收益吐回去。这篇文章专门讲合约风控的框架:你需要在哪些层次做控制,每层具体怎么设置。

三个层次的风控

层次 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 品牌风格