pmfees 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pmfees-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SwapHunt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md LICENSE
2
+ recursive-include tests *.py *.json
pmfees-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,232 @@
1
+ Metadata-Version: 2.4
2
+ Name: pmfees
3
+ Version: 0.1.0
4
+ Summary: Exact trading fees for Kalshi, Polymarket US and polymarket.com, with a CLI and break-even helper.
5
+ Author-email: SwapHunt <github@swaphunt.dev>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/swaphunt/pmfees
8
+ Project-URL: Source, https://github.com/swaphunt/pmfees
9
+ Project-URL: Issues, https://github.com/swaphunt/pmfees/issues
10
+ Project-URL: Changelog, https://github.com/swaphunt/pmfees/blob/main/CHANGELOG.md
11
+ Project-URL: Fee calculator, https://swaphunt.dev/tools/kalshi-vs-polymarket-fee-calculator
12
+ Keywords: kalshi,polymarket,prediction markets,fees,trading
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Typing :: Typed
16
+ Classifier: Development Status :: 4 - Beta
17
+ Classifier: Topic :: Office/Business :: Financial
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Dynamic: license-file
22
+
23
+ # pmfees
24
+
25
+ Exact trading fees for the prediction market platforms **Kalshi**, **Polymarket US** and
26
+ **polymarket.com** (international), as a small Python library and a command line tool.
27
+
28
+ - The platforms' own formulas and rounding rules: Kalshi rounds up so that fee + position cost
29
+ is a whole centicent ($0.0001), Polymarket US rounds to the cent with banker's rounding,
30
+ polymarket.com rounds to 5 decimals.
31
+ - Exact decimal arithmetic (`decimal.Decimal`), so $1.75 is $1.75 and not $1.7500000000000002.
32
+ - A break-even helper: how far the price has to move before a round trip is in profit after
33
+ the fee on both orders.
34
+ - No dependencies outside the Python standard library. Typed (`py.typed`).
35
+
36
+ Rates current as of: Kalshi 2026-11-10 (fee schedule 7.7.26), Polymarket US 2026-11-09,
37
+ polymarket.com 2026-11-08. Each platform's date and source are in the rates file and in every result.
38
+
39
+ Other ways to get the same numbers, from the same rates file:
40
+
41
+ - In a browser: the [SwapHunt Kalshi vs Polymarket fee calculator](https://swaphunt.dev/tools/kalshi-vs-polymarket-fee-calculator).
42
+ - Over HTTP, for agents: [`GET https://x402.swaphunt.dev/v1/pm/fees`](https://swaphunt.dev/api), paid per call
43
+ with [x402](https://www.x402.org/) in USDC. This package is free; the endpoint exists for agents that
44
+ cannot install a library.
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ pip install pmfees
50
+ ```
51
+
52
+ Python 3.10 or newer.
53
+
54
+ ## Command line
55
+
56
+ ```bash
57
+ pmfees kalshi --price 0.50 --contracts 100
58
+ ```
59
+
60
+ ```text
61
+ Kalshi taker fee: $1.75 (3.50% of trade value at 50¢)
62
+ buy 100 contracts at $0.50 = $50.00 trade value
63
+ base rate: 0.07
64
+ multiplier: 1
65
+ fee schedule version: 7.7.26
66
+ 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
67
+ rates as of 2026-11-10 · source: https://kalshi.com/docs/kalshi-fee-schedule.pdf
68
+ ```
69
+
70
+ More examples:
71
+
72
+ ```bash
73
+ # Polymarket US, Tier 1 (under $10,000 of 30-day taker volume, the default)
74
+ pmfees polymarket-us --price 0.50 --contracts 100
75
+ # -> Polymarket US taker fee: $2.38 (4.76% of trade value at 50¢) [0.095 × 100 × 0.5 × 0.5 = 2.375]
76
+
77
+ # polymarket.com, Crypto category
78
+ pmfees polymarket --price 0.25 --contracts 100 --category Crypto
79
+ # -> polymarket.com taker fee: $1.3125 (5.25% of trade value at 25¢)
80
+
81
+ # Break-even: buy 100 on Kalshi at 50¢, when is selling in profit?
82
+ pmfees kalshi --price 0.50 --contracts 100 --break-even
83
+ # -> 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
84
+ ```
85
+
86
+ Options:
87
+
88
+ | Option | Platforms | Meaning |
89
+ |---|---|---|
90
+ | `--price` | all | Price of the contract you trade, in dollars (0 < price < 1) |
91
+ | `--contracts` | all | Number of contracts (shares on polymarket.com) |
92
+ | `--side buy\|sell` | all | Changes the cash flow only; the fee formulas are symmetric |
93
+ | `--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 |
94
+ | `--multiplier` | kalshi | Fee multiplier M (default 1 for takers, 0 for makers) |
95
+ | `--tier 1-4\|new` | polymarket-us | Taker tier, or `new` for the first 7 days of a new account (default 1) |
96
+ | `--volume` | polymarket-us | Trailing 30-day taker volume in USD; picks the tier for you |
97
+ | `--category` | polymarket | Market category, e.g. `Crypto`, `Sports`, `Politics` (required) |
98
+ | `--break-even`, `--tick` | all | Also print the break-even move (price step, default 0.01) |
99
+ | `--json` | all | Machine-readable output |
100
+ | `--rates PATH` | all | Use an updated rates file |
101
+
102
+ `pmfees rates` prints the loaded rates and their date.
103
+
104
+ ## Library
105
+
106
+ ```python
107
+ from pmfees import fee, break_even
108
+
109
+ r = fee("kalshi", 0.50, 100)
110
+ r.fee # Decimal('1.7500') what you pay, in USD
111
+ r.raw_fee # Decimal('1.7500') before rounding
112
+ r.fee_pct_of_trade_value # Decimal('3.500')
113
+ r.breakdown() # dict of strings: coefficient, rounding, formula, source_url, rates_as_of, ...
114
+
115
+ fee("polymarket-us", 0.10, 1000, "buy", tier=4).fee # Decimal('6.26')
116
+ fee("polymarket-us", 0.10, 1000, volume_30d=12_500).fee # Tier 2
117
+ fee("polymarket", 0.25, 100, category="Crypto").fee # Decimal('1.31250')
118
+ fee("kalshi", 0.50, 1).fee # Decimal('0.0175') centicent rounding, not $0.02
119
+ fee("kalshi", 0.50, 100, maker=True).fee # Decimal('0.0000') maker M defaults to 0
120
+ fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee # Decimal('0.4375')
121
+ fee("kalshi", 0.50, 100, multiplier=0.5).fee # Decimal('0.8750')
122
+
123
+ b = break_even("polymarket-us", 0.40, 500, tier=2)
124
+ b.exit_price, b.move_cents # (Decimal('0.45'), Decimal('5.00'))
125
+ ```
126
+
127
+ Signature: `fee(platform, price, contracts, side="buy", tier=None, maker=False, *, category=None,
128
+ multiplier=None, volume_30d=None, rates=None) -> FeeResult`. Platform names: `kalshi`,
129
+ `polymarket-us`, `polymarket` (also `polymarket.com`). Prices and counts can be `str`, `int`,
130
+ `float` or `Decimal`; floats are converted through `str`, so `0.1` means exactly 0.1.
131
+
132
+ `break_even(...)` takes the same arguments plus `tick`. It opens the position at `price`, then
133
+ walks the price in `tick` steps (up for a buy, down for a sell) and returns the first exit price
134
+ where proceeds − cost − entry fee − exit fee > 0, or `exit_price=None` if no price before $1 (or
135
+ $0) works.
136
+
137
+ ## Kalshi: centicent rounding and the multiplier
138
+
139
+ Kalshi does not round the fee on its own. It rounds **fee + position cost** (contracts × price) up to
140
+ a whole centicent ($0.0001), per the fee schedule (version 7.7.26, page 2). Most of the time that
141
+ looks like rounding the fee up to four decimals, but the fee alone is what you see change:
142
+
143
+ ```python
144
+ from pmfees import fee
145
+
146
+ fee("kalshi", 0.50, 1).fee # Decimal('0.0175') 0.07 × 1 × 0.5 × 0.5 = 0.0175 exactly; not $0.02
147
+ fee("kalshi", 0.33, 7).fee # Decimal('0.1084') raw 0.108339; 2.31 + 0.108339 = 2.418339 -> 2.4184
148
+ ```
149
+
150
+ Accounts cleared through a broker (FCM) keep balances in whole cents, so there the fee rounds to the
151
+ cent ([Kalshi docs](https://docs.kalshi.com/getting_started/fee_rounding.md)). pmfees models
152
+ kalshi.com accounts (direct members).
153
+
154
+ Each Kalshi series has a fee multiplier M: 1 (standard), 0.5 or 0. Takers default to M = 1, makers
155
+ to M = 0, because Kalshi charges makers only on series listed with maker fees:
156
+
157
+ ```python
158
+ fee("kalshi", 0.25, 100).fee # Decimal('1.3125') M = 1
159
+ fee("kalshi", 0.25, 100, multiplier=0.5).fee # Decimal('0.6563') raw 0.65625, rounded up
160
+ fee("kalshi", 0.50, 100, maker=True).fee # Decimal('0.0000') maker, M defaults to 0
161
+ fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee # Decimal('0.4375') 0.0175 × 100 × 0.25
162
+ ```
163
+
164
+ ```bash
165
+ pmfees kalshi --price 0.25 --contracts 100 --multiplier 0.5
166
+ # -> Kalshi taker fee: $0.6563 (2.63% of trade value at 25¢)
167
+ ```
168
+
169
+ ## The formulas
170
+
171
+ | Platform | Taker fee | Rounding |
172
+ |---|---|---|
173
+ | 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) |
174
+ | 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 |
175
+ | 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 |
176
+
177
+ The numbers in this table are for reading only. The code takes every rate, tier, multiplier and
178
+ rounding rule (including Kalshi's fee + position cost basis) from `prediction_market_fees.json`.
179
+
180
+ Not modelled: Polymarket US combo fees and maker rebates, polymarket.com maker and taker rebate
181
+ programs, and per-market exceptions (polymarket.com
182
+ markets carry their own `feeSchedule`, Kalshi series their own multiplier). Check the market when
183
+ it matters.
184
+
185
+ ## Sources
186
+
187
+ | Platform | Source | Rates current as of |
188
+ |---|---|---|
189
+ | Kalshi | <https://kalshi.com/docs/kalshi-fee-schedule.pdf> (version 7.7.26) | 2026-11-10 |
190
+ | Polymarket US | <https://docs.polymarket.us/fees> | 2026-11-09 |
191
+ | polymarket.com | <https://docs.polymarket.com/trading/fees> | 2026-11-08 |
192
+
193
+ The tests lock the formulas to the worked examples and fee tables on these pages, with a link
194
+ to the source in each test.
195
+
196
+ ## Updating the rates
197
+
198
+ All rates live in `src/pmfees/data/prediction_market_fees.json`. Each platform has its own `as_of`
199
+ (the date its rates were last checked against `source_url`). SwapHunt checks the official fee pages
200
+ every week; when a rate changes, the updated file arrives here as a pull request, and a new release
201
+ follows after review. To use newer rates without waiting for a release:
202
+
203
+ ```python
204
+ from pmfees import fee, load_rates
205
+
206
+ rates = load_rates("prediction_market_fees.json")
207
+ fee("kalshi", 0.50, 100, rates=rates)
208
+ ```
209
+
210
+ or set `PMFEES_RATES_FILE=/path/to/prediction_market_fees.json`, or pass `--rates` on the
211
+ command line. A file with a missing field or an unknown rounding mode is rejected with a
212
+ `RatesError` that names the field.
213
+
214
+ ## Development
215
+
216
+ ```bash
217
+ pip install -e . pytest ruff mypy
218
+ pytest
219
+ ruff check . && ruff format --check .
220
+ mypy
221
+ ```
222
+
223
+ Releases go to PyPI from GitHub Actions with trusted publishing: bump `__version__`, add a
224
+ CHANGELOG entry, and push a `v<version>` tag. The publish job waits for approval.
225
+
226
+ ## Disclaimer
227
+
228
+ Fee estimates for information only. The platform's own confirmation is what you pay.
229
+
230
+ ## License
231
+
232
+ MIT. See [LICENSE](LICENSE).
pmfees-0.1.0/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # pmfees
2
+
3
+ Exact trading fees for the prediction market platforms **Kalshi**, **Polymarket US** and
4
+ **polymarket.com** (international), as a small Python library and a command line tool.
5
+
6
+ - The platforms' own formulas and rounding rules: Kalshi rounds up so that fee + position cost
7
+ is a whole centicent ($0.0001), Polymarket US rounds to the cent with banker's rounding,
8
+ polymarket.com rounds to 5 decimals.
9
+ - Exact decimal arithmetic (`decimal.Decimal`), so $1.75 is $1.75 and not $1.7500000000000002.
10
+ - A break-even helper: how far the price has to move before a round trip is in profit after
11
+ the fee on both orders.
12
+ - No dependencies outside the Python standard library. Typed (`py.typed`).
13
+
14
+ Rates current as of: Kalshi 2026-11-10 (fee schedule 7.7.26), Polymarket US 2026-11-09,
15
+ polymarket.com 2026-11-08. Each platform's date and source are in the rates file and in every result.
16
+
17
+ Other ways to get the same numbers, from the same rates file:
18
+
19
+ - In a browser: the [SwapHunt Kalshi vs Polymarket fee calculator](https://swaphunt.dev/tools/kalshi-vs-polymarket-fee-calculator).
20
+ - Over HTTP, for agents: [`GET https://x402.swaphunt.dev/v1/pm/fees`](https://swaphunt.dev/api), paid per call
21
+ with [x402](https://www.x402.org/) in USDC. This package is free; the endpoint exists for agents that
22
+ cannot install a library.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install pmfees
28
+ ```
29
+
30
+ Python 3.10 or newer.
31
+
32
+ ## Command line
33
+
34
+ ```bash
35
+ pmfees kalshi --price 0.50 --contracts 100
36
+ ```
37
+
38
+ ```text
39
+ Kalshi taker fee: $1.75 (3.50% of trade value at 50¢)
40
+ buy 100 contracts at $0.50 = $50.00 trade value
41
+ base rate: 0.07
42
+ multiplier: 1
43
+ fee schedule version: 7.7.26
44
+ 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
45
+ rates as of 2026-11-10 · source: https://kalshi.com/docs/kalshi-fee-schedule.pdf
46
+ ```
47
+
48
+ More examples:
49
+
50
+ ```bash
51
+ # Polymarket US, Tier 1 (under $10,000 of 30-day taker volume, the default)
52
+ pmfees polymarket-us --price 0.50 --contracts 100
53
+ # -> Polymarket US taker fee: $2.38 (4.76% of trade value at 50¢) [0.095 × 100 × 0.5 × 0.5 = 2.375]
54
+
55
+ # polymarket.com, Crypto category
56
+ pmfees polymarket --price 0.25 --contracts 100 --category Crypto
57
+ # -> polymarket.com taker fee: $1.3125 (5.25% of trade value at 25¢)
58
+
59
+ # Break-even: buy 100 on Kalshi at 50¢, when is selling in profit?
60
+ pmfees kalshi --price 0.50 --contracts 100 --break-even
61
+ # -> 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
62
+ ```
63
+
64
+ Options:
65
+
66
+ | Option | Platforms | Meaning |
67
+ |---|---|---|
68
+ | `--price` | all | Price of the contract you trade, in dollars (0 < price < 1) |
69
+ | `--contracts` | all | Number of contracts (shares on polymarket.com) |
70
+ | `--side buy\|sell` | all | Changes the cash flow only; the fee formulas are symmetric |
71
+ | `--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 |
72
+ | `--multiplier` | kalshi | Fee multiplier M (default 1 for takers, 0 for makers) |
73
+ | `--tier 1-4\|new` | polymarket-us | Taker tier, or `new` for the first 7 days of a new account (default 1) |
74
+ | `--volume` | polymarket-us | Trailing 30-day taker volume in USD; picks the tier for you |
75
+ | `--category` | polymarket | Market category, e.g. `Crypto`, `Sports`, `Politics` (required) |
76
+ | `--break-even`, `--tick` | all | Also print the break-even move (price step, default 0.01) |
77
+ | `--json` | all | Machine-readable output |
78
+ | `--rates PATH` | all | Use an updated rates file |
79
+
80
+ `pmfees rates` prints the loaded rates and their date.
81
+
82
+ ## Library
83
+
84
+ ```python
85
+ from pmfees import fee, break_even
86
+
87
+ r = fee("kalshi", 0.50, 100)
88
+ r.fee # Decimal('1.7500') what you pay, in USD
89
+ r.raw_fee # Decimal('1.7500') before rounding
90
+ r.fee_pct_of_trade_value # Decimal('3.500')
91
+ r.breakdown() # dict of strings: coefficient, rounding, formula, source_url, rates_as_of, ...
92
+
93
+ fee("polymarket-us", 0.10, 1000, "buy", tier=4).fee # Decimal('6.26')
94
+ fee("polymarket-us", 0.10, 1000, volume_30d=12_500).fee # Tier 2
95
+ fee("polymarket", 0.25, 100, category="Crypto").fee # Decimal('1.31250')
96
+ fee("kalshi", 0.50, 1).fee # Decimal('0.0175') centicent rounding, not $0.02
97
+ fee("kalshi", 0.50, 100, maker=True).fee # Decimal('0.0000') maker M defaults to 0
98
+ fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee # Decimal('0.4375')
99
+ fee("kalshi", 0.50, 100, multiplier=0.5).fee # Decimal('0.8750')
100
+
101
+ b = break_even("polymarket-us", 0.40, 500, tier=2)
102
+ b.exit_price, b.move_cents # (Decimal('0.45'), Decimal('5.00'))
103
+ ```
104
+
105
+ Signature: `fee(platform, price, contracts, side="buy", tier=None, maker=False, *, category=None,
106
+ multiplier=None, volume_30d=None, rates=None) -> FeeResult`. Platform names: `kalshi`,
107
+ `polymarket-us`, `polymarket` (also `polymarket.com`). Prices and counts can be `str`, `int`,
108
+ `float` or `Decimal`; floats are converted through `str`, so `0.1` means exactly 0.1.
109
+
110
+ `break_even(...)` takes the same arguments plus `tick`. It opens the position at `price`, then
111
+ walks the price in `tick` steps (up for a buy, down for a sell) and returns the first exit price
112
+ where proceeds − cost − entry fee − exit fee > 0, or `exit_price=None` if no price before $1 (or
113
+ $0) works.
114
+
115
+ ## Kalshi: centicent rounding and the multiplier
116
+
117
+ Kalshi does not round the fee on its own. It rounds **fee + position cost** (contracts × price) up to
118
+ a whole centicent ($0.0001), per the fee schedule (version 7.7.26, page 2). Most of the time that
119
+ looks like rounding the fee up to four decimals, but the fee alone is what you see change:
120
+
121
+ ```python
122
+ from pmfees import fee
123
+
124
+ fee("kalshi", 0.50, 1).fee # Decimal('0.0175') 0.07 × 1 × 0.5 × 0.5 = 0.0175 exactly; not $0.02
125
+ fee("kalshi", 0.33, 7).fee # Decimal('0.1084') raw 0.108339; 2.31 + 0.108339 = 2.418339 -> 2.4184
126
+ ```
127
+
128
+ Accounts cleared through a broker (FCM) keep balances in whole cents, so there the fee rounds to the
129
+ cent ([Kalshi docs](https://docs.kalshi.com/getting_started/fee_rounding.md)). pmfees models
130
+ kalshi.com accounts (direct members).
131
+
132
+ Each Kalshi series has a fee multiplier M: 1 (standard), 0.5 or 0. Takers default to M = 1, makers
133
+ to M = 0, because Kalshi charges makers only on series listed with maker fees:
134
+
135
+ ```python
136
+ fee("kalshi", 0.25, 100).fee # Decimal('1.3125') M = 1
137
+ fee("kalshi", 0.25, 100, multiplier=0.5).fee # Decimal('0.6563') raw 0.65625, rounded up
138
+ fee("kalshi", 0.50, 100, maker=True).fee # Decimal('0.0000') maker, M defaults to 0
139
+ fee("kalshi", 0.50, 100, maker=True, multiplier=1).fee # Decimal('0.4375') 0.0175 × 100 × 0.25
140
+ ```
141
+
142
+ ```bash
143
+ pmfees kalshi --price 0.25 --contracts 100 --multiplier 0.5
144
+ # -> Kalshi taker fee: $0.6563 (2.63% of trade value at 25¢)
145
+ ```
146
+
147
+ ## The formulas
148
+
149
+ | Platform | Taker fee | Rounding |
150
+ |---|---|---|
151
+ | 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) |
152
+ | 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 |
153
+ | 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 |
154
+
155
+ The numbers in this table are for reading only. The code takes every rate, tier, multiplier and
156
+ rounding rule (including Kalshi's fee + position cost basis) from `prediction_market_fees.json`.
157
+
158
+ Not modelled: Polymarket US combo fees and maker rebates, polymarket.com maker and taker rebate
159
+ programs, and per-market exceptions (polymarket.com
160
+ markets carry their own `feeSchedule`, Kalshi series their own multiplier). Check the market when
161
+ it matters.
162
+
163
+ ## Sources
164
+
165
+ | Platform | Source | Rates current as of |
166
+ |---|---|---|
167
+ | Kalshi | <https://kalshi.com/docs/kalshi-fee-schedule.pdf> (version 7.7.26) | 2026-11-10 |
168
+ | Polymarket US | <https://docs.polymarket.us/fees> | 2026-11-09 |
169
+ | polymarket.com | <https://docs.polymarket.com/trading/fees> | 2026-11-08 |
170
+
171
+ The tests lock the formulas to the worked examples and fee tables on these pages, with a link
172
+ to the source in each test.
173
+
174
+ ## Updating the rates
175
+
176
+ All rates live in `src/pmfees/data/prediction_market_fees.json`. Each platform has its own `as_of`
177
+ (the date its rates were last checked against `source_url`). SwapHunt checks the official fee pages
178
+ every week; when a rate changes, the updated file arrives here as a pull request, and a new release
179
+ follows after review. To use newer rates without waiting for a release:
180
+
181
+ ```python
182
+ from pmfees import fee, load_rates
183
+
184
+ rates = load_rates("prediction_market_fees.json")
185
+ fee("kalshi", 0.50, 100, rates=rates)
186
+ ```
187
+
188
+ or set `PMFEES_RATES_FILE=/path/to/prediction_market_fees.json`, or pass `--rates` on the
189
+ command line. A file with a missing field or an unknown rounding mode is rejected with a
190
+ `RatesError` that names the field.
191
+
192
+ ## Development
193
+
194
+ ```bash
195
+ pip install -e . pytest ruff mypy
196
+ pytest
197
+ ruff check . && ruff format --check .
198
+ mypy
199
+ ```
200
+
201
+ Releases go to PyPI from GitHub Actions with trusted publishing: bump `__version__`, add a
202
+ CHANGELOG entry, and push a `v<version>` tag. The publish job waits for approval.
203
+
204
+ ## Disclaimer
205
+
206
+ Fee estimates for information only. The platform's own confirmation is what you pay.
207
+
208
+ ## License
209
+
210
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pmfees"
7
+ version = "0.1.0"
8
+ description = "Exact trading fees for Kalshi, Polymarket US and polymarket.com, with a CLI and break-even helper."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "SwapHunt", email = "github@swaphunt.dev" }]
13
+ requires-python = ">=3.10"
14
+ dependencies = []
15
+ keywords = ["kalshi", "polymarket", "prediction markets", "fees", "trading"]
16
+ classifiers = [
17
+ "Programming Language :: Python :: 3",
18
+ "Operating System :: OS Independent",
19
+ "Typing :: Typed",
20
+ "Development Status :: 4 - Beta",
21
+ "Topic :: Office/Business :: Financial",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/swaphunt/pmfees"
26
+ Source = "https://github.com/swaphunt/pmfees"
27
+ Issues = "https://github.com/swaphunt/pmfees/issues"
28
+ Changelog = "https://github.com/swaphunt/pmfees/blob/main/CHANGELOG.md"
29
+ "Fee calculator" = "https://swaphunt.dev/tools/kalshi-vs-polymarket-fee-calculator"
30
+
31
+ [project.scripts]
32
+ pmfees = "pmfees.cli:main"
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["src"]
36
+
37
+ [tool.setuptools.package-data]
38
+ pmfees = ["py.typed", "data/prediction_market_fees.json"]
39
+
40
+ [tool.ruff]
41
+ line-length = 110
42
+ target-version = "py310"
43
+
44
+ [tool.ruff.lint]
45
+ select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF"]
46
+ ignore = ["RUF001", "RUF002", "RUF003"] # Θ, × and − are intentional in formulas and docs
47
+
48
+ [tool.mypy]
49
+ strict = true
50
+ python_version = "3.10"
51
+ mypy_path = "src"
52
+ files = ["src", "tests"]
pmfees-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,26 @@
1
+ """pmfees: exact trading fees for Kalshi, Polymarket US and polymarket.com.
2
+
3
+ All rates, tiers, multipliers and rounding rules come from ``prediction_market_fees.json``
4
+ (bundled, or your own file via ``load_rates(path)`` / ``PMFEES_RATES_FILE``).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ __version__ = "0.1.0"
10
+
11
+ from .core import PLATFORMS, BreakEven, FeeResult, break_even, fee, platform_key
12
+ from .rates import Rates, RatesError, default_rates, load_rates
13
+
14
+ __all__ = [
15
+ "PLATFORMS",
16
+ "BreakEven",
17
+ "FeeResult",
18
+ "Rates",
19
+ "RatesError",
20
+ "__version__",
21
+ "break_even",
22
+ "default_rates",
23
+ "fee",
24
+ "load_rates",
25
+ "platform_key",
26
+ ]
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())