佣金与滑点

QTrade 内置四种 Commission 实现,覆盖大多数策略需要的模式。全部位于 qtrade.core.commission,共享抽象基类 Commission

from qtrade.core import (
    NoCommission,            # default: 0
    PercentageCommission,    # X% of order value
    FixedCommission,         # flat fee per order
    SlippageCommission,      # X% slippage on order value
)

把实例传给 Backtest(..., commission=...)TradingEnv(..., commission=...)commission=None 等价于 NoCommission()

接口

Commission.calculate_commission(order_size: int, fill_price: float) -> float

返回一笔成交的佣金(账户币种)。Broker 在成交时从 cash 扣除。order_size 的符号保留 —— 如果想买卖对称收费,在内部用 abs(order_size)

自定义实现:

from qtrade.core.commission import Commission

class TieredCommission(Commission):
    """0.1% under $10k, 0.05% above (per fill)."""

    def calculate_commission(self, order_size, fill_price):
        notional = abs(order_size) * fill_price
        rate = 0.001 if notional < 10_000 else 0.0005
        return notional * rate

内置实现

NoCommission

NoCommission()

始终返回 0.0。不传任何参数时的默认值。用于和 Buy & Hold 做干净对比,或者建模零佣金券商。

PercentageCommission

PercentageCommission(percentage=0.001)   # 0.1%

abs(order_size) * fill_price * percentage 收费。

股票(佣金按名义本金的 bps 报价)和加密现货(taker 费率通常 0.05–0.1%)的标准模型。

FixedCommission

FixedCommission(fixed_fee=1.0)   # $1 per fill

无论 size 和价格如何,返回固定费用。适合 期货(交易所按合约计费)和按笔收单一费用的折扣券商

对于含多个佣金组件(交易所 + 清算 + 券商)的期货,加总后传入:FixedCommission(fixed_fee=2.50)

SlippageCommission

SlippageCommission(slippage_percentage=0.0005)   # 5 bps

数学上与 PercentageCommission 相同,但意图不同 —— 这个建模的是穿越买卖价差的价格冲击,不是交易所费用。适用场景:

  • 想在显式佣金之上额外加上滑点。

  • 想让成本按名义本金缩放,但在报表中和「佣金」分开统计。

# Crypto spot: 0.1% taker fee + 0.05% slippage
class CryptoCost(Commission):
    def __init__(self):
        self.fee = PercentageCommission(0.001)
        self.slip = SlippageCommission(0.0005)
    def calculate_commission(self, order_size, fill_price):
        return self.fee.calculate_commission(order_size, fill_price) \
             + self.slip.calculate_commission(order_size, fill_price)

如何选择合适的模型

资产类别

典型设置

美股(零售)

NoCommission()(大多数券商已零佣)+ 小额 SlippageCommission

美股(机构)

PercentageCommission(0.0005)(综合约 5 bps)

期货

FixedCommission(2.5) 每合约 + 滑点

外汇

PercentageCommission(0.0001)(主要货币对约 1 个点)

加密现货

PercentageCommission(0.001)(taker)或 (0.0005)(maker)

加密永续合约

PercentageCommission(0.0005) taker + 资金费率(单独建模)

不确定的话,回测时分别带和不带佣金跑一遍。差距告诉你策略的成本敏感度 —— 高换手率策略经常成本前看起来很美,扣掉成本就亏钱。

A note on the built-in Contract specs

The qtrade.contracts module ships specs for common futures (GC_COMEX, ES_CME, CL_NYMEX, etc.) that bundle a multiplier and a default margin_ratio. The multiplier values are part of the contract design and rarely change. The margin_ratio values are conventional starting points only — actual margin is set by the exchange (SPAN) and your broker, and floats over time. Verify against your account before trusting backtest leverage numbers.

To override, either tweak with dataclasses.replace:

from dataclasses import replace
from qtrade.contracts import GC_COMEX
MY_GC = replace(GC_COMEX, margin_ratio=0.07)

…or define your own:

from qtrade.contracts import Contract
SHFE_AU = Contract(multiplier=1000, margin_ratio=0.08, name="SHFE Gold")

未建模的部分

  • Maker / taker 不对称。所有成交按单一费率收费。如需对限价单按 maker 费率收费,写一个自定义 Commission 并根据订单是否有 limit 价格分支。

  • 买卖价差。Broker 用 Close(或下一根 Open)成交市价单。买卖价差未建模 —— SlippageCommission 是最接近的近似。

  • 资金费率 / 借券成本。未建模。对于长期空仓或永续合约资金费率,需要在策略的 on_bar_close 里手动扣 cash

  • 按资产收费。多资产回测中单个 Commission 实例应用到所有资产。如需按资产差异化费率,写一个根据订单 _fill_price 分支的自定义 Commission,或在策略逻辑里包装。