Package Logo
polymarket-pnl
polymarket-pnl@v1.1.0
Total Downloads
7238
Published
20 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.1.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.1.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.1.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.1.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.1.spkg
substreams publish polymarket-pnl-v1.0.1.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

8add90f5e6f12d9a8ae0124eb07d5a62ebe1052a
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.1.0 map_order_fills

map
map_token_transfers

8c56fd6ef122a4a073d1a6d70c9876254c0921ee
map map_token_transfers (
)  -> pnl.v1.TokenTransfers

Extracts ERC1155 TransferSingle events for position tracking.

substreams gui polymarket-pnl@v1.1.0 map_token_transfers

map
map_usdc_transfers

830eaec8ce31726b23e035509abd63487e7e72cc
map map_usdc_transfers (
)  -> pnl.v1.UsdcTransfers

Extracts USDC (ERC20) transfer events for collateral tracking.

substreams gui polymarket-pnl@v1.1.0 map_usdc_transfers

map
map_user_pnl

17d69b39d0a3c94891e20ecde17d7fc895622138

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

map
map_market_stats

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

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

substreams gui polymarket-pnl@v1.1.0 map_market_stats

map
db_out

005a635174b60c7085cee0d2ef9cfff09862dcd7
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.1.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.1.0 ethcommon:all_events
Stores icon
Stores

store
store_user_positions

c91cf013a894a8bb6db2c415399416201c41d174
store <add,bigint> store_user_positions (
)

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

substreams gui polymarket-pnl@v1.1.0 store_user_positions

store
store_user_cost_basis

312ee686a897385ca168f19a5d93b33cff4dc98d
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.1.0 store_user_cost_basis

store
store_user_realized_pnl

662e484b2a1e85358504417de75c4dd2b5c9d258
store <add,bigint> store_user_realized_pnl (
)

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

substreams gui polymarket-pnl@v1.1.0 store_user_realized_pnl

store
store_user_volume

83adabef1159d7b1618da72608ab069987481314
store <add,bigint> store_user_volume (
)

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

substreams gui polymarket-pnl@v1.1.0 store_user_volume

store
store_user_trade_count

67a24abeddf8041f0612b1e101b9842c9d38af8e
store <add,int64> store_user_trade_count (
)

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

substreams gui polymarket-pnl@v1.1.0 store_user_trade_count

store
store_market_volume

477a7fa9bf1eea3f39df52e5751a2627762f5b2c
store <add,bigint> store_market_volume (
)

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

substreams gui polymarket-pnl@v1.1.0 store_market_volume

store
store_latest_prices

013842ee5729840588130bf205446beed8af2ce1
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.1.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.1.0 ethcommon:index_events
Protobuf

Protobuf Docs Explorer

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