原文標題:《Polymarket PnL 精確計算:為什麼你算的盈虧可能全是錯的》
原文作者:Leo,加密分析師
我在 Polymarket 自研自動化交易半年,踩過的最大坑不是策略失靈,是連自己賺了多少錢都算不對。
不是我菜。是 PM 的 PnL 計算本身就是雷區。官方 API 給你的數字是錯的,第三方分析網站展示的排名也是錯的。你自己寫腳本算?大概率還是錯的。
偏差有多離譜?排行榜第 3 名 kch123,用錯誤方法算出來虧 $350 萬,實際盈利 $1140 萬。不是差幾個百分點——是盈虧符號都反了。
這篇把我踩過的每個坑拆開講。做交易的、寫工具的、看排行榜的,遲早會遇到。
最直覺的做法:拉 /positions 介面,求和 cashPnl(現金盈虧)字段。
拿排行榜前 15 的三個地址實測:
swisstony:cashPnl 求和 +$3.5 萬,排行榜實際 +$560 萬,差 158 倍
kch123:cashPnl 求和 -$352 萬,排行榜實際 +$1140 萬,符號反轉
gmanas:cashPnl 求和 -$264 萬,排行榜實際 +$502 萬,符號反轉
三個地址,兩個盈虧符號直接反了。
原因:/positions 介面返回的 cashPnl 不包含已 closed/redeemed 的 realized PnL。贏了的倉位被自動贖回成 USDC 後,這個 position 就從 API 響應裡消失了。留下來的是未結算的持倉——往往以浮虧為主。
Bạn nghĩ rằng mình đã tính toán được toàn bộ Lãi/Lỗ, nhưng thực tế chỉ nhận được phần chưa giải quyết.
Trong dữ liệu giao dịch JSONL có một trường makerPnl (Lãi/Lỗ làm thị trường), theo tên có vẻ như là được sử dụng để tính toán PnL của bạn. Nhưng đừng tin vào đó.
Tôi đã quan sát thấy trong dữ liệu làm thị trường rằng tổng của makerPnl tính toán lại số không khớp với kết quả hạch toán luồng tiền trên chuỗi một cách đáng kể. Tuy nhiên, vài lần, con số khác biệt có thể thay đổi tuỳ theo tình huống cụ thể, nhưng hướng đi là như nhau: logic tính toán nội bộ của makerPnl không khớp với dòng tiền USDC thực tế.
Dù sai số lớn nhỏ ra sao, kết luận vẫn là: Đừng sử dụng trường này để tính toán PnL.
Điều này ngược với sự trực giác.
Có nhiều bản ghi của cùng một txHash (băm giao dịch), phản ứng bình thường của đa số: dữ liệu trùng lặp, hãy loại bỏ.
Không thể thực hiện như vậy. CLOB của PM (Cuốn Sổ Đặt Lệnh Trên Chuỗi) có thể khớp nhiều đơn đặt lệnh làm thị trường trong một giao dịch trên chuỗi, nhiều bản ghi dưới cùng txHash đó là các fill thực sự độc lập.
Trước đây, tôi đã loại bỏ theo txHash + tài sản, mặt mua thiếu sót $133. Trên chuỗi Polygon, tôi đã xác minh rằng, một băm giao dịch thực sự có nhiều sự kiện Chuyển Tiền USDC độc lập, mỗi sự kiện tương ứng với một giao dịch thực sự.
Kết luận: Không thể phân biệt theo txHash một mình. Để tính toán PnL, hãy tổng hợp trực tiếp dữ liệu gốc từ /activity.
API /activity có tùy chọn phân trang, sử dụng offset (khoảng lệch)? Quá 3000 bản ghi sẽ trả về lỗi 400 trực tiếp. Điều này không được đề cập trong tài liệu.
Tất cả ba URL đã được xác minh: GET /activity?offset=3100 trả về HTTP 400, thông báo lỗi vượt quá giới hạn lịch sử tối đa của 3000 bản ghi. Các nhà lãnh đạo thường có hàng ngàn giao dịch, 3000 bản ghi không đủ cho họ.
Sử dụng tham số cuối (thời gian đoạn trước đó của trang - 1) để phân trang bằng con trỏ, không có giới hạn.
Sau khi tính toán PnL của một địa chỉ, so sánh với bảng xếp hạng, bạn thấy chênh lệ một chút.
Trong hầu hết các trường hợp, chênh lệ thường dưới $10 (do biến động giá trị vốn trữ của tài sản). Tuy nhiên, nếu chênh lệ lớn hơn đáng kể, nguyên nhân có thể bao gồm: cửa sổ tổng hợp của bảng xếp hạng, độ trễ khi làm mới bộ nhớ cache, hoặc người dùng đã liên kết nhiều ví proxy.
Trong quá trình thử nghiệm, PnL của một địa chỉ đơn theo phương pháp dòng tiền rất tương đồng với giá trị trả về từ lb-api. Nếu kết quả của bạn có chênh lệ lớn, hãy kiểm tra trước xem phân trang đã hoàn tất chưa (lỗ hổng 4), xem có sử dụng trường không đúng hay không (lỗ hổng 1-2).
Sau khi thử nghiệm nhiều phương pháp, tôi xác minh rằng phương pháp zuỳ nhất là Tổng hợp Dòng Tiền Data API. Không sử dụng bất kỳ trường đã tính toán trước nào, tính toán trực tiếp từ giao dịch ban đầu để dò tài sản vào và ra.
Công thức:
PnL = TỔNG(GIAO DỊCH nơi side=BÁN) + TỔNG(RÚT) + TỔNG(GỘP) + TỔNG(MAKER_REBATE) + TỔNG(THƯỞNG) - TỔNG(GIAO DỊCH nơi side=MUA) - TỔNG(CHIA) + Giá trị vốn trữ
· GIAO DỊCH MUA: Chi USDC để mua mã thông báo (chi phí)
· GIAO DỊCH BÁN: Bán mã thông báo và nhận lại USDC (doanh thu)
· RÚT: Rút USDC từ vị trí đã thắng (doanh thu)
· CHIA: Chia USDC để tạo cặp mã thông báo (chi phí)
· GỘP: Ghép cặp mã thông báo trở lại USDC (doanh thu)
· MAKER_REBATE: Hoa hồng Maker (doanh thu)
· THƯỞNG: Phần thưởng/Airdrop (doanh thu)
· Nguồn dữ liệu:
GET /activity?user=<địa chỉ>&limit=500, cuối cùng, sau đó tổng hợp theo loại dữ liệu.
· Giá trị vốn giữ hãng:
GET /positions?user=<địa chỉ>, size × giá hiện tại.
· Xác minh chéo:
So sánh kết quả tính toán với API bảng xếp hạng của Polymarket (lb-api.polymarket.com/profit?window=all&address=X), sai số <$10 được coi là đúng. Sai lệch đến từ sự biến động thời gian thực của giá trị vốn giữ hãng.
Sau khi áp dụng phương pháp dòng tiền, tiến hành xác minh chéo với API bảng xếp hạng:
swisstony: Phương pháp dòng tiền +$560.1 triệu, bảng xếp hạng +$560.1 triệu, sai số < $10
kch123: Phương pháp dòng tiền +$1139.6 triệu, bảng xếp hạng +$1139.6 triệu, sai số < $10
gmanas: Phương pháp dòng tiền +$502.4 triệu, bảng xếp hạng +$502.4 triệu, sai số < $10
Cả ba địa chỉ đều có sai số dưới $10, chênh lệch đến từ sự biến động thời gian thực của giá trị vốn giữ hãng.
Sau khi phương pháp chạy thành công, tôi đã sử dụng nó để phân tích lợi nhuận thực tế của hàng trăm địa chỉ hàng đầu. Điều đó là một câu chuyện khác.
Tổng của (lãi ròng tiền mặt) từ /positions → Không được, không bao gồm lợi nhuận đã giải quyết, dấu có thể bị đảo ngược
Tổng của trường makerPnl → Không được, không khớp với dòng tiền trên chuỗi
Tính toán sau khi loại bỏ trùng lặp theo txHash → Không được, $100+, xóa bản ghi fill thực tế
offset Phân Trang + Tổng → Không thể, dữ liệu bị cắt, Báo lỗi >3000
Data API Luồng Tiền → Hiện tại là phương pháp đáng tin cậy nhất, <$10
Bước đầu tiên trong việc thực hiện định lượng không phải là tìm alpha. Đó là xác nhận bạn đã tính đúng hay chưa.
Tất cả những điều trên đều đến từ việc thực tế gặp rắc rối, không phải là lý thuyết suy luận. API của PM có thể thay đổi hành vi bất cứ lúc nào, đề xuất sử dụng API bảng xếp hạng định kỳ để xác minh kết quả tính toán của bạn.
Liên kết Gốc
Chào mừng bạn tham gia cộng đồng chính thức của BlockBeats:
Nhóm Telegram đăng ký: https://t.me/theblockbeats
Nhóm Telegram thảo luận: https://t.me/BlockBeats_App
Tài khoản Twitter chính thức: https://twitter.com/BlockBeatsAsia