Polymarket PnL Precision Calculation: Why Your PnL Calculation Might Be Wrong?

Bitsfull2026/05/02 11:0015335

概要:

Doing Polymarket Quant, the first step is not to find a strategy, but to first confirm whether your P&L calculations are correct.


I've been trading on Polymarket with automated strategies for half a year, and the biggest pitfall I've encountered is not a failed strategy, but the inability to correctly calculate how much money I've actually made.


It's not that I'm bad at math. It's that Polymarket's P&L calculation itself is a minefield. The numbers provided by the official API are wrong, the rankings displayed on third-party analytics websites are also wrong. Even if you write your own script to calculate, it's likely still wrong.


How off is the deviation? The third-ranked user on the leaderboard, kch123, miscalculated his P&L by -$3.5 million, showing a loss, when he actually made $11.4 million in profit. It's not just a small percentage difference — the profitability signs are even reversed.


This article breaks down every pitfall I've encountered. Whether you're trading, developing tools, or checking the leaderboard, you'll run into these issues sooner or later.


Pitfall 1: cashPnl Does Not Include Settled Profits


The most intuitive approach: pull the /positions endpoint and sum the cashPnl (cash P&L) field.


Testing with the top 15 leaderboard addresses:


swisstony: Sum of cashPnl +$35,000, actual leaderboard +$5.6 million, a difference of 158 times


kch123: Sum of cashPnl -$3.52 million, actual leaderboard +$11.4 million, with reversed signs


gmanas: Sum of cashPnl -$2.64 million, actual leaderboard +$5.02 million, with reversed signs


For these three addresses, the signs of the profits are directly reversed.


Reason: The cashPnl returned by the /positions endpoint does not include the realized P&L of closed positions. When a winning position is automatically settled into USDC, that position vanishes from the API response. What remains are unsettled positions, often dominated by unrealized losses.


You may think you're calculating the total PnL, but you're actually only looking at the unsettled portion.


Pitfall 2: The makerPnl Field Misalignment with On-chain Cash Flow


In the transaction data JSONL, there is a makerPnl (liquidity provider PnL) field, which seems to be designed for calculating PnL. Don't trust it.


After observing the market making data, I noticed that the SUM(makerPnl) figure is off by an order of magnitude compared to the on-chain cash flow reconciliation. The specific multiplier may vary depending on the scenario, but the trend is consistent: the internal logic of makerPnl does not align with the actual USDC flow.


Regardless of the magnitude of the deviation, the conclusion remains the same: do not use this field to calculate PnL.


Pitfall 3: Unable to Deduplicate by txHash Alone


This is the most counterintuitive.


Multiple records appear with the same txHash (transaction hash). The typical initial reaction is: duplicate data, deduplicate.


However, this approach is not suitable. In the PM's CLOB (on-chain limit order book), multiple maker orders can be matched within a single on-chain transaction. The multiple records under the same txHash represent real independent fills.


Previously, when I deduplicated based on txHash + asset, I undercounted $133 on the BUY side. After validating on the Polygon chain, it was evident that within one transaction hash, there were indeed multiple independent USDC Transfer events, each corresponding to a real trade.


Conclusion: You cannot deduplicate based on txHash alone. To calculate PnL, directly sum up the raw data from /activity.


Pitfall 4: There is a Ceiling on Pagination Offset


When paging through the /activity endpoint using an offset, if it exceeds 3000 entries, a direct HTTP 400 error is returned. This limit is not documented.


All three scenarios above have been verified: GET /activity?offset=3100 returns an HTTP 400 error with the message "max historical activity offset of 3000 exceeded." For heavy users with tens of thousands of transactions, 3000 entries are simply not sufficient.


Use the end parameter (pass the timestamp of the last transaction on the previous page - 1) for cursor-based pagination, with no upper limit.


Pitfall 5: Ranking Discrepancy in PnL Calculation


After calculating the PnL for an address, you compare it to the leaderboard and notice a slight discrepancy.


In most cases, the difference is within $10 (due to real-time fluctuations in position value). However, if the difference is significantly larger, possible reasons include: the leaderboard's aggregation window, cache refresh delays, or users binding multiple proxy wallets.


In testing, the PnL for a single address calculated using the cash flow method closely matches the lb-api return value. If your results have a large variance, first check if your pagination is complete (Pitfall 4) and if you have used incorrect fields (Pitfalls 1-2).


Best Practice


After trying various approaches, I have validated that the most reliable method is using the Data API for cash flow aggregation. Without relying on any precomputed fields, calculate fund flows directly from the raw transaction records.


Formula:


PnL = SUM(TRADE where side=SELL) + SUM(REDEEM) + SUM(MERGE) + SUM(MAKER_REBATE) + SUM(REWARD) - SUM(TRADE where side=BUY) - SUM(SPLIT) + Position Value


· TRADE BUY: Spend USDC to buy tokens (expense)

· TRADE SELL: Sell tokens to receive USDC (income)

· REDEEM: Redeem USDC from winning position (income)

· SPLIT: Mint tokens by splitting USDC (expense)

· MERGE: Merge token pairs back to USDC (income)

· MAKER_REBATE: Maker rebate (income)

· REWARD: Reward/ Airdrop (income)


· Data Source:

GET /activity?user=<address>&limit=500, use end for pagination, sum by type after full pull.


· Position Market Value:

GET /positions?user=<address>, size × curPrice.


· Cross-Validation:

Compare the calculation result with the Polymarket Leaderboard API (lb-api.polymarket.com/profit?window=all&address=X), consider it a pass if the difference is <$10. The variance is due to real-time fluctuation in position market value.


Validation: Top 15 Leaderboard Test


After calculating using the cash flow method, cross-validate with Leaderboard API:


swisstony: Cash Flow +$5.601 million, Leaderboard +$5.601 million, difference < $10


kch123: Cash Flow +$11.396 million, Leaderboard +$11.396 million, difference < $10


gmanas: Cash Flow +$5.024 million, Leaderboard +$5.024 million, difference < $10


The error for all three addresses is within $10, with the difference stemming from real-time fluctuation in position market value.


After the method was successfully run, I used it to analyze the true gains and losses of over a hundred top addresses. That's another story.


Summary


SUM(cashPnl) from /positions → Not viable, does not include settled profits, sign may be reversed


Sum of makerPnl field → Not viable, inconsistent with on-chain cash flow


Calculate after deduplicating by txHash → Not viable, $100+, deleted real fill


Offset Pagination + Summation → Not feasible, data truncation, error for >3000


Data API Cash Flow Method → Currently the most reliable, <$10


The first step in quant trading is not to find alpha. It is to first ensure your calculations are correct.


All the above come from real-world trading pitfalls, not theoretical deductions. PM's API behavior could change at any time, so it is recommended to regularly cross-validate your calculations using a leaderboard API.



Welcome to join the official BlockBeats community:

Telegram Subscription Group: https://t.me/theblockbeats

Telegram Discussion Group: https://t.me/BlockBeats_App

Official Twitter Account: https://twitter.com/BlockBeatsAsia