Polymarket PnL Accurate Calculation: Why Your Profit and Loss Might Be Incorrect?

Original Title: “Polymarket PnL Accurate Calculation: Why Your Profit and Loss Might Be Completely Wrong”
Original Author: Leo, Crypto Analyst

I’ve been developing automated trading on Polymarket for half a year, and the biggest pitfall I’ve encountered isn’t strategy failure, but that I couldn’t even accurately calculate how much I made or lost.

It’s not that I’m bad at it. It’s that PM’s PnL calculation itself is a minefield. The numbers provided by the official API are wrong, and third-party analysis websites’ rankings are also incorrect. You write your own scripts? Most likely still wrong.

How big is the deviation? The third-place address kch123, using an incorrect method, calculated a loss of $3.5 million, but the actual profit was $11.4 million. It’s not a few percentage points off—it’s that the profit and loss signs are reversed.

This article breaks down every pit I’ve fallen into. Traders, tool developers, ranking viewers—you will encounter these issues sooner or later.

Pit 1: cashPnl does not include settled profits and losses

The most intuitive approach: call the /positions API, sum the cashPnl (cash profit and loss) fields.

Testing the top 3 addresses on the leaderboard:

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

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

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

For these three addresses, two of the profit/loss signs are directly reversed.

Reason: The cashPnl returned by the /positions API does not include realized PnL from closed/redeemed positions. When winning positions are automatically redeemed into USDC, that position disappears from the API response. What remains are unsettled positions—often with unrealized losses.

You think you’re calculating total profit and loss, but you’re only getting the unsettled part.

Pit 2: makerPnl field does not match on-chain cash flow

The JSONL trading data has a makerPnl (market maker profit and loss) field, which sounds like it’s for calculating PnL. Don’t trust it.

In market-making data, I observed that the sum of makerPnl differs by an order of magnitude from on-chain cash flow calculations. The exact multiple varies by scenario, but the direction is consistent: the internal logic of makerPnl doesn’t match actual USDC flow.

No matter how big the deviation, the conclusion is the same: don’t use this field to calculate PnL.

Pit 3: Don’t deduplicate by txHash alone

This is the most counterintuitive.

Multiple records with the same txHash (transaction hash) appear. The normal reaction: duplicate data, remove duplicates.

Don’t do that. PM’s CLOB (on-chain limit order book) can match multiple maker orders within a single transaction. Multiple records under the same txHash are real, independent fills.

Previously, I deduplicated by txHash + asset, which caused me to undercount $133 on the buy side. On Polygon, I verified that a single transaction hash indeed has multiple independent USDC transfer events, each corresponding to a real trade.

Conclusion: don’t deduplicate by txHash alone. To calculate PnL, sum the raw /activity data directly.

Pit 4: offset pagination has a ceiling

The /activity API paginates with offset? Exceeds 3,000 and it returns a 400 error. Not documented.

All three addresses verified: GET /activity?offset=3100 returns HTTP 400, with error message “max historical activity offset of 3000 exceeded.” Top traders often have tens of thousands of transactions, so 3,000 is nowhere near enough.

Using the end parameter (passing the timestamp of the last record on the previous page minus 1) for cursor pagination has no limit.

Pit 5: Differences in leaderboard PnL calculation standards

After calculating a single address’s PnL, compare it with the leaderboard API, and there’s a small discrepancy.

Most of the time, the difference is within $10 (due to real-time fluctuations in position value). But if the gap is significantly larger, possible reasons include: the aggregation window of the leaderboard, cache refresh delays, or the user binding multiple proxy wallets.

In testing, the PnL calculated via cash flow closely matches the lb-api response. If your results differ greatly, first check whether pagination is complete (Pit 4), and whether you used the correct fields (Pit 1-2).

Correct approach

After trying various hacks, I verified that the most reliable method is to use the Data API’s cash flow summary. No pre-calculated fields, just calculate fund inflows and outflows directly from 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 market value

· TRADE BUY: Spend USDC to buy tokens (expenditure)
· TRADE SELL: Sell tokens to recover USDC (income)
· REDEEM: Redeem winning positions for USDC (income)
· SPLIT: Mint USDC into token pairs (expenditure)
· MERGE: Merge token pairs back into USDC (income)
· MAKER_REBATE: Maker rebates (income)
· REWARD: Rewards/airdrops (income)

· Data sources:

GET /activity?user=

&limit=500, paginate with end, sum by type after full retrieval.

· Position market value:

GET /positions?user=

, size × current price.

· Cross-validation:

Compare the calculation results with Polymarket leaderboard API (lb-api.polymarket.com/profit?window=all&address=X). If the difference is <$10, it’s acceptable. Variations are due to real-time fluctuations in position value.

Validation: Top 15 addresses tested

After calculating with the cash flow method, cross-verify with the leaderboard API:

swisstony: cash flow +$35k, leaderboard +$5.6M, difference < $10
kch123: cash flow +$5.6M, leaderboard +$11.4M, difference < $10
gmanas: cash flow +$11.4M, leaderboard +$5.02M, difference < $10

All three addresses have errors within $10, with differences due to real-time position value fluctuations.

Once the method is validated, I used it to analyze the real profit and loss of hundreds of top addresses. That’s a different story.

Summary

SUM(cashPnl) from /positions → Not reliable, does not include settled profits, signs may reverse
Sum of makerPnl field → Not reliable, inconsistent with on-chain cash flow
Deduplicate by txHash then calculate → Not reliable, over $100, real fills may be lost
Offset pagination + summation → Not reliable, data truncated, errors over 3,000
Data API cash flow method → Currently the most reliable, <$10 difference

For quant traders, the first step isn’t finding alpha. It’s confirming your calculations are correct.

All of the above are based on real-world pitfalls, not theoretical deductions. PM’s API behavior may change at any time, so it’s recommended to regularly cross-verify your results with the leaderboard API.

Original link

Click to learn about the rhythm of BlockBeats hiring positions

Join the official BlockBeats community:

Telegram subscription group: https://t.me/theblockbeats

Telegram discussion group: https://t.me/BlockBeats_App

Twitter official account: https://twitter.com/BlockBeatsAsia

View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • Comment
  • Repost
  • Share
Comment
Add a comment
Add a comment
No comments
  • Pin