← Leo Labs

Polymarket PnL Calculation: Why Your Profit Numbers Are Probably Wrong

Five calculation traps dissected with top-15 leaderboard validation

I've been running quantitative trading strategies on Polymarket for six months. The biggest trap I fell into wasn't a failed strategy—it was not knowing how much money I was actually making.

Polymarket's PnL calculation is a minefield. The official API gives you wrong numbers. Third-party analytics sites show incorrect rankings. Write your own script? Probably still wrong.

How far off? Leaderboard rank #3 kch123: wrong methods show -$3.5M loss, actual profit is +$11.4M. The sign is completely reversed.

Trap 1: Positions API Only Shows Losses

Most intuitive approach: pull /positions endpoint, sum up the cashPnl field.

Testing with three top-15 leaderboard addresses:

UsercashPnl SumActual Leaderboard PnLError
swisstony+$35K+$5.6M158x off
kch123-$3.5M+$11.4MSign flipped
gmanas-$2.6M+$5.0MSign flipped

Three addresses, two with completely reversed profit/loss signs.

The issue hides in PM's auto-redemption mechanism. Winning positions get automatically redeemed to USDC. Once redeemed, those positions disappear from the API. What remains are unresolved, losing, underwater positions.

You think you're calculating total PnL. You're only seeing the losing half.

Trap 2: makerPnl Inflates by 16x

The trading data JSONL includes a makerPnl field. Sounds like it's built for PnL calculations. Don't trust it.

Testing with my H35 strategy: SUM(makerPnl) calculated +$1,270. On-chain cash flow verification? +$79.

16x difference. This field's internal logic doesn't align with on-chain USDC flows. The exact reason is unclear, but the conclusion is definitive.

Trap 3: Deduplication Deletes Real Trades

Same txHash appears in multiple records with identical amounts. Normal reaction: duplicate data, deduplicate.

Wrong. These are real multiple maker fills.

I previously deduplicated by txHash + asset, undercounting BUY side by $133. Verifying on Polygon chain revealed that one transaction hash indeed contains multiple independent USDC Transfer events, each corresponding to a real fill. PM's CLOB can match multiple maker orders within one on-chain transaction.

Don't deduplicate. Sum directly.

Trap 4: Offset Pagination Has a Ceiling

Using offset for /activity endpoint pagination? It throws 400 errors beyond 3000 records. Not documented.

Verified on all three addresses: GET /activity?offset=3100 returns HTTP 400, error message max historical activity offset of 3000 exceeded. Top players have tens of thousands of trades—3000 records isn't enough.

Use end parameter (pass last record's timestamp - 1) for cursor pagination. No limit.

Trap 5: Leaderboard Aggregates by User, Not Wallet

You calculate a single address's PnL, compare with leaderboard—off by tens of thousands.

Not a calculation error. Leaderboard sums all proxy wallets under the same username. Many top players use multiple wallets. Single address naturally mismatches.

Retail traders (single wallet) unaffected.

The Right Way: Data API Cash Flow Method

After trying various wrong approaches, the most reliable method is Data API cash flow aggregation. Don't use any pre-calculated fields—compute directly from raw transaction records.

PnL = SUM(SELL) + SUM(REDEEM) + SUM(MERGE) + SUM(REBATE)
    - SUM(BUY) - SUM(SPLIT)
    + Position Market Value
TypeMeaningDirection
BUYSpend USDC to buy tokensOutflow (-)
SELLSell tokens to recover USDCInflow (+)
REDEEMRedeem winning positions to USDCInflow (+)
SPLITMint USDC into token pairsOutflow (-)
MERGEMerge token pairs back to USDCInflow (+)
REBATEMaker rebatesInflow (+)

Data source: GET /activity?user=<address>&limit=500, paginate with end, pull complete history then sum by type.

Position market value: GET /positions?user=<address>, size × curPrice.

Cross-validation: Compare with Polymarket leaderboard API (lb-api.polymarket.com/profit?window=all&address=X), <$10 difference passes.

Validation: Top 15 Leaderboard Test

UserCash Flow PnLLeaderboard PnLDifference
swisstony+$5.601M+$5.601M< $10
kch123+$11.396M+$11.396M< $10
gmanas+$5.024M+$5.024M< $10

All three addresses within $10 error margin.

Summary

MethodReliable?Error
SUM(cashPnl) from PositionsNo10x, losses only
makerPnl field sumNo16x, internal logic inconsistent
Deduplicate by txHash then calculateNo$100+, deletes real fills
offset pagination + sumNoData truncation, >3000 errors
Data API cash flow methodMost reliable<$10

Step one in quantitative trading isn't finding alpha. It's making sure you're calculating correctly.

All above from live trading experience, not theory. PM's API behavior can change anytime—periodically cross-validate with leaderboard API.

Polymarket

Prediction Markets · Quantitative Trading