💡 國內提示: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 品牌風格