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