第四階段:進階擴展

模組 16:會計與風控深潛理解帳戶模型、保證金計算、手續費結構 — 你的錢到底是怎麼算的

一、為什麼需要理解會計系統?

💡 會計不只是「算帳」

❌ 常見誤解:「我只要知道盈虧就好,會計是交易所的事」。

✅ 真相:如果回測中的保證金計算和真實交易所不同,你的策略可能在回測中能開 10 倍槓桿,實盤卻只能開 3 倍 — 回測結果完全不具參考價值。NautilusTrader 的 accounting/ 模組就是為了確保回測和實盤的帳戶行為一致。

二、CashAccount vs MarginAccount

特徵CashAccount 現貨帳戶MarginAccount 保證金帳戶
槓桿1x(無槓桿)可達 125x(依交易所)
下單前檢查現金餘額 ≥ 訂單成本可用保證金 ≥ 初始保證金
做空❌ 不能✅ 可以
強制平倉❌ 不會✅ 保證金不足時觸發
適用場景股票現貨、加密貨幣現貨期貨、加密貨幣合約、外匯
NautilusTrader 類CashAccountMarginAccount

帳戶餘額結構

# 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
圖 1:保證金檢查流程
# 回測中配置保證金
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"),      # 預設槓桿
)
⚠️ OMS Type 很重要

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 vs Taker 手續費

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
        # 正常交易邏輯...

七、互動練習

🧠 練習 1:帳戶類型選擇

你要交易以下品種,應該用什麼帳戶類型和 OMS?

  1. Binance BTCUSDT 現貨
  2. Binance BTCUSDT 永續合約
  3. Interactive Brokers 美股
  1. Binance BTCUSDT 現貨
    • 帳戶:CashAccount(無槓桿)
    • OMS:NETTING(加密現貨通常是淨倉)
  2. Binance BTCUSDT 永續合約
    • 帳戶:MarginAccount(有槓桿)
    • OMS:NETTING(Binance 合約是淨倉)
    • 槓桿:自行設定(1x-125x)
  3. Interactive Brokers 美股
    • 帳戶:MarginAccount(IB 提供融資)
    • OMS:NETTING(美股是淨倉)
    • 注意:IB 保證金計算複雜,需要熟悉 Reg-T 規則
🧠 練習 2:手續費計算

Maker 0.02%, Taker 0.05%。你用限價單買入 1 BTC @ $60,000,再用市價單賣出:

  1. 買入手續費是多少 USDT?
  2. 賣出手續費是多少 USDT?
  3. 如果 BTC 漲到 $60,100 時賣出,扣除手續費後實際盈虧?
  1. 買入(限價單 = Maker):
    $60,000 × 0.02% = $12 USDT
  2. 賣出(市價單 = Taker):
    $60,100 × 0.05% = $30.05 USDT
  3. 實際盈虧:
    • 毛利:$60,100 – $60,000 = $100
    • 手續費:$12 + $30.05 = $42.05
    • 淨利:$100 – $42.05 = $57.95 USDT
💡 結論

如果回測沒模擬手續費,會以為賺了 $100!
實際只賺 $57.95 — 差了 42%

🧠 練習 3:設計風控規則

你管理 $100,000 的帳戶,設計合理的風控參數(每日虧損上限、單筆最大金額、最大持倉數量、每秒最大下單數)。

保守型風控設計($100,000 帳戶):

  1. 每日虧損上限:$2,000 (2%)
    理由:超常虧損通常意味著市場異常或策略失效。設定後當日不再開新倉。
  2. 單筆最大金額:$10,000 (10%)
    理由:避免單一交易承擔過大風險。
  3. 最大持倉數量:5 個品種
    理由:分散風險,但不要太多導致管理困難。
  4. 每秒最大下單:10 單
    理由:正常策略不需要每秒下很多單。如果超過 → 可能是代碼 bug。
  5. 最大槓桿:3x
    理由:3x 已經意味著 30% 的反向波動會讓保證金大幅縮水。

附加規則:

  • 同向持倉不超過 3 個(避免風險集中)
  • 新策略上線第一週限制為一半倉位

八、本模組重點回顧

📋 關鍵點
  1. CashAccount vs MarginAccount:現貨用 Cash,合約/期貨用 Margin
  2. OMS 類型:NETTING(淨倉)和 HEDGING(對沖),選錯會導致回測不準
  3. 保證金三層:總餘額 > 初始保證金 > 維持保證金,低於維持 → 強制平倉
  4. Maker/Taker 手續費:正確模擬手續費對回測準確性至關重要
  5. 多幣種:Portfolio 原生支持多幣種餘額和盈虧計算
  6. 策略級風控:可以在 Strategy 中加入自定義風控規則作為額外保護層