Quant Python: Architecting Autonomous Trading Systems

Quant Python: Architecting Autonomous Trading Systems

Day 57: Market Friction Modeling: Fixed Commissions

Python Quant's avatar
Python Quant
May 29, 2026
∙ Paid

Before you read further, be honest with yourself: every backtest you have written until now is probably lying to you. Not because the math is wrong — because you have been treating commission as an afterthought. By the end of today, that changes permanently.


What This Lesson Covers

By the end of Day 57 you will have:

  • A working mental model of why commission must live before the trade decision, not after it

  • Three working Python modules — CommissionModel, ExecutionRecord, and CommissionAwareOrderRouter — that form the cost accounting spine of every strategy you build from here on

  • A CLI dashboard that lets you watch the gate accept and reject trades in real time

  • 22 passing unit tests that prove your numbers are right


The “Subtract At The End” Trap

Every junior quant makes the same mistake. They build a backtest, nail the signal logic, produce a beautiful equity curve, and then — at the very end of the loop — do this:

# The naive approach (DO NOT DO THIS)
total_pnl = sum(trade_returns)
total_commission = num_trades * 0.005 * avg_shares  # flat estimate
net_pnl = total_pnl - total_commission
print(f"Net P&L: ${net_pnl:.2f}")

This will get you fired. Here is why.

That single line treats commission as an accounting footnote — something you reconcile after the strategy has already decided to trade. In production, commission is a gate condition, not a line item. The moment you decouple cost from decision, you have built a strategy that will routinely execute trades with negative expected value. At scale, this is not a rounding error — it is systematic alpha destruction.

Funds blow through six-figure paper profits because their backtest used a 0.1% flat commission estimate while their broker charged $0.005/share with a $1.00 minimum. On a 50-share trade at $12/share ($600 notional), that is $1.00 / $600 = 16.7 basis points in commission alone. If your signal’s average edge is 15 bps, every single trade loses money by design.


The Failure Mode: Three Technical Crashes

Understanding how this breaks is as important as knowing that it breaks. There are three distinct failure modes, and you are probably exposed to all three right now.

Crash 1 — The Wrong Commission Model

Brokers do not all charge the same way. Alpaca charges $0.00/trade for equities but may charge on options. Interactive Brokers uses a tiered per-share model with minimums. Your generic commission_rate = 0.001 assumption is a fiction that compounds across thousands of trades.

Crash 2 — Float Accumulation Drift

pnl = 0.0
for trade in trades:
    pnl += trade.return_usd - (trade.shares * 0.005)  # float arithmetic
# After 10,000 trades: pnl has drifted by $0.02–$0.15 in float errors

In a strategy with tight expected returns, this drift contaminates your Sharpe calculation. Use decimal.Decimal for all monetary values in production execution logs — IEEE 754 floating-point is not an accounting standard.

Crash 3 — No Minimum Viable Edge (MVE) Gate

Without a pre-execution viability check, your order router submits trades where:

expected_return_usd < commission_cost_usd

This is the mathematical definition of negative expectancy. Every such trade is a scheduled loss.


The AutoQuant-Alpha Architecture

We implement a three-layer commission system. Each layer has exactly one responsibility, and they only communicate downward.

┌─────────────────────────────────────────────────────┐
│  Layer 1: CommissionModel                           │
│  Supports: FLAT | PER_SHARE | PERCENTAGE            │
│  Output: cost_usd (Decimal), viable (bool)          │
├─────────────────────────────────────────────────────┤
│  Layer 2: ExecutionRecord                           │
│  Atomic trade log with Decimal P&L accounting       │
│  Immutable dataclass — write-once, append-only      │
├─────────────────────────────────────────────────────┤
│  Layer 3: CommissionAwareOrderRouter                │
│  Pre-flight cost gate before Alpaca API call        │
│  Position sizing adjusted to maintain MVE threshold │
└─────────────────────────────────────────────────────┘

The key design principle: commission is computed before any order is constructed. The order router never touches the Alpaca API unless the viability gate passes.


User's avatar

Continue reading this post for free, courtesy of Python Quant.

Or purchase a paid subscription.
© 2026 Python Quant · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture