> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sory.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Fees

> Your negotiated rates, from a file you control.

**Fees come from a config file. Never from the venue.**

A venue's published schedule is its *public retail* tier, routinely an order of magnitude away from a negotiated rate — 40/60 bps advertised against 0/4 bps actually paid. Since routing picks venues on all-in price, published fees make it route wrong on **every** order.

```toml fees.toml theme={"dark"}
[binance]                 # per-venue default
maker_bps = 1.0
taker_bps = 4.0

[binance."BTC/USDT"]      # per-symbol override
maker_bps = -1.0          # a rebate is a negative fee
taker_bps = 3.5
```

```python theme={"dark"}
config = {"market_data": {...}, "fees_bps": "fees.toml"}
```

## Rules

<Columns cols={3}>
  <Card title="Negative is first-class" icon="minus">
    A maker rebate is a negative fee. The arithmetic handles the sign with no special case.
  </Card>

  <Card title="Validated at startup" icon="circle-check">
    Every configured venue and symbol must have an entry.
  </Card>

  <Card title="Missing is fatal" icon="triangle-alert">
    A missing entry raises. It is never a silent zero.
  </Card>
</Columns>

```text theme={"dark"}
FeeError: Fee schedule is incomplete, missing: okx ETH/USDT
```

## How they apply

```text theme={"dark"}
bid_all_in = bid × (1 − fee)
ask_all_in = ask × (1 + fee)
```

The consolidated book is **taker**-adjusted, because taker is what you pay to cross it. Maker rates are there for your own quote pricing.

Worked against a raw price of 100:

|     | Fee         | All-in |                     |
| --- | ----------- | ------ | ------------------- |
| Bid | taker 5 bps | 99.95  | you receive less    |
| Ask | taker 5 bps | 100.05 | you pay more        |
| Bid | maker −1 bp | 100.01 | the rebate pays you |
| Ask | maker −1 bp | 99.99  |                     |

<Note>
  A sign error on a rebate is a silent, permanent routing bug: nothing crashes, nothing looks wrong, and every decision is subtly backwards. There is a dedicated test pinning these exact numbers.
</Note>
