PublicBot
The lean, anonymous, allowlisted projection of a LIVE bot — a DELAYED performance badge. This is the ENTIRE public surface of a shared bot. Unlike the frozen projections it is served from a pre-computed BotPublicSnapshot sidecar (>=15-minute compute cutoff), NEVER the live bot.
Structural safety is the whole surface:
- Money is ALWAYS relative — returnPct / winRatePct / maxDrawdownPct percentages and a unitless profitFactor. There is NO absolute balance/stake/equity/profit.
- status is COARSE (active/paused/stopped) — an unhealthy/error bot reads as "paused"; error_message is never exposed.
- openPositionsBucket is a DELAYED, BUCKETED count (0 / 1-3 / 4+) as of the compute cutoff — never a live count, never per-position detail (no pair, entry/exit, size, or unrealized PnL).
- uptimeBucket is a coarse age band — never an exact created_at/now.
- No ids, no owner PII, no config/secret, no runner/infra, no linked entities.
type PublicBot {
projectionLevel: ShareProjectionLevel!
strategyName: String!
exchangeName: String
status: String!
marketType: String
returnPct: Float
winRatePct: Float
maxDrawdownPct: Float
profitFactor: Float
closedTradeCount: Int!
uptimeBucket: String!
openPositionsBucket: String!
sparkline: [Float!]!
}
Fields
PublicBot.projectionLevel ● ShareProjectionLevel! non-null enum
The publisher's chosen projection level (card = teaser without the sparkline, full = all safe fields).
PublicBot.strategyName ● String! non-null scalar
Human display name (the publisher-authored Strategy.name).
PublicBot.exchangeName ● String scalar
Exchange vendor NAME only (e.g. 'binance') — never keys or account data.