> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clypt.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# TradingSpec

> The unified configuration hierarchy that defines everything about a trading system

## What is TradingSpec?

`TradingSpec` is the **single configuration object** that completely defines a trading system — what data to use, what strategy to run, and how to execute orders. In notebook development, `mode` is always `"backtest"`. Paper and live trading run on the platform after you submit your strategy — the same graph runs identically in all modes.

```python theme={null}
spec = TradingSpec(
    data=TradingDataSpec(...),          # What data to consume
    strategy=TradingStrategySpec(...),   # What strategy to run
    execution=TradingExecutionSpec(...), # How to execute trades
    mode="backtest",                    # backtest | paper | live
)
```

## Hierarchy Overview

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#1e293b', 'primaryTextColor': '#e2e8f0', 'primaryBorderColor': '#94F1E8', 'lineColor': '#5bb8b0', 'clusterBkg': '#0f172a', 'clusterBorder': '#1e3a3a', 'titleColor': '#94F1E8', 'edgeLabelBackground': 'transparent' }}}%%
graph TD
    classDef highlight fill:#134e4a,stroke:#94F1E8,stroke-width:2.5px,color:#94F1E8

    TS["<b>TradingSpec</b>"]
    DS["<b>TradingDataSpec</b><br>symbol_source_map: SymbolSourceMap<br>observations: List[ObservationSpec]<br>start / end: Optional[datetime]<br>storage: local or db"]
    SS["<b>TradingStrategySpec</b><br>graph: StatefulGraph<br>name / version / description<br>output_nodes: Optional[List[str]]"]
    ES["<b>TradingExecutionSpec</b><br>execution_price_source: ohlcv or orderbook<br>max_position_size / max_order_size"]
    AS["<b>AccountSpec</b><br>exchange / market_type / base_currency<br>initial_cash / max_leverage<br>credentials: Optional[VenueCredential]<br>cost_model: Optional[CostModelSpec]"]
    MD["mode: backtest / paper / live"]
    MT["max_ticks: Optional[int]"]
    DB["debug: bool"]

    TS --> DS
    TS --> SS
    TS --> ES
    ES --> AS
    TS --> MD
    TS --> MT
    TS --> DB

    class TS highlight
```

## TradingDataSpec

Defines **what data** the system consumes.

```python theme={null}
from clyptq.apps.trading.spec import TradingDataSpec, OHLCVSpec, SymbolSourceMap

data = TradingDataSpec(
    symbol_source_map=SymbolSourceMap({
        "binance:futures": ["BTC/USDT", "ETH/USDT"],
        "gateio:futures":  ["SOL/USDT"],
    }),
    observations=[
        OHLCVSpec(
            exchange="binance",
            market_type="futures",
            timeframe="1m",
        ),
        OHLCVSpec(
            exchange="gateio",
            market_type="futures",
            timeframe="1m",
        ),
    ],
    start=datetime(2024, 1, 1),
    end=datetime(2024, 12, 31),
)
```

### SymbolSourceMap

Maps exchanges to symbols, creating the axis keys used throughout the system:

```python theme={null}
symbol_map = SymbolSourceMap({
    "binance:futures": ["BTC/USDT", "ETH/USDT"],
    "gateio:futures":  ["SOL/USDT"],
})

# Generates axis_keys:
# "binance:futures:BTC/USDT"
# "binance:futures:ETH/USDT"
# "gateio:futures:SOL/USDT"
```

**Key properties:**

| Property      | Description                                                     |
| ------------- | --------------------------------------------------------------- |
| `axis_keys`   | All unique axis keys (source-prefixed)                          |
| `all_symbols` | Unique raw symbols without source prefix                        |
| `sources`     | All source keys (e.g., `["binance:futures", "gateio:futures"]`) |

**Key methods:**

| Method                  | Description                         |
| ----------------------- | ----------------------------------- |
| `symbols_for(source)`   | Raw symbols for a source            |
| `axis_keys_for(source)` | Axis keys for a source              |
| `venue_for(axis_key)`   | Get execution venue for an axis key |

### OHLCVSpec

Currently the primary data source:

```python theme={null}
OHLCVSpec(
    exchange="binance",               # Exchange ID
    market_type="futures",            # spot, futures, perpetual, linear
    timeframe="1m",                   # 1m, 5m, 15m, 1h, 4h, 1d
)
```

`exchange` and `market_type` can be lists — the driver **expands** them into concrete specs:

```python theme={null}
# This single spec:
OHLCVSpec(
    exchange=["binance", "gateio"],
    market_type=["futures", "spot"],
    timeframe="1m",
)

# Expands to 4 concrete specs:
# binance:futures, binance:spot, gateio:futures, gateio:spot
```

## TradingStrategySpec

Wraps the [StatefulGraph](/engine/stateful-graph) with metadata:

```python theme={null}
from clyptq.apps.trading.spec import TradingStrategySpec

strategy = TradingStrategySpec(
    graph=my_graph,                     # StatefulGraph instance
    name="Momentum Crossover",         # Strategy name
    version="1.0",                     # Version string
    description="SMA crossover ...",   # Description
    output_nodes=["signal", "equity"], # Which nodes to include in results
)
```

| Field          | Type                  | Default     | Description                              |
| -------------- | --------------------- | ----------- | ---------------------------------------- |
| `graph`        | `StatefulGraph`       | Required    | The computation graph                    |
| `name`         | `str`                 | `"unnamed"` | Strategy name                            |
| `version`      | `str`                 | `"1.0"`     | Version identifier                       |
| `description`  | `str`                 | `""`        | Strategy description                     |
| `output_nodes` | `Optional[List[str]]` | `None`      | Nodes to collect in results (None = all) |

## TradingExecutionSpec

Defines **how** trades are executed:

```python theme={null}
from clyptq.apps.trading.spec import TradingExecutionSpec, AccountSpec

execution = TradingExecutionSpec(
    accounts=(
        AccountSpec(
            exchange="binance",
            market_type="futures",
            base_currency="USDT",
            initial_cash=10000.0,
        ),
    ),
    execution_price_source="ohlcv",
    max_position_size=None,
    max_order_size=None,
)
```

| Field                    | Type                       | Default | Description                                             |
| ------------------------ | -------------------------- | ------- | ------------------------------------------------------- |
| `accounts`               | `Tuple[AccountSpec, ...]`  | `()`    | Trading accounts (required)                             |
| `execution_price_source` | `"ohlcv"` \| `"orderbook"` | `None`  | Price source for backtest fills (`"ohlcv"` recommended) |
| `max_position_size`      | `Optional[float]`          | `None`  | Global position size limit                              |
| `max_order_size`         | `Optional[float]`          | `None`  | Global order size limit                                 |
| `min_order_interval_s`   | `float`                    | `0.0`   | Minimum seconds between orders                          |

<Note>
  `mode` is a top-level field on `TradingSpec`, not on `TradingExecutionSpec`. In notebook development, always set `mode="backtest"` directly on `TradingSpec`.
</Note>

### AccountSpec

Each exchange account is defined separately:

```python theme={null}
AccountSpec(
    exchange="binance",           # Required: exchange ID
    market_type="futures",        # Required: spot, futures, perpetual, linear
    base_currency="USDT",         # Required: account currency (uppercase 3-4 letters)
    initial_cash=10000.0,         # For backtest/paper (None for live)
    max_leverage=3.0,             # None = use venue default
    cost_model=CostModelSpec(...),# None = auto-fetch from exchange
    credentials=None,             # Required for live mode
)
```

| Field           | Type                        | Default  | Notes                                                                                               |
| --------------- | --------------------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `exchange`      | `str`                       | Required | `"binance"`, `"gateio"`, `"bybit"`, `"okx"`, `"coinbase"`, `"kraken"`, `"aster"`                    |
| `market_type`   | `str`                       | Required | `"spot"`, `"futures"`, `"perpetual"`, `"linear"`                                                    |
| `base_currency` | `str`                       | Required | `"USDT"`, `"USDC"`, `"USD"` (must be uppercase)                                                     |
| `initial_cash`  | `Optional[float]`           | `None`   | Optional for backtest (defaults to 10000 if unset). Optional for live (acts as capital cap if set). |
| `max_leverage`  | `Optional[float]`           | `None`   | Auto: 1.0 for spot, venue max for futures (fallback: 10.0 for non-spot)                             |
| `cost_model`    | `Optional[CostModelSpec]`   | `None`   | Override fees. None = auto-fetch.                                                                   |
| `credentials`   | `Optional[VenueCredential]` | `None`   | Required for live mode                                                                              |

**`key` property**: Returns `"{exchange}:{market_type}"` (e.g., `"binance:futures"`)

### CostModelSpec

Override trading fees per account:

```python theme={null}
CostModelSpec(
    taker_fee=0.0004,    # 0.04% (default)
    maker_fee=0.0002,    # 0.02% (default)
    slippage_bps=2.0,    # 2 basis points (default)
)
```

If not specified, fees are auto-fetched from the exchange via CCXT.

**Zero-cost backtest:**

```python theme={null}
AccountSpec(
    ...,
    cost_model=CostModelSpec(taker_fee=0.0, maker_fee=0.0, slippage_bps=0.0)
)
```

## Execution Modes

### Backtest

```python theme={null}
spec = TradingSpec(
    ...,
    mode="backtest",
)
```

* Uses historical data from `start` to `end`
* Simulated execution with CostModelSpec fees
* `initial_cash` required per account
* No API credentials needed
* **The only mode used in notebook cells**

### Paper

* Uses live/current data from the exchange
* Simulated execution (no real orders placed)
* `initial_cash` optional (defaults to 10000.0)
* No API credentials needed

<Info>
  Paper trading is managed through the dashboard after strategy submission. It cannot be run from notebook cells.
</Info>

### Live

* Uses live data from exchange APIs
* Real order execution
* **Requires** API credentials
* `initial_cash` is optional — if set, it acts as a capital cap (actual balance must be >= initial\_cash)

<Info>
  Live trading is managed through the dashboard after strategy submission. It cannot be run from notebook cells.
</Info>

## Supported Exchanges

| Exchange | Spot                        | Futures    | Max Leverage | Notes                                                |
| -------- | --------------------------- | ---------- | ------------ | ---------------------------------------------------- |
| Binance  | USDT, FDUSD, USDC, BTC, ETH | USDT, USDC | 125x         | `market_type="futures"`                              |
| Gate.io  | USDT, BTC, ETH              | USDT       | 100x         | `market_type="futures"`                              |
| Bybit    | USDT, USDC                  | USDT, USDC | 100x         | `market_type="linear"` (normalized from `"futures"`) |
| Kraken   | USD, USDT                   | USD        | 50x          | `market_type="perpetual"` (4h funding)               |
| Coinbase | USD, USDC                   | USDC       | 10x          | `market_type="perpetual"` (CFTC)                     |
| OKX      | USDT, USDC                  | USDT, USDC | 125x         | `market_type="swap"` (normalized from `"futures"`)   |
| Aster    | USDT                        | USDT       | 20x          | `market_type="futures"` (DEX)                        |

## Validation

`TradingSpec.validate()` enforces:

1. **Mode** must be explicitly set (`"backtest"`, `"paper"`, or `"live"`)
2. **Strategy.graph** must not be None
3. **Observations** must not be empty
4. **Live mode**: accounts must have credentials, `initial_cash` is optional (capital cap if set)
5. **Backtest mode**: accounts need observation data at system clock resolution

`AccountSpec.__post_init__()` validates:

* `base_currency` is uppercase 3-4 letters
* `exchange:market_type` is a valid combination
* `base_currency` is supported by the exchange/market\_type
* `max_leverage` doesn't exceed venue maximum

`SymbolSourceMap.validate_base_currencies()`:

* Symbol quote currencies must match account base currencies
* Prevents PnL calculation errors (e.g., USD vs USDT mismatch)

## Complete Example

```python theme={null}
from datetime import datetime
from clyptq.system.graph import StatefulGraph, Input
from clyptq.apps.trading.spec import (
    TradingSpec, TradingDataSpec, TradingStrategySpec,
    TradingExecutionSpec, AccountSpec, CostModelSpec,
    OHLCVSpec, SymbolSourceMap,
)

# 1. Build strategy graph
graph = StatefulGraph()
graph.add_node("sma_fast", SMA(input=close, period=10),
    inputs=[Input("FIELD:binance:futures:ohlcv:close", "1m", lookback=10)])
graph.add_node("sma_slow", SMA(input=close, period=50),
    inputs=[Input("FIELD:binance:futures:ohlcv:close", "1m", lookback=50)])
graph.add_node("signal", MomentumAlpha(),
    inputs=[
        Input("sma_fast", "1m", lookback=2),
        Input("sma_slow", "1m", lookback=2),
    ])

# 2. Compose TradingSpec
spec = TradingSpec(
    data=TradingDataSpec(
        symbol_source_map=SymbolSourceMap({
            "binance:futures": ["BTC/USDT", "ETH/USDT"],
        }),
        observations=[
            OHLCVSpec(exchange="binance", market_type="futures", timeframe="1m"),
        ],
        start=datetime(2024, 1, 1),
        end=datetime(2024, 12, 31),
    ),
    strategy=TradingStrategySpec(
        graph=graph,
        name="SMA Crossover",
        version="1.0",
        output_nodes=["signal"],
    ),
    execution=TradingExecutionSpec(
        accounts=(
            AccountSpec(
                exchange="binance",
                market_type="futures",
                base_currency="USDT",
                initial_cash=10000.0,
                max_leverage=3.0,
            ),
        ),
    ),
    mode="backtest",
)

# 3. Validate and run
spec.validate()
driver = TradingDriver.from_spec(spec)
results = driver.run()
```

### Going to Paper or Live

Paper and live trading are not configured from notebook cells. After backtesting your strategy:

1. Submit your strategy via the dashboard
2. The platform validates and re-runs your backtest for independent verification
3. Start a Paper or Live run from the dashboard — the same `StatefulGraph` runs without any code changes

See [Backtest to Live](/tutorials/backtest-to-live) for the full deployment lifecycle.

## Multi-Exchange Example

```python theme={null}
spec = TradingSpec(
    data=TradingDataSpec(
        symbol_source_map=SymbolSourceMap({
            "binance:futures": ["BTC/USDT", "ETH/USDT"],
            "gateio:futures":  ["SOL/USDT", "DOGE/USDT"],
        }),
        observations=[
            OHLCVSpec(exchange="binance", market_type="futures", timeframe="1m"),
            OHLCVSpec(exchange="gateio", market_type="futures", timeframe="1m"),
        ],
    ),
    strategy=TradingStrategySpec(graph=multi_venue_graph),
    execution=TradingExecutionSpec(
        accounts=(
            AccountSpec(
                exchange="binance", market_type="futures",
                base_currency="USDT", initial_cash=10000.0,
            ),
            AccountSpec(
                exchange="gateio", market_type="futures",
                base_currency="USDT", initial_cash=10000.0,
            ),
        ),
    ),
    mode="backtest",
)
```

Each account creates its own STATE namespace (`STATE:binance:futures:*`, `STATE:gateio:futures:*`), enabling venue-specific equity tracking and order execution.

## Common Mistakes

### Mismatched base\_currency

```python theme={null}
# Symbol is BTC/USDT but account uses USD
AccountSpec(exchange="binance", market_type="futures", base_currency="USD")
# → validate_base_currencies() error: USDT ≠ USD
```

### Missing observation for account

```python theme={null}
# Account for gateio but no GateIO observation
data = TradingDataSpec(
    symbol_source_map=SymbolSourceMap({"gateio:futures": ["BTC/USDT"]}),
    observations=[OHLCVSpec(exchange="binance", ...)],  # Missing gateio!
)
# → Validation error
```

### initial\_cash in live mode

```python theme={null}
# initial_cash is optional in live mode — acts as a capital cap
AccountSpec(
    exchange="binance", market_type="futures",
    base_currency="USDT",
    initial_cash=10000.0,  # Optional: caps capital usage to $10,000
    # Actual exchange balance must be >= initial_cash (validated at runtime)
)
```

## Relationship to Other Concepts

* **[StatefulGraph](/engine/stateful-graph)**: `TradingStrategySpec.graph` holds the graph
* **[FIELD Data Principle](/engine/field-state)**: Observations define available FIELD sources
* **[STATE Principle](/engine/field-state)**: AccountSpec defines STATE namespaces
* **[Execution Pipeline](/engine/execution-pipeline)**: TradingExecutionSpec configures the executor
* **[Lookback Buffers](/engine/lookback-buffers)**: Warmup is computed from graph + data specs
