Skip to main content

pmfees

Exact trading fees for the prediction market platforms Kalshi, Polymarket US and polymarket.com (international), as a small Python library and a command line tool.

  • The platforms' own formulas and rounding rules: Kalshi rounds up so that fee + position cost is a whole centicent ($0.0001), Polymarket US rounds to the cent with banker's rounding, polymarket.com rounds to 5 decimals.
  • Exact decimal arithmetic (decimal.Decimal), so $1.75 is $1.75 and not $1.7500000000000002.
  • A break-even helper: how far the price has to move before a round trip is in profit after the fee on both orders.
  • No dependencies outside the Python standard library. Typed (py.typed).

Rates current as of: Kalshi 2026-11-10 (fee schedule 7.7.26), Polymarket US 2026-11-09, polymarket.com 2026-11-08. Each platform's date and source are in the rates file and in every result.

Other ways to get the same numbers, from the same rates file:

Install

pip install pmfees

Python 3.10 or newer.

Command line

pmfees kalshi --price 0.50 --contracts 100
Kalshi taker fee: $1.75 (3.50% of trade value at 50¢)
  buy 100 contracts at $0.50 = $50.00 trade value
  base rate: 0.07
  multiplier: 1
  fee schedule version: 7.7.26
  0.07 × 100 × 0.5 × (1 − 0.5) = 1.75, rounded up so that fee + position cost is a whole centicent ($0.0001): $1.75
  rates as of 2026-11-10 · source: https://kalshi.com/docs/kalshi-fee-schedule.pdf

More examples:

# Polymarket US, Tier 1 (under $10,000 of 30-day taker volume, the default)
pmfees polymarket-us --price 0.50 --contracts 100
# -> Polymarket US taker fee: $2.38 (4.76% of trade value at 50¢)   [0.095 × 100 × 0.5 × 0.5 = 2.375]

# polymarket.com, Crypto category
pmfees polymarket --price 0.25 --contracts 100 --category Crypto
# -> polymarket.com taker fee: $1.3125 (5.25% of trade value at 25¢)

# Break-even: buy 100 on Kalshi at 50¢, when is selling in profit?
pmfees kalshi --price 0.50 --contracts 100 --break-even
# -> Break-even: the price must rise 4¢ to 54¢ (tick 1¢); entry fee $1.75 + exit fee $1.7388, profit at that price $0.5112

Options:

Option Platforms Meaning
--price all Price of the contract you trade, in dollars (0 < price < 1)
--contracts all Number of contracts (shares on polymarket.com)
--side buy|sell all Changes the cash flow only; the fee formulas are symmetric
--maker all Maker order. Kalshi: maker rate 0.0175 with M default 0, so pass --multiplier 1 on markets with maker fees. Polymarket US and polymarket.com: makers pay no fee
--multiplier kalshi Fee multiplier M (default 1 for takers, 0 for makers)
--tier 1-4|new polymarket-us Taker tier, or new for the first 7 days of a new account (default 1)
--volume polymarket-us Trailing 30-day taker volume in USD; picks the tier for you
--category polymarket Market category, e.g. Crypto, Sports, Politics (required)
--break-even, --tick all Also print the break-even move (price step, default 0.01)
--json all Machine-readable output
--rates PATH all Use an updated rates file

pmfees rates prints the loaded rates and their date.

Library

from pmfees import fee, break_even

r = fee("kalshi", 0.50, 100)
r.fee  # Decimal('1.7500')  what you pay, in USD
r.raw_fee  # Decimal('1.7500') before rounding
r.fee_pct_of_trade_value  # Decimal('3.500')
r.breakdown()  # dict of strings: coefficient, rounding, formula, source_url, rates_as_of, ...

fee("polymarket-us", 0.10, 1000, "buy", tier=4).fee  # Decimal('6.26')
fee("polymarket-us", 0.10, 1000, volume_30d=12_500).fee  # Tier 2
fee("polymarket", 0.25, 100, category="Crypto").fee  # Decimal('1.31250')
fee("kalshi", 0.50, 1).fee  # Decimal('0.0175')  centicent rounding, not $0.02
fee("kalshi", 0.50, 100, maker=True).fee  # Decimal('0.0000')  maker M defaults to 0
fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee  # Decimal('0.4375')
fee("kalshi", 0.50, 100, multiplier=0.5).fee  # Decimal('0.8750')

b = break_even("polymarket-us", 0.40, 500, tier=2)
b.exit_price, b.move_cents  # (Decimal('0.45'), Decimal('5.00'))

Signature: fee(platform, price, contracts, side="buy", tier=None, maker=False, *, category=None, multiplier=None, volume_30d=None, rates=None) -> FeeResult. Platform names: kalshi, polymarket-us, polymarket (also polymarket.com). Prices and counts can be str, int, float or Decimal; floats are converted through str, so 0.1 means exactly 0.1.

break_even(...) takes the same arguments plus tick. It opens the position at price, then walks the price in tick steps (up for a buy, down for a sell) and returns the first exit price where proceeds − cost − entry fee − exit fee > 0, or exit_price=None if no price before $1 (or $0) works.

Kalshi: centicent rounding and the multiplier

Kalshi does not round the fee on its own. It rounds fee + position cost (contracts × price) up to a whole centicent ($0.0001), per the fee schedule (version 7.7.26, page 2). Most of the time that looks like rounding the fee up to four decimals, but the fee alone is what you see change:

from pmfees import fee

fee("kalshi", 0.50, 1).fee  # Decimal('0.0175')  0.07 × 1 × 0.5 × 0.5 = 0.0175 exactly; not $0.02
fee("kalshi", 0.33, 7).fee  # Decimal('0.1084')  raw 0.108339; 2.31 + 0.108339 = 2.418339 -> 2.4184

Accounts cleared through a broker (FCM) keep balances in whole cents, so there the fee rounds to the cent (Kalshi docs). pmfees models kalshi.com accounts (direct members).

Each Kalshi series has a fee multiplier M: 1 (standard), 0.5 or 0. Takers default to M = 1, makers to M = 0, because Kalshi charges makers only on series listed with maker fees:

fee("kalshi", 0.25, 100).fee  # Decimal('1.3125')  M = 1
fee("kalshi", 0.25, 100, multiplier=0.5).fee  # Decimal('0.6563')  raw 0.65625, rounded up
fee("kalshi", 0.50, 100, maker=True).fee  # Decimal('0.0000')  maker, M defaults to 0
fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee  # Decimal('0.4375')  0.0175 × 100 × 0.25
pmfees kalshi --price 0.25 --contracts 100 --multiplier 0.5
# -> Kalshi taker fee: $0.6563 (2.63% of trade value at 25¢)

The formulas

Platform Taker fee Rounding
Kalshi M × 0.07 × C × P × (1 − P), M default 1; maker M × 0.0175 × C × P × (1 − P), M default 0 Up, so that fee + position cost is a whole centicent ($0.0001)
Polymarket US Θ × C × p × (1 − p), Θ by 30-day taker volume: 0.095 (< $10K), 0.085 (< $50K), 0.075 (< $250K), 0.0695 ($250K+); new accounts 0.0695 for the first 7 days Nearest cent, half to even
polymarket.com C × rate × p × (1 − p), rate by category (Crypto 0.07; Sports, Economics, Culture, Weather, Other, Combos 0.05; Finance, Politics, Mentions, Tech 0.04; Geopolitics 0) 5 decimals

The numbers in this table are for reading only. The code takes every rate, tier, multiplier and rounding rule (including Kalshi's fee + position cost basis) from prediction_market_fees.json.

Not modelled: Polymarket US combo fees and maker rebates, polymarket.com maker and taker rebate programs, and per-market exceptions (polymarket.com markets carry their own feeSchedule, Kalshi series their own multiplier). Check the market when it matters.

Sources

Platform Source Rates current as of
Kalshi https://kalshi.com/docs/kalshi-fee-schedule.pdf (version 7.7.26) 2026-11-10
Polymarket US https://docs.polymarket.us/fees 2026-11-09
polymarket.com https://docs.polymarket.com/trading/fees 2026-11-08

The tests lock the formulas to the worked examples and fee tables on these pages, with a link to the source in each test.

Updating the rates

All rates live in src/pmfees/data/prediction_market_fees.json. Each platform has its own as_of (the date its rates were last checked against source_url). SwapHunt checks the official fee pages every week; when a rate changes, the updated file arrives here as a pull request, and a new release follows after review. To use newer rates without waiting for a release:

from pmfees import fee, load_rates

rates = load_rates("prediction_market_fees.json")
fee("kalshi", 0.50, 100, rates=rates)

or set PMFEES_RATES_FILE=/path/to/prediction_market_fees.json, or pass --rates on the command line. A file with a missing field or an unknown rounding mode is rejected with a RatesError that names the field.

Development

pip install -e . pytest ruff mypy
pytest
ruff check . && ruff format --check .
mypy

Releases go to PyPI from GitHub Actions with trusted publishing: bump __version__, add a CHANGELOG entry, and push a v<version> tag. The publish job waits for approval.

Disclaimer

Fee estimates for information only. The platform's own confirmation is what you pay.

License

MIT. See LICENSE.

Metadata

Release files for pmfees 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pmfees 0.1.0
File Size Uploaded Provenance Actions
pmfees-0.1.0.tar.gz 27.6 kB Without provenance Details for pmfees-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pmfees 0.1.0
File Interpreter ABI Platform Actions
pmfees-0.1.0-py3-none-any.whl Python 3 none any Details for pmfees-0.1.0-py3-none-any.whl

Total release size: 46.1 kB

Release files / pmfees-0.1.0.tar.gz

Download URL pmfees-0.1.0.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e30bd6a308c735b4c04e4a5aec735aac94b528970c58a56947e1cc4155b76904
BLAKE2b-256 checksum
How to use checksums
c115411dc085ff7fe68765f022807c0fe9dc4f6fd28aa794f1ed7b056e05d665
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pmfees-0.1.0-py3-none-any.whl

Download URL pmfees-0.1.0-py3-none-any.whl
Size 18.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ead19a43ab87fedc5b013b103be8d2f2c5f30427ad80f583e9fc684422dd426
BLAKE2b-256 checksum
How to use checksums
e9528f743b8b402018592fa6992541e75f30ef165c2c6352a12fa97efd9879e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for pmfees 0.1.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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page