Skip to content

Latest commit

 

History

History
323 lines (250 loc) · 12.2 KB

File metadata and controls

323 lines (250 loc) · 12.2 KB

Data Type Reference

This document defines all JSON data structures used in both Tier 1 (WASM) and Tier 2 (process) strategies. The schemas are identical across tiers -- the only difference is the transport mechanism (linear memory vs. stdin/stdout).

Manifest

The manifest declares a strategy's identity, version, and data requirements. For WASM strategies, it is returned by springbot_manifest(). For process strategies, it is sent as a response to the {"type": "manifest"} message.

{
  "id": "bollinger-bands",
  "name": "Bollinger Bands",
  "version": "1.2.0",
  "tier": "wasm",
  "author": "springbot",
  "description": "Mean-reversion strategy using Bollinger Bands",
  "requires": {
    "candles": { "timeframe": "1h", "lookback": 20 },
    "ticker": true
  }
}
Field Type Required Description
id string Yes Unique slug identifier. Used as the strategy's key throughout the system. Examples: "bollinger-bands", "ob-imbalance".
name string Yes Human-readable display name. Examples: "Bollinger Bands", "Order Book Imbalance".
version string Yes Semver version string. Examples: "1.0.0", "2.1.3".
tier string No "wasm" or "process". Defaults to "wasm" if omitted. For process strategies, the engine forces this to "process" regardless of what the strategy reports.
author string No Strategy author name.
description string No Human-readable description.
requires object Yes Data requirements (see Requires below). Determines what market data the engine delivers on each tick.

Requires

The requires object declares what market data the strategy needs. The engine uses this to:

  1. Subscribe to the correct data feeds (WebSocket channels, REST pollers)
  2. Slice the market data snapshot to include only the requested fields
  3. Compute the union of requirements when multiple strategies run on the same bot

Only the fields you declare are delivered to your strategy on each tick. Unrequested fields are omitted entirely from the EvaluateInput JSON.

{
  "candles": { "timeframe": "1h", "lookback": 20 },
  "ticker": true,
  "order_book": { "depth": 10 },
  "trades": { "count": 50 },
  "funding_rate": true,
  "open_interest": true,
  "portfolio": true
}
Field Type Description
candles object OHLCV candlestick data. See CandleRequirement.
ticker bool Real-time price ticker (best bid, best ask, last price, 24h volume/change).
order_book object Current order book snapshot. See OrderBookRequirement.
trades object Recent executed trades from the exchange. See TradeRequirement.
funding_rate bool Current and predicted funding rate (perpetual futures only).
open_interest bool Current open interest and change (perpetual futures only).
portfolio bool The bot's current base and quote balances plus open orders.

All fields are optional. A strategy must declare at least one requirement.

CandleRequirement

{ "timeframe": "1h", "lookback": 20 }
Field Type Required Description
timeframe string Yes Candle interval. Valid values: "1m", "5m", "15m", "1h", "4h", "1d".
lookback int Yes Number of candles needed. Must be greater than 0. The engine maintains a ring buffer of this size and delivers up to lookback candles on each tick. On early ticks, fewer candles may be available.

OrderBookRequirement

{ "depth": 10 }
Field Type Required Description
depth int Yes Number of price levels on each side (bids and asks). Must be greater than 0. The engine truncates the order book to this depth.

TradeRequirement

{ "count": 50 }
Field Type Required Description
count int Yes Number of recent trades to include. Must be greater than 0. The engine maintains a ring buffer of recent trades and delivers up to count trades on each tick.

EvaluateInput

The EvaluateInput is the complete data payload delivered to a strategy on each tick. It contains only the fields the strategy declared in its manifest requires -- all other fields are omitted from the JSON (not null, not empty arrays, fully absent).

Full Schema

{
  "candles": [
    {
      "time": 1714435200,
      "open": 62150.00,
      "high": 62480.50,
      "low": 62020.00,
      "close": 62350.25,
      "volume": 1842.5
    }
  ],
  "ticker": {
    "best_bid": 62340.00,
    "best_ask": 62355.50,
    "last_price": 62350.25,
    "volume_24h": 45230.8,
    "change_24h": 1.25
  },
  "order_book": {
    "bids": [
      { "price": 62340.00, "size": 1.5 },
      { "price": 62335.00, "size": 3.2 }
    ],
    "asks": [
      { "price": 62355.50, "size": 0.8 },
      { "price": 62360.00, "size": 2.1 }
    ]
  },
  "trades": [
    {
      "time": 1714438800,
      "price": 62350.25,
      "size": 0.15,
      "side": "buy"
    }
  ],
  "funding_rate": {
    "current": 0.0001,
    "predicted": 0.00012,
    "next_funding": 1714449600
  },
  "open_interest": {
    "value": 28500000000.0,
    "change": 2.5
  },
  "portfolio": {
    "base_balance": 0.5,
    "quote_balance": 10000.00,
    "open_orders": [
      {
        "id": "ord-abc123",
        "side": "buy",
        "price": 62100.00,
        "size": 0.1
      }
    ]
  }
}

Field Reference

candles

Array of OHLCV candlestick objects, ordered chronologically (oldest first, most recent last). Present only if requires.candles is declared.

Field Type Description
time int Unix timestamp in seconds (UTC). Start time of the candle.
open float Opening price.
high float Highest price during the interval.
low float Lowest price during the interval.
close float Closing price.
volume float Trading volume during the interval (in base asset units).

Note: On early ticks after a bot starts, the array may contain fewer candles than the declared lookback. Always check the array length before accessing elements.

ticker

Real-time price information. Present only if requires.ticker is true.

Field Type Description
best_bid float Highest current bid price.
best_ask float Lowest current ask price.
last_price float Last traded price.
volume_24h float Total volume over the last 24 hours (in base asset units).
change_24h float Price change over the last 24 hours as a percentage.

order_book

Current state of the order book, truncated to the requested depth. Present only if requires.order_book is declared.

Field Type Description
bids array Bid price levels, sorted best first (highest bid at index 0).
asks array Ask price levels, sorted best first (lowest ask at index 0).

Each price level:

Field Type Description
price float Price at this level.
size float Total size at this level (in base asset units).

trades

Array of recent executed trades from the exchange, ordered chronologically (oldest first). Present only if requires.trades is declared.

Field Type Description
time int Unix timestamp in seconds (UTC).
price float Execution price.
size float Trade size (in base asset units).
side string "buy" or "sell" (lowercase).

funding_rate

Current and predicted funding rate for perpetual futures contracts. Present only if requires.funding_rate is true. Not all exchanges or trading pairs support this.

Field Type Description
current float Current funding rate (e.g., 0.0001 = 0.01%).
predicted float Predicted next funding rate.
next_funding int Unix timestamp in seconds of the next funding event.

open_interest

Current open interest for perpetual futures. Present only if requires.open_interest is true. Not all exchanges or trading pairs support this.

Field Type Description
value float Total open interest (in quote currency).
change float Change in open interest as a percentage.

portfolio

The bot's current position and balances. Present only if requires.portfolio is true. This is per-bot data, not account-wide.

Field Type Description
quote_balance float Available quote currency balance (e.g., USD).
base_balance float Available base asset balance (e.g., BTC).
open_orders array List of currently open orders for this bot.

Each open order:

Field Type Description
id string Exchange order ID.
side string "buy" or "sell" (lowercase).
price float Order price.
size float Order size (in base asset units).

Signal

The signal is the output of a strategy evaluation. It tells the engine what action the strategy recommends and how confident it is.

{
  "direction": "BUY",
  "confidence": 0.85
}
Field Type Required Description
direction string Yes Trading action: "BUY", "SELL", or "HOLD". Case-sensitive.
confidence float Yes Confidence level from 0.0 to 1.0 (inclusive).

Direction Values

Direction Meaning
"BUY" The strategy recommends buying the base asset.
"SELL" The strategy recommends selling the base asset.
"HOLD" The strategy recommends no action. The engine will never place a trade on HOLD.

How Confidence Is Used

Confidence is used in two ways by the engine:

1. Weighted signal aggregation

When a bot runs multiple strategies, their signals are combined using weighted aggregation. Each strategy has a configured weight (set when creating a bot config). The aggregation formula is:

score = sum(weight_i * confidence_i * direction_value_i) / sum(weight_i)

Where direction_value maps BUY to +1, SELL to -1, and HOLD to 0.

The resulting score is a normalized value in the range [-1.0, +1.0]:

  • If score > buy_threshold -> the engine places a BUY order
  • If score < -sell_threshold -> the engine places a SELL order
  • Otherwise -> HOLD (no trade)

The thresholds are configured per bot config (typical defaults: buy_threshold = 0.5, sell_threshold = 0.5).

Example: A bot runs two strategies with equal weight (1.0 each):

  • Strategy A: BUY with confidence 0.9
  • Strategy B: SELL with confidence 0.3
  • Score: (1.0 * 0.9 * 1 + 1.0 * 0.3 * -1) / (1.0 + 1.0) = 0.6 / 2.0 = 0.3
  • With a buy threshold of 0.5, this results in HOLD (0.3 < 0.5)

2. Position sizing

After aggregation produces a BUY or SELL action, the absolute value of the aggregate score is used as a confidence factor for position sizing. Higher aggregate confidence results in larger order sizes relative to the bot's available capital.

Validation

A signal is invalid if:

  • direction is not one of "BUY", "SELL", "HOLD" (case-sensitive, uppercase only)
  • confidence is less than 0.0 or greater than 1.0
  • Either field is missing

Invalid signals are rejected by the engine. The supervision layer treats an invalid signal as a strategy failure, logs it, and returns HOLD with confidence 0.0 for that tick.