Futures
Access hundreds of perpetual contracts
TradFi
Gold
One platform for global traditional assets
Options
Hot
Trade European-style vanilla options
Unified Account
Maximize your capital efficiency
Demo Trading
Introduction to Futures Trading
Learn the basics of futures trading
Futures Events
Join events to earn rewards
Demo Trading
Use virtual funds to practice risk-free trading
Launch
CandyDrop
Collect candies to earn airdrops
Launchpool
Quick staking, earn potential new tokens
HODLer Airdrop
Hold GT and get massive airdrops for free
Pre-IPOs
Unlock full access to global stock IPOs
Alpha Points
Trade on-chain assets and earn airdrops
Futures Points
Earn futures points and claim airdrop rewards
Promotions
AI
Gate AI
Your all-in-one conversational AI partner
Gate AI Bot
Use Gate AI directly in your social App
GateClaw
Gate Blue Lobster, ready to go
Gate for AI Agent
AI infrastructure, Gate MCP, Skills, and CLI
Gate Skills Hub
10K+ Skills
From office tasks to trading, the all-in-one skill hub makes AI even more useful.
GateRouter
Smartly choose from 40+ AI models, with 0% extra fees
Polymarket PnL Accurate Calculation: Why Your Profit and Loss Might Be Incorrect?
After developing proprietary automated trading on Polymarket for half a year, the biggest pit I’ve hit wasn’t that my strategy failed—it was that I couldn’t even calculate how much I earned correctly.
It’s not because I’m incompetent. It’s because PM’s PnL calculation itself is a minefield. The numbers given by the official API are wrong, and the rankings shown by third-party analytics sites are also wrong. If you write your own script to calculate it? Most likely it’s still wrong.
How crazy is the discrepancy? The #3 address, kch123, calculated a loss of $3.5 million using the wrong method, but the actual profit was $11.4 million. It’s not off by just a few percentage points—your profit and loss signs are flipped.
This article breaks down every pit I encountered. If you trade, build tools, or look at rankings, you’ll run into these issues sooner or later.
Pit 1: cashPnl does not include settled profits
The most intuitive approach: pull the /positions interface and sum the cashPnl (cash profit and loss) fields.
Testing the top 15 addresses on the leaderboard:
swisstony: sum of cashPnl +$35k, actual on the leaderboard +$5.6m, a 158x difference
kch123: sum of cashPnl -$3.52m, actual on the leaderboard +$11.4m, sign reversed
gmanas: sum of cashPnl -$2.64m, actual on the leaderboard +$5.02m, sign reversed
For these three addresses, the profit/loss signs for two of them are directly reversed.
Reason: the cashPnl returned by the /positions interface does not include realized PnL that has been closed/redeemed. When winning positions are automatically redeemed into USDC, that position disappears from the API response. What remains are unsettled positions—which are often dominated by unrealized losses.
You think you’re calculating all profit and loss, but you’re only getting the unsettled portion.
Pit 2: makerPnl field is inconsistent with on-chain cash flows
In the trading data JSONL, there’s a makerPnl (market-making profit and loss) field. It sounds like it’s meant to help you calculate PnL—don’t trust it.
In my observations of market-making data, the number computed by SUM(makerPnl) differs from the on-chain cash flow reconciliation by an order of magnitude. The exact multiple may vary depending on the scenario, but the direction is consistent: the internal calculation logic of makerPnl doesn’t match the actual USDC flow.
No matter how large the deviation is, the conclusion is the same: don’t use this field to calculate PnL.
Pit 3: cannot deduplicate by txHash alone
This is the most counterintuitive one.
The same txHash (transaction hash) appears multiple times. A normal person’s first reaction: duplicate data—deduplicate.
Don’t do that. PM’s CLOB (on-chain limit order book) can match multiple maker orders within a single on-chain transaction. Under the same txHash, multiple records are real independent fills.
Previously, I deduplicated by txHash + asset, which caused the BUY side to be undercounted by $133. On the Polygon chain, I verified that within a single transaction hash there are indeed multiple independent USDC Transfer events, and each one corresponds to a real executed trade.
Conclusion: you can’t deduplicate by txHash alone. To calculate PnL, directly sum the original data from /activity.
Pit 4: offset-based pagination has a ceiling
When paging through the /activity interface using offset (offset)? If you exceed 3000 records, you get an immediate 400 error. It’s not documented.
All three addresses above have been verified: GET /activity?offset=3100 returns HTTP 400, with the error message “max historical activity offset of 3000 exceeded.” Top players often have tens of thousands of transactions—3000 is simply not enough.
Use the end parameter (pass the timestamp of the last record on the previous page minus 1) as the cursor pagination method—there’s no limit.
Pit 5: differences in leaderboard PnL definitions
After you calculate an address’s PnL and then compare it on the leaderboard, you find it’s off by a bit.
In most cases, the difference is within $10 (from real-time fluctuations in position value). But if the difference is clearly larger, possible reasons include: the leaderboard’s aggregation window, cache refresh delays, or users binding multiple proxy wallets.
In my testing, the single-address PnL calculated via the cash flow method matches the lb-api return value very closely. If your result differs by a lot, first check whether pagination is complete (Pit 4) and whether you used the wrong fields (Pit 1-2).
Correct approach
After trying all kinds of wrong ways, the most reliable method I verified is to use the Data API’s cash flow summary. Don’t use any precomputed fields—directly compute the inflows and outflows of funds 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 (outflow)
· TRADE SELL:sell tokens to get USDC back (inflow)
· REDEEM:redeem winning positions into USDC (inflow)
· SPLIT:mint USDC into token pairs (outflow)
· MERGE:merge token pairs back into USDC (inflow)
· MAKER_REBATE:maker rebate (inflow)
· REWARD:rewards/airdrops (inflow)
· Data source:
GET /activity?user=
&limit=500, paginate using end; after fetching everything, sum by type.· Position value:
GET /positions?user=
, size × curPrice.· Cross-validation:
Compare your calculation results with the Polymarket leaderboard API (lb-api.polymarket.com/profit?window=all&address=X). If the difference is <$10, consider it passed. The difference comes from real-time fluctuations in position value.
Validation: leaderboard top 15 tested
After calculating using the cash flow method, cross-validate with the leaderboard API:
swisstony:cash flow +$560.1m, leaderboard +$560.1m, difference < $10
kch123:cash flow +$1139.6m, leaderboard +$1139.6m, difference < $10
gmanas:cash flow +$502.4m, leaderboard +$502.4m, difference < $10
For all three addresses, the error is within $10, and the difference comes from real-time fluctuations in position value.
After getting the method to work, I used it to analyze the real profit and loss of hundreds of top addresses. That’s another story.
Summary
SUM(cashPnl) from /positions → no good; it doesn’t include settled profits, and the signs may be reversed
Summing the makerPnl field → no good; it’s inconsistent with on-chain cash flows
Calculate after deduplicating by txHash → no good; it’s $100+ off and you delete real fills
offset pagination + summation → no good; data is truncated, and it errors out for >3000
Data API cash flow method → currently the most reliable, <$10
The first step in quant trading isn’t finding alpha. It’s first confirming that you calculated correctly.
Everything above comes from real-world pitfalls from hands-on practice, not theoretical reasoning. PM’s API behavior could change at any time, so it’s recommended to regularly cross-verify your calculation results with the leaderboard API.
Click to learn about Rhythm BlockBeats’ job openings
Welcome to join the official Rhythm BlockBeats community:
Telegram subscription group: https://t.me/theblockbeats
Telegram discussion group: https://t.me/BlockBeats_App
Twitter official account: https://twitter.com/BlockBeatsAsia