Package Logo
polymarket-pnl
polymarket-pnl@v1.0.1
Total Downloads
1289
Published
2 hours ago
Network
polygon polygon
Publisher
User Avatar PaulieB14

Readme

Polymarket P&L Substreams


Overview

Comprehensive Substreams package for tracking Polymarket P&L with SQL sink support for persistent state accumulation. Tracks all trading activity from both CTF Exchange and Neg Risk Exchange contracts.

Key Features

Feature Description
Real P&L Tracking Realized & unrealized P&L with cost basis
SQL Sink PostgreSQL/Clickhouse for persistent state
Trader Analytics Volume, win rate, max drawdown
Market Stats Price, volume, trade counts per market
Whale Detection Large trade tracking with trader context

Quick Start

Stream Data (No Database)

# Install CLI
brew install streamingfast/tap/substreams

# Authenticate
substreams auth

# Stream order fills
substreams run https://spkg.io/PaulieB14/polymarket-pnl-v1.0.0.spkg \
  map_order_fills \
  -e polygon.substreams.pinax.network:443 \
  -s 65000000 -t +1000

# Stream user P&L
substreams run https://spkg.io/PaulieB14/polymarket-pnl-v1.0.0.spkg \
  map_user_pnl \
  -e polygon.substreams.pinax.network:443 \
  -s 65000000 -t +1000

Sink to PostgreSQL (Required for P&L)

Important: P&L requires accumulated state. Use the SQL sink for accurate calculations.

# Install sink
brew install streamingfast/tap/substreams-sink-sql

# Create database
createdb polymarket_pnl

# Setup schema
substreams-sink-sql setup \
  "psql://localhost:5432/polymarket_pnl?sslmode=disable" \
  https://spkg.io/PaulieB14/polymarket-pnl-v1.0.0.spkg

# Run sink (start from beginning for full history)
substreams-sink-sql run \
  "psql://localhost:5432/polymarket_pnl?sslmode=disable" \
  https://spkg.io/PaulieB14/polymarket-pnl-v1.0.0.spkg \
  -e polygon.substreams.pinax.network:443

Query Your Data

-- Top traders by P&L
SELECT * FROM leaderboard_pnl LIMIT 20;

-- Whale trades with trader stats
SELECT * FROM whale_trades;

-- User positions
SELECT * FROM user_positions
WHERE user_address = '0x...' AND quantity > 0;

-- Daily stats
SELECT date, total_volume, total_trades
FROM daily_stats ORDER BY date DESC;

Architecture

                    Polygon Blockchain
                           │
                           ▼
              ┌─────────────────────────┐
              │     Firehose Blocks     │
              └─────────────────────────┘
                           │
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ map_order_fills │ │map_token_transf │ │map_usdc_transf  │
│  (CTF + NegRisk)│ │    (ERC1155)    │ │    (USDC)       │
└─────────────────┘ └─────────────────┘ └─────────────────┘
         │                 │                   │
         └─────────────────┼───────────────────┘
                           ▼
              ┌─────────────────────────┐
              │    STORES (State)       │
              │  • user_positions       │
              │  • user_cost_basis      │
              │  • user_realized_pnl    │
              │  • latest_prices        │
              └─────────────────────────┘
                           │
                           ▼
              ┌─────────────────────────┐
              │      map_user_pnl       │
              │   (Computed Analytics)  │
              └─────────────────────────┘
                           │
                           ▼
              ┌─────────────────────────┐
              │         db_out          │
              │      (SQL Sink)         │
              └─────────────────────────┘
                           │
                           ▼
              ┌─────────────────────────┐
              │       PostgreSQL        │
              └─────────────────────────┘

Modules

Layer 1: Event Extraction

Module Description
map_order_fills OrderFilled events from CTF & NegRisk exchanges
map_token_transfers ERC1155 TransferSingle events
map_usdc_transfers USDC transfer events

Layer 2: State Stores

Store Key Description
store_user_positions {user}:{token} Position quantities
store_user_cost_basis {user}:{token} Total cost basis
store_user_realized_pnl {user} Realized P&L
store_user_volume {user} Trading volume
store_user_trade_count {user} Trade count
store_market_volume {token} Market volume
store_latest_prices {token} Latest prices

Layer 3: Analytics

Module Description
map_user_pnl Real-time P&L calculations
map_market_stats Market-level statistics

Layer 4: Sink

Module Description
db_out Database changes for SQL sink

Database Schema

Tables

Table Description
trades All order fills with price, amount, side
user_pnl Aggregated P&L per user
user_positions Current positions with cost basis
markets Market statistics
daily_stats Daily aggregates

Views

View Description
leaderboard_pnl Top 1000 by P&L
leaderboard_volume Top 1000 by volume
whale_trades Trades >$10K

Contract Addresses

Contract Address Start Block
CTF Exchange 0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e 33,605,403
NegRisk Exchange 0xC5d563A36AE78145C45a50134d48A1215220f80a 50,505,492
Conditional Tokens 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045 4,023,686
USDC 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 4,023,686

Build from Source

# Clone
git clone https://github.com/PaulieB14/Polymarket-P-L-Substreams
cd Polymarket-P-L-Substreams

# Build
substreams build

# Test
substreams run substreams.yaml map_order_fills \
  -e polygon.substreams.pinax.network:443 \
  -s 65000000 -t +100

# Package & publish
substreams pack substreams.yaml -o polymarket-pnl-v1.0.0.spkg
substreams publish polymarket-pnl-v1.0.0.spkg

Why SQL Sink?

P&L calculation requires state accumulation over time:

Without Sink With SQL Sink
No history Full history persisted
P&L = $0 Accurate P&L
Stateless Tracks cost basis
Demo only Production ready

Related


License

MIT

Documentation

Modules

Maps icon
Maps

map
map_order_fills

6f05a26c10972d4866098bcda48c7fdbb58126e4
map map_order_fills (
blocksf.ethereum.type.v2.Block
)  -> pnl.v1.OrderFills

Extracts OrderFilled events from both CTF Exchange and NegRisk Exchange. This is the primary source of trading activity.

substreams gui polymarket-pnl@v1.0.1 map_order_fills

map
map_token_transfers

bb8397fbef9a0ab151a1c34faa303387c8cbd217
map map_token_transfers (
)  -> pnl.v1.TokenTransfers

Extracts ERC1155 TransferSingle events for position tracking.

substreams gui polymarket-pnl@v1.0.1 map_token_transfers

map
map_usdc_transfers

759f1ceda4ba2ce5799dd21d7d62a28a0e66b651
map map_usdc_transfers (
)  -> pnl.v1.UsdcTransfers

Extracts USDC (ERC20) transfer events for collateral tracking.

substreams gui polymarket-pnl@v1.0.1 map_usdc_transfers

map
map_user_pnl

f82f823fa8896574e26aaf56b7c68025f3ef8598

Computes real-time P&L for users based on their positions and trades. Outputs user P&L updates when positions change.

substreams gui polymarket-pnl@v1.0.1 map_user_pnl

map
map_market_stats

2adb5ccb2772251a774c61621b7e83fba907e312
map map_market_stats (
store_market_volumeDELTAS<add,bigint>
)  -> pnl.v1.MarketStats

Computes market-level statistics (volume, trades, prices).

substreams gui polymarket-pnl@v1.0.1 map_market_stats

map
db_out

2bb4b1ea99db5e20df2791a4b448e5a70eb69ff1
Default param : min_trade_size=1000000

Outputs database changes for SQL sink (PostgreSQL/Clickhouse). Creates/updates tables: trades, user_pnl, user_positions, markets

substreams gui polymarket-pnl@v1.0.1 db_out

map
ethcommon:all_events

963652a247fd23d0823dde62d21ae54c783b6073
map ethcommon:all_events (
)  -> sf.substreams.ethereum.v1.Events

all_events gives you all the events in a block (from successful transactions), with basic block hash/number/timestamp and transaction hash

substreams gui polymarket-pnl@v1.0.1 ethcommon:all_events
Stores icon
Stores

store
store_user_positions

06dfab7e456c4a3d3a3d929e29e5d7a1718c05a7
store <add,bigint> store_user_positions (
)

Accumulates user positions per token. Tracks quantity held. Key: {user_address}:{token_id}

substreams gui polymarket-pnl@v1.0.1 store_user_positions

store
store_user_cost_basis

caa8df954fe42fcae9ddbbded92b5f8e051d030d
store <add,bigint> store_user_cost_basis (
)

Tracks total cost basis per user per token for average price calculation. Key: {user_address}:{token_id}

substreams gui polymarket-pnl@v1.0.1 store_user_cost_basis

store
store_user_realized_pnl

eb0adc854c4e5b2cc643128cbdc71c1eb0fc7466
store <add,bigint> store_user_realized_pnl (
)

Accumulates realized P&L when users sell positions. Key: {user_address}

substreams gui polymarket-pnl@v1.0.1 store_user_realized_pnl

store
store_user_volume

5752e3f4072c318bd9a09bfb58b0684cbe847ef8
store <add,bigint> store_user_volume (
)

Tracks total trading volume per user. Key: {user_address}

substreams gui polymarket-pnl@v1.0.1 store_user_volume

store
store_user_trade_count

7a3b626a2cfa2a84505ffc0909a77343206c53d8
store <add,int64> store_user_trade_count (
)

Tracks number of trades per user. Key: {user_address}

substreams gui polymarket-pnl@v1.0.1 store_user_trade_count

store
store_market_volume

77dbe92f2ab1cf34cb004d9d0b8a200c6abe24b8
store <add,bigint> store_market_volume (
)

Tracks total volume per market (token_id). Key: {token_id}

substreams gui polymarket-pnl@v1.0.1 store_market_volume

store
store_latest_prices

6a5138a86481e48beb6a290cdbdc1dcd25c2b08e
store <set,pnl.v1.TokenPrice> store_latest_prices (
)

Stores latest price per token for unrealized P&L calculation. Key: {token_id}

substreams gui polymarket-pnl@v1.0.1 store_latest_prices
Block Indexes icon
Block Indexes

blockIndex
ethcommon:index_events

87255243f80f5d4755cd826ec57bf70696a4d7b6

index_events sets the following keys on the block:

  • Event signatures evt_sig:0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef (signature in hex, prefixed by 0x)
  • Event address evt_addr:0x0123456789abcdef0123456789abcdef01234567 (address in hex, prefixed by 0x)
substreams gui polymarket-pnl@v1.0.1 ethcommon:index_events
Protobuf

Protobuf Docs Explorer

sf.ethereum.type.v2
sf.ethereum.substreams.v1
pnl.v1