Realized PnL
The moment a wallet sells, Conyr computes realized PnL with FIFO cost-basis accounting and emits a record — in USD and SOL in under 20ms. One record is produced per exit, so a position sold across several partial exits (a DCA-out) yields several records, each carrying the running cumulative PnL for the whole position.
The PnL record
Identity
| Field | Type | Description |
|---|---|---|
wallet_address | string | The trader |
token_mint | string | Token sold |
entry_signature | string | Buy tx that opened the position (the position key) |
exit_signature | string | Sell tx for this exit |
entry_timestamp / exit_timestamp | number | Entry/exit time, unix ms |
entry_slot / exit_slot | number | Entry/exit slot |
hold_time_seconds | number | Time held |
Exit shape
| Field | Type | Description |
|---|---|---|
exit_number | number | Which exit on this position (1st, 2nd, …) |
exit_type | string | FULL or PARTIAL |
position_type | string | FULL_POSITION · DCA_EXIT · ARBITRAGE |
percentage_sold | number | % of the original position sold in this exit |
token_amount | string | Tokens sold in this exit |
remaining_token_amount | string | Tokens left after this exit |
Pricing & PnL
| Field | Type | Description |
|---|---|---|
price_per_token_entry / price_per_token_exit | number | Per-token USD price at entry / exit |
entry_sol_price / exit_sol_price | number | SOL/USD at entry / exit |
realized_pnl_usd / realized_pnl_sol | number | Realized PnL for this exit |
percentage_gain | number | Return on the sold portion, % |
total_position_realized_pnl_usd / _sol | number | Cumulative realized PnL across the whole position |
Fees & attribution
| Field | Type | Description |
|---|---|---|
entry_network_fees_usd | number | This exit’s pro-rata share of the entry fee |
exit_network_fees_usd | number | Network fee for this exit |
entry_dex / exit_dex | string | Venue used to enter / exit |
trade_flag | string | null | Bot/terminal attribution (bot, bloom_bot, axiom, bullx, photon) |
Fees are allocated correctly across partial exits: the entry fee is counted once and split pro-rata across each exit, plus that exit’s own network fee. realized_pnl_usd is net of this allocation.
REST — historical PnL
L2 GET /v1/wallet/{address}/pnl
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max records (max 200) |
offset | integer | 0 | Pagination offset |
token | string | — | Filter to a single mint |
from / to | integer | — | Time range, unix ms |
curl -H "Authorization: Bearer $API_KEY" \
"https://api.conyr.ai/v1/wallet/7xKXtg.../pnl?limit=20&token=EPjFWd..."{
"trades": [
{
"wallet_address": "7xKXtg...",
"token_mint": "EPjFWd...",
"entry_signature": "5vGk...", "exit_signature": "3mPq...",
"entry_timestamp": 1709651400000, "exit_timestamp": 1709655900000,
"hold_time_seconds": 4500,
"price_per_token_entry": 0.00234, "price_per_token_exit": 0.00312,
"realized_pnl_usd": 78.50, "realized_pnl_sol": 0.52,
"percentage_gain": 33.33,
"position_type": "FULL_POSITION", "exit_type": "FULL",
"entry_dex": "Raydium", "exit_dex": "Raydium"
}
],
"limit": 20,
"offset": 0
}Stream — live realized PnL
L2 Channel wallet:{address}:pnl
Fires on every sell, carrying the full ~40-field PnL event (all fields above plus cumulative position state, slots, and fee breakdown). Pair it with Positions to keep a live book.
ws.send(JSON.stringify({ op: "subscribe", channels: ["wallet:7xKXtg...:pnl"] }));This is a per-exit win/loss feed. A wallet that scales out of one good position over five sells produces five winning records — which inflates a naive win rate. For a position-correct skill read that corrects exactly this, see Wallet Quality.