prediction-fees
Exact trading fees for Kalshi and Polymarket, from a dated schedule. No dependencies, MIT.
pip install prediction-fees
from prediction_fees import kalshi_fee, kalshi_fee_levels, polymarket_fee, polymarket_rebate
kalshi_fee(0.50, 100) # Decimal('1.75') taker
kalshi_fee(0.50, 1) # Decimal('0.02') 0.0175 rounds up to the cent
kalshi_fee(0.50, 100, maker=True) # Decimal('0.44')
kalshi_fee(0.50, 100, as_of="2026-11-03")
# one order that walked three levels: summed first, rounded once
kalshi_fee_levels([(0.45, 10), (0.46, 20), (0.48, 5)]) # Decimal('0.61')
# a series without maker fees (Kalshi GET /series/{ticker} fee_type "quadratic")
kalshi_fee(0.50, 100, maker=True, fee_type="quadratic") # Decimal('0.00')
polymarket_fee(0.50, 100, category="crypto") # Decimal('1.75000') USDC
polymarket_fee(0.50, 100, rate=0.03) # Decimal('0.75000') the market's own feeSchedule.rate
polymarket_fee(0.50, 100, maker=True) # Decimal('0.00000')
polymarket_rebate(0.60, 100, category="politics") # Decimal('0.240000') maker rebate
Every function returns a Decimal. Prices are in dollars (0 to 1). Inputs can be int,
float, str or Decimal; floats are read through their shortest repr, so 0.07 is exactly
0.07 and there is no float error in the round-up (a naive math.ceil charges a cent too many
on, for example, 100 contracts at 0.10).
The rules
Kalshi. Per order execution (one order matched at one time, across however many price levels it took):
fee = round_up_to_cent( rate × multiplier × Σ C × P × (1 − P) )
rate is 0.07 for takers and 0.0175 for makers. multiplier is the series'
fee_multiplier and applies to takers and makers (1 for most series; some 0.5, a few 0).
Makers pay only on series whose fee_type charges makers (quadratic_with_maker_fees,
quadratic_with_combo_maker_fees); a quadratic series charges makers 0. On 2 Nov 2026 that
was 163 of Kalshi's 15,600 series. Read both from Kalshi's public
GET /trade-api/v2/series/{series_ticker} (the series is the market ticker up to the first
-) and pass them: fee_type="quadratic" makes a maker fill cost 0, and
kalshi_multipliers(fee_type, fee_multiplier) gives the (taker, maker) multipliers. Without fee_type makers are charged (the
conservative side).
Polymarket. Takers, per execution:
fee = round_down_to_0.00001( rate × Σ C × P × (1 − P) )
rate is the market's own coefficient: Gamma GET /markets?id= returns it as
feeSchedule.rate (0 when feesEnabled is false), and some older sports markets still carry
0.03. Without it, the category table:
| category | taker coefficient | maker rebate share |
|---|---|---|
| crypto | 0.07 | 0.20 |
| sports | 0.05 | 0.15 |
| economics, culture, weather, other | 0.05 | 0.25 |
| combos | 0.05 | 0 |
| finance, politics, mentions, tech | 0.04 | 0.25 |
| geopolitics | 0 | 0 |
Pass the market's own coefficient as rate or category (case-insensitive);
polymarket_market_terms(market) reads a Gamma row (its feeSchedule, else the category its feeType names,
e.g. politics_fees). Fees are rounded to 5 decimals, down: Polymarket's docs say anything
below 0.00001 USDC rounds to zero.
Makers pay 0 and earn a rebate, polymarket_rebate:
rebate = rebate_share × rate × Σ C × P × (1 − P)
Each market's daily rebate pool is its rebate share of the taker fees paid there, split pro rata
by each maker's fee-equivalent, so a maker's rebate is exactly the share of its own
fee-equivalent. Pass the market's feeSchedule.rebateRate as rebate_share (or a category).
The rebate is not rounded (it is paid daily in aggregate) and the $1 minimum payout is not
modelled.
Edge cases. A price of exactly 0 or 1 costs nothing (P × (1 − P) is 0). A price outside
[0, 1], a negative size or rate, NaN or infinity raises FeeError (a ValueError). Zero
contracts cost nothing.
Dates
The table (fees.json, shipped inside the package) lists each venue's rates with the date they
took effect. as_of= takes a date, a datetime (read in UTC) or an ISO string and picks the
entry in force that day; without it you get the latest entry. A date before the first entry
raises FeeError rather than guessing; pass rate= to price an older trade.
| venue | effective | rates |
|---|---|---|
| Kalshi | 2026-07-07 | taker 0.07, maker 0.0175 |
| Polymarket | 2026-07-10 | the category table above, makers 0 plus the rebate share |
prediction_fees.table() returns the whole table, sources and notes included.
What is not certain
Checked on 2026-11-01 (Polymarket and the Kalshi series rule on 2026-11-02):
- Kalshi's taker formula and 0.07 are well established. The maker coefficient 0.0175 and the 2026-07-07 effective date come from secondary sources quoting Kalshi's fee schedule PDF (kalshi.com/docs/kalshi-fee-schedule.pdf), which could not be fetched to confirm.
- Kalshi's API docs describe fees accrued to $0.000001 with a per-order rounding accumulator that refunds over-rounding. This library follows the published schedule (round up to the cent per execution), so a fill split across several executions may show a cent or two more than Kalshi's final charge.
- Polymarket's coefficients and rebate shares are as read from docs.polymarket.com on
2026-11-02. 2026-07-10 is the date of the last change in the published timeline (sports 0.03
to 0.05); earlier periods are not tabulated, and a market's own
feeSchedulecan still differ from the table (0.03 on some older sports markets), so prefer it. The docs say fees are rounded to 5 decimals and that anything below 0.00001 USDC rounds to zero; this library reads that as rounding down, which the docs do not state in so many words. - Not covered: the $1 minimum rebate payout, taker volume rebates, Polymarket US (a separate exchange with its own schedule), Kalshi incentive programs and perpetuals.
Corrections with a source are welcome: hello@langbot.ai.
The same table and functions ship for JavaScript/TypeScript as
prediction-fees on npm.
License
MIT. Maintained by Langbot.
Metadata
Release files for prediction-fees 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| prediction_fees-0.2.0.tar.gz | 14.5 kB | Without provenance | Details for prediction_fees-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| prediction_fees-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for prediction_fees-0.2.0-py3-none-any.whl |
Total release size: 25.5 kB
Release files / prediction_fees-0.2.0.tar.gz
| Download URL | prediction_fees-0.2.0.tar.gz |
|---|---|
| Size | 14.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d2263a2bda8febfb994dd9ead39cbf0a8bd3db825fa823dd966e35554dec7e96
|
|
BLAKE2b-256 checksum How to use checksums |
1378169fd63fc5ae080aaa18a7c191799e9ba062f38c5ab1f80b6398818e3257
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / prediction_fees-0.2.0-py3-none-any.whl
| Download URL | prediction_fees-0.2.0-py3-none-any.whl |
|---|---|
| Size | 11.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
08d8aea066fb7553d1002f188fceb4a5ba48965c5a96084e935b526dd29f8ba4
|
|
BLAKE2b-256 checksum How to use checksums |
a21ef9b69a44c9c27c356f663fa7b1eaad5289a1b13ecf497d3cfa0a32179a9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for prediction-fees 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.