Skip to main content
The trader namespace exposes a family of read endpoints that return a wallet’s profit and loss in chart-ready shapes: an OHLC candlestick series for an equity curve, a daily calendar for a heatmap, best and worst day/week/month extremes, and drawdown/runup risk metrics. Each endpoint is keyed by the trader’s address and authenticated with X-API-Key. REST responses are wrapped, so the payload lives under .data. These are historical snapshots. For a live view that updates as new fills land, see the realtime companion guide Live trader PnL dashboard.

When to use this

  • Drawing an equity (total PnL) candlestick chart for a single wallet.
  • Rendering a GitHub-style daily PnL heatmap of green and red days.
  • Showing a trader’s best and worst day, week, and month at a glance.
  • Plotting maximum drawdown and runup for a risk panel.
  • Listing the markets where a wallet made or lost the most across the platform.

Equity curve from PnL candles

getTraderPnlCandles returns an OHLC series of the wallet’s PnL over time, suitable for a candlestick or area chart. Pass a resolution (1m, 1h, 4h, 1d, or auto) and a timeframe (1d, 7d, 30d, or lifetime, default lifetime). count_back defaults to 500 and caps at 2500, and fill_gaps carries the last close across empty buckets so the line stays continuous.
import { StructClient } from "@structbuild/sdk";

const client = new StructClient({ apiKey: "sk_live_xxx" });

const { data: bars } = await client.trader.getTraderPnlCandles({
  address: "0xTRADER",
  resolution: "1d",
  timeframe: "lifetime",
  count_back: 500,
  fill_gaps: true,
});
Each element is a PnlCandlestickBar. The total-PnL OHLC fields drive an equity candlestick, and parallel realized and unrealized series let you split the line.
FieldDescription
tBar start time, Unix seconds
o h l cTotal PnL open, high, low, close (nullable on empty buckets)
ro rh rl rcRealized PnL open, high, low, close
uo uh ul ucUnrealized PnL open, high, low, close
po ph pl pcPortfolio value open, high, low, close
ob cb ub pbOpening basis, closing basis, unrealized basis, portfolio basis
nopOpen position count in the bar
For a simple equity line, plot c per bar. For a candlestick, map o/h/l/c straight into the chart and treat null buckets (gaps) as carried-forward closes unless you set fill_gaps.

Daily heatmap from the calendar

getTraderPnlCalendar returns one entry per day, ideal for a contribution-style heatmap. days defaults to 30 and caps at 30.
const { data: calendar } = await client.trader.getTraderPnlCalendar({
  address: "0xTRADER",
  days: 30,
});
Each PnlCandleEntry is { t, pnl }: t is the day in Unix seconds and pnl is that day’s PnL in USD. Color each cell on the sign and magnitude of pnl to get a green and red heatmap.

Best and worst periods

getTraderPnlPeriods returns the wallet’s extreme day, week, and month for both total PnL and portfolio value. Pass a timeframe (1d, 24h, 7d, 30d, or lifetime) to bound the window the extremes are computed over.
const { data: periods } = await client.trader.getTraderPnlPeriods({
  address: "0xTRADER",
  timeframe: "lifetime",
});
The PnlPeriodsResponse carries six extremes objects: total_pnl_day, total_pnl_week, total_pnl_month, portfolio_day, portfolio_week, and portfolio_month. Each is a PnlPeriodExtremes with best and worst, and each of those (when present) is a metric of { from, to, change, change_pct } (from and to are Unix seconds bounding the period, change is the PnL over it). Render total_pnl_day.best and total_pnl_day.worst as the best and worst day, and so on for week and month.

Drawdown and runup

getTraderPnlRisk returns risk metrics for both the total-PnL series and the portfolio series. It takes the same timeframe values as periods.
const { data: risk } = await client.trader.getTraderPnlRisk({
  address: "0xTRADER",
  timeframe: "lifetime",
});
PnlRiskResponse has total_pnl and portfolio, each a PnlRiskMetric (either may be null when there is no history). The metric fields:
FieldDescription
max_drawdownLargest peak-to-trough decline
max_drawdown_pctThe same as a percentage (nullable)
current_drawdownDecline from the most recent peak
current_drawdown_pctThe same as a percentage (nullable)
max_runupLargest trough-to-peak gain
max_runup_pctThe same as a percentage (nullable)
high low latestSeries high, low, and most recent value
Each drawdown and runup field also has a matching *_market object naming the market that drove it, so you can annotate the risk panel.

Best and worst markets

getTopTradesMarkets ranks markets across the platform by PnL rather than scoping to one wallet. It is global, so it takes no address. Pass a timeframe (1d, 7d, 30d, or lifetime), plus limit (default 50, max 200) and offset for paging.
const { data: markets } = await client.trader.getTopTradesMarkets({
  timeframe: "30d",
  limit: 50,
});
Each MarketEntry includes condition_id, title, question, image_url, realized_pnl_usd, total_pnl_usd, total_volume_usd, total_fees, and a trader profile, alongside trade counts and volume breakdowns. Sort or split the rows by total_pnl_usd to surface the best and worst markets.

Follow-on

Last modified on June 13, 2026