Package Logo
polymarket-pnl
polymarket-pnl@v1.2.0
Total Downloads
75755
Published
12 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.1.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.1.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.1.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.1.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.1.0.spkg
substreams publish polymarket-pnl-v1.1.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

7b767a94c53b2cd5251d7ce9b2b06b8c7a1c44f0
map map_order_fills (
blocksf.ethereum.type.v2.Block
)  -> pnl.v1.OrderFills

Extracts OrderFilled events from CTF Exchange and NegRisk Exchange across both CLOB v1 (legacy) and v2 (deployed 2026-03-31, cutover 2026-04-28). This is the primary source of trading activity.

substreams gui polymarket-pnl@v1.2.0 map_order_fills

map
map_token_transfers

148fbbfdee6384ca041ff9cfc4d3455e713255bf
map map_token_transfers (
)  -> pnl.v1.TokenTransfers

Extracts ERC1155 TransferSingle events for position tracking.

substreams gui polymarket-pnl@v1.2.0 map_token_transfers

map
map_usdc_transfers

57dfe8163a7504001e19a05274649fea98493ea1
map map_usdc_transfers (
)  -> pnl.v1.UsdcTransfers

Extracts USDC (ERC20) transfer events for collateral tracking.

substreams gui polymarket-pnl@v1.2.0 map_usdc_transfers

map
map_user_pnl

c2dd7ddb3b9160a30d957d6ea6feaf1f9ba3e13d

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.2.0 map_user_pnl

map
map_market_stats

9acefc94fb8d89961210c0c9ac9e2ff7cd6893a4
map map_market_stats (
store_market_volumeDELTAS<add,bigint>
)  -> pnl.v1.MarketStats

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

substreams gui polymarket-pnl@v1.2.0 map_market_stats

map
db_out

0a17dc9945c585ecebf6fa19c3d7cf64327208fe
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.2.0 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.2.0 ethcommon:all_events
Stores icon
Stores

store
store_user_positions

66d1de880441fda837ae21a354a6ba5489cdd5d1
store <add,bigint> store_user_positions (
)

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

substreams gui polymarket-pnl@v1.2.0 store_user_positions

store
store_user_cost_basis

dd205513d494ee96bbaa1bdbe0c4ba9f93b8f92b
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.2.0 store_user_cost_basis

store
store_user_realized_pnl

09084d9d9ebf642dd28ea1c1fb7eb9244b18a6a3
store <add,bigint> store_user_realized_pnl (
)

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

substreams gui polymarket-pnl@v1.2.0 store_user_realized_pnl

store
store_user_volume

0e3d28044f78fa6181585066f5eddb0252c8763f
store <add,bigint> store_user_volume (
)

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

substreams gui polymarket-pnl@v1.2.0 store_user_volume

store
store_user_trade_count

b42fc0f528283e12ed51dcac5fd81811caddab83
store <add,int64> store_user_trade_count (
)

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

substreams gui polymarket-pnl@v1.2.0 store_user_trade_count

store
store_market_volume

0a6a213afaa41da463040fc28957c9aa9a253536
store <add,bigint> store_market_volume (
)

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

substreams gui polymarket-pnl@v1.2.0 store_market_volume

store
store_latest_prices

2508a371395dfb249044f78c30dc24fc7702298a
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.2.0 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.2.0 ethcommon:index_events
Protobuf

Protobuf Docs Explorer

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