模組 16:會計與風控深潛理解帳戶模型、保證金計算、手續費結構 — 你的錢到底是怎麼算的
一、為什麼需要理解會計系統?
❌ 常見誤解:「我只要知道盈虧就好,會計是交易所的事」。
✅ 真相:如果回測中的保證金計算和真實交易所不同,你的策略可能在回測中能開 10 倍槓桿,實盤卻只能開 3 倍 —
回測結果完全不具參考價值。NautilusTrader 的 accounting/ 模組就是為了確保回測和實盤的帳戶行為一致。
二、CashAccount vs MarginAccount
| 特徵 | CashAccount 現貨帳戶 | MarginAccount 保證金帳戶 |
|---|---|---|
| 槓桿 | 1x(無槓桿) | 可達 125x(依交易所) |
| 下單前檢查 | 現金餘額 ≥ 訂單成本 | 可用保證金 ≥ 初始保證金 |
| 做空 | ❌ 不能 | ✅ 可以 |
| 強制平倉 | ❌ 不會 | ✅ 保證金不足時觸發 |
| 適用場景 | 股票現貨、加密貨幣現貨 | 期貨、加密貨幣合約、外匯 |
| NautilusTrader 類 | CashAccount | MarginAccount |
帳戶餘額結構
# CashAccount 的餘額
account.balance_total(Currency.from_str("USDT")) # 總餘額
account.balance_free(Currency.from_str("USDT")) # 可用餘額
account.balance_locked(Currency.from_str("USDT")) # 凍結餘額(掛單佔用)
# MarginAccount 的額外屬性
margin_account.initial_margins() # 各品種的初始保證金
margin_account.maintenance_margins() # 各品種的維持保證金
# ❗ 重要概念
# 可用保證金 = 總餘額 - 凍結 - 初始保證金
# 如果 總餘額 < 維持保證金 → 強制平倉!三、保證金模型(MarginModel)
flowchart LR
order["📝 下單請求"]
calc["💰 計算初始保證金"]
check["✅ 保證金充足?"]
submit["➡️ 提交訂單"]
reject["❌ 拒絕訂單"]
order --> calc
calc --> check
check -->|是| submit
check -->|否| reject
style order fill:#0f1419,stroke:#4fc3f7,stroke-width:2px
style reject fill:#0f1419,stroke:#f44336,stroke-width:2px
style submit fill:#0f1419,stroke:#4caf50,stroke-width:2px
# 回測中配置保證金
from nautilus_trader.backtest.engine import BacktestEngine
from nautilus_trader.model.enums import AccountType
engine = BacktestEngine()
engine.add_venue(
venue=Venue("BINANCE"),
oms_type=OmsType.NETTING, # 淨倉模式
account_type=AccountType.MARGIN, # 保證金帳戶
starting_balances=[
Money(100_000, Currency.from_str("USDT")),
],
leverages={ # 槓桿設定
InstrumentId.from_str("BTCUSDT-PERP.BINANCE"): Decimal("10"),
InstrumentId.from_str("ETHUSDT-PERP.BINANCE"): Decimal("20"),
},
default_leverage=Decimal("1"), # 預設槓桿
)HEDGING(對沖模式):同一品種可以同時持有多空倉位(如外匯 MT4),每次開倉都是獨立持倉。
NETTING(淨倉模式):同一品種只有一個淨持倉(如 Binance 合約),買1手再賣1手 = 平倉。
選錯模式會導致回測行為和實盤不一致!
四、手續費結構(FeeModel)
from nautilus_trader.backtest.models import FeeModel, MakerTakerFeeModel
# 方法 1:使用內建的 Maker/Taker 模型
fee_model = MakerTakerFeeModel(
maker_fee=Decimal("0.0002"), # Maker 手續費 0.02%
taker_fee=Decimal("0.0005"), # Taker 手續費 0.05%
)
# 在回測配置中使用
engine.add_venue(
venue=Venue("BINANCE"),
fee_model=fee_model,
# ...
)Maker(掛單):你掛限價單等待成交,為市場提供流動性 → 手續費低甚至返佣。
Taker(吃單):你直接市價成交或「穿過」掛單吃單 → 手續費高。
❌ 常見錯誤:回測時只用 Taker 費率,但策略大量使用限價單 → 高估了交易成本 → 可能放棄了本該盈利的策略。
五、多幣種 Portfolio
# NautilusTrader 原生支持多幣種
engine.add_venue(
venue=Venue("BINANCE"),
starting_balances=[
Money(50_000, Currency.from_str("USDT")),
Money(2, Currency.from_str("BTC")),
Money(30, Currency.from_str("ETH")),
],
)
# 在策略中查詢各幣種餘額
class MyStrategy(Strategy):
def on_start(self):
account = self.portfolio.account(self.instrument_id.venue)
usdt = account.balance_total(Currency.from_str("USDT"))
btc = account.balance_total(Currency.from_str("BTC"))
eth = account.balance_total(Currency.from_str("ETH"))
self.log.info(f"USDT: {usdt}, BTC: {btc}, ETH: {eth}")
# 未實現盈虧(按基礎貨幣計算)
unrealized = self.portfolio.unrealized_pnl(self.instrument_id)
self.log.info(f"未實現 PnL: {unrealized}")
六、風控引擎進階
模組 09 介紹了風控的基礎。這裡深入進階配置:
6.1 組件級風控規則
from nautilus_trader.risk.engine import RiskEngine
# 風控規則示例
risk_config = LiveRiskEngineConfig(
bypass=False,
# 訂單頻率限制
max_order_submit_rate="100/00:00:01", # 每秒最多 100 單
max_order_modify_rate="100/00:00:01", # 每秒最多修改 100 次
# 淨倉位上限(每個品種)
max_notional_per_order={
"BTCUSDT-PERP.BINANCE": 100_000, # 單筆最多 10 萬 USDT
},
)6.2 自定義風控規則
from nautilus_trader.trading.strategy import Strategy
class RiskManagedStrategy(Strategy):
"""在策略層面加入額外風控"""
def _check_risk_limits(self) -> bool:
"""檢查是否允許繼續交易"""
# 1. 當日虧損上限
account = self.portfolio.account(self.instrument_id.venue)
if self._daily_pnl < Money(-5000, USD):
self.log.warning("當日虧損超過 $5000,停止交易")
return False
# 2. 最大持倉數量
positions = self.cache.positions(venue=self.instrument_id.venue)
if len(positions) >= 5:
self.log.warning("已達最大持倉數量 5")
return False
# 3. 最大相關性(同方向持倉)
long_count = sum(1 for p in positions if p.is_long)
if long_count >= 3:
self.log.warning("太多同向持倉,風險集中")
return False
return True
def on_bar(self, bar):
if not self._check_risk_limits():
return
# 正常交易邏輯...
七、互動練習
你要交易以下品種,應該用什麼帳戶類型和 OMS?
- Binance BTCUSDT 現貨
- Binance BTCUSDT 永續合約
- Interactive Brokers 美股
- Binance BTCUSDT 現貨
- 帳戶:
CashAccount(無槓桿) - OMS:
NETTING(加密現貨通常是淨倉)
- 帳戶:
- Binance BTCUSDT 永續合約
- 帳戶:
MarginAccount(有槓桿) - OMS:
NETTING(Binance 合約是淨倉) - 槓桿:自行設定(1x-125x)
- 帳戶:
- Interactive Brokers 美股
- 帳戶:
MarginAccount(IB 提供融資) - OMS:
NETTING(美股是淨倉) - 注意:IB 保證金計算複雜,需要熟悉 Reg-T 規則
- 帳戶:
Maker 0.02%, Taker 0.05%。你用限價單買入 1 BTC @ $60,000,再用市價單賣出:
- 買入手續費是多少 USDT?
- 賣出手續費是多少 USDT?
- 如果 BTC 漲到 $60,100 時賣出,扣除手續費後實際盈虧?
- 買入(限價單 = Maker):
$60,000 × 0.02% = $12 USDT - 賣出(市價單 = Taker):
$60,100 × 0.05% = $30.05 USDT - 實際盈虧:
- 毛利:$60,100 – $60,000 = $100
- 手續費:$12 + $30.05 = $42.05
- 淨利:$100 – $42.05 = $57.95 USDT
如果回測沒模擬手續費,會以為賺了 $100!
實際只賺 $57.95 — 差了 42%
你管理 $100,000 的帳戶,設計合理的風控參數(每日虧損上限、單筆最大金額、最大持倉數量、每秒最大下單數)。
保守型風控設計($100,000 帳戶):
- 每日虧損上限:$2,000 (2%)
理由:超常虧損通常意味著市場異常或策略失效。設定後當日不再開新倉。 - 單筆最大金額:$10,000 (10%)
理由:避免單一交易承擔過大風險。 - 最大持倉數量:5 個品種
理由:分散風險,但不要太多導致管理困難。 - 每秒最大下單:10 單
理由:正常策略不需要每秒下很多單。如果超過 → 可能是代碼 bug。 - 最大槓桿:3x
理由:3x 已經意味著 30% 的反向波動會讓保證金大幅縮水。
附加規則:
- 同向持倉不超過 3 個(避免風險集中)
- 新策略上線第一週限制為一半倉位
八、本模組重點回顧
- CashAccount vs MarginAccount:現貨用 Cash,合約/期貨用 Margin
- OMS 類型:NETTING(淨倉)和 HEDGING(對沖),選錯會導致回測不準
- 保證金三層:總餘額 > 初始保證金 > 維持保證金,低於維持 → 強制平倉
- Maker/Taker 手續費:正確模擬手續費對回測準確性至關重要
- 多幣種:Portfolio 原生支持多幣種餘額和盈虧計算
- 策略級風控:可以在 Strategy 中加入自定義風控規則作為額外保護層