Skip to main content

TradePose Client SDK

Python SDK for TradePose quantitative trading platform. Simple, type-safe, production-ready.

What is this?

Official Python client for the TradePose trading platform API. Designed for quantitative traders, algo developers, and trading system architects who need:

  • 🎯 Simple synchronous API - No async/await required, works out of the box
  • 📊 Batch testing - Multi-strategy, multi-period backtesting with background polling
  • 🔒 Type safety - Pydantic models, IDE autocomplete, compile-time validation
  • 🎨 Direct typed authoring - Data, Base opportunity, and Advanced policy are explicit
  • 🔄 Production-ready - Explicit error handling, idempotent submission recovery, Jupyter support
  • 📋 CRUD Resources - Strategy, Portfolio, Account, Binding management via Gateway API

Installation

pip install tradepose-client

Requirements:

  • Python 3.13+
  • Dependencies: httpx, pydantic, polars, PyYAML, nest-asyncio

Local authoring workspace and agent skills

Initialize a local Python workspace and install the SDK-distributed Claude and Codex skills:

tradepose init . --agents claude,codex
tradepose doctor
tradepose skills check

tradepose strategy new <name> creates one Strategy Family with a human-owned playbook/strategies/**/<name>.py Working Source. Folders organize the workspace but do not participate in source identity. Edit its typed interface and public documentation, then create one self-contained workspace Experiment before previewing:

tradepose strategy new <name> --folder mean_reversion --template rsi-reversion
# Edit playbook/strategies/mean_reversion/<name>.py.
tradepose experiment new research --source working:<name>
tradepose strategy show <name> --json
tradepose strategy status <name> --json
tradepose strategy check <name> --json
tradepose experiment check research --json
tradepose experiment preview research --json

Use experiment new --kind ohlcv_indicators for OHLCV plus declared indicators without signal execution, or --kind ohlcv_signals [--blueprint NAME] for the full signal/trigger/policy path. Periods accept --year YYYY or paired ISO --start/--end bounds.

The SQLite Experiment Catalog contains append-only revisions with shared periods and ordered Working/Formal Strategy Family Members. Use experiment list/show/update/history/diff/restore/archive/clone for lifecycle operations and explicit experiment export/import envelopes for exchange. Use experiment preview --file <path|-> before saving a large definition and experiment edit <slug> for an editor-driven update. Preview resolves exact Source Revisions, Params, parameter selections, Configs, and request hashes without writing a Run or contacting the Gateway. With explicit remote-execution authorization, experiment run <slug> [--detach] creates the sole durable Run; run resume <run-id> continues that same evidence root.

Use tradepose inspect <selector> with strategy:<slug>, source:<slug>@<version|head|working> (or an exact source hash), experiment:<slug>[@revision], portfolio:<slug>[@version], or run:<id> for durable bidirectional lineage. strategy refs --all, experiment refs, and portfolio refs return the same stable typed summary; their activity commands provide filtered, cursor-paginated evidence. run list can be focused with exactly one of --strategy, --experiment, or --portfolio. All discovery is SQLite-only and never contacts the Gateway. Local Portfolio promotion selects exact selection IDs or unambiguous short prefixes and commits Params/Policy-first append-only versions to SQLite. Portfolio state has no watched file projection: use portfolio export <slug> --output <path> when a portable snapshot is needed, and portfolio evaluate to atomically create a new-period Experiment plus its typed Portfolio-version origin without executing it.

Run metadata, canonical request bytes, and source snapshots live in .tradepose/state.sqlite3. Use tradepose state info to see its schema, path, domain record counts and lifecycle commands. Large result files live under results/runs/<run-id>/<task-id>/artifacts/. Inspect local state with run list, run show, and run path; run keep/run unkeep control retention, while run remove removes only safe local evidence and never cancels remote work. Terminal unprotected Runs expire after seven days; preview cleanup with state clean before applying it. SQLite v10 is authoritative. A v9 workspace is migrated only through the explicit, backed-up tradepose state migrate operation; migration is never implicit.

Use tradepose skills install --agents claude,codex to add missing files. tradepose skills sync --agents claude,codex updates only unmodified generated files, and tradepose skills check reports missing, package drift, and user conflicts. Manifest integrity—including malformed or mismatched recorded checksums—or generated-file conflicts use storage exit code 7. See Security boundary, Known limitations, the domain glossary, and the 3.0 breaking workflow guide.

Quick Start

Batch Testing (Recommended)

Test multiple strategies across multiple periods - no async/await needed:

from tradepose_client import BatchTester
from tradepose_client.batch import Period

# Create tester
tester = BatchTester(api_key="tp_live_xxx")

# Submit batch (non-blocking, returns immediately)
batch = tester.submit_backtest(
    strategies=[strategy1, strategy2, strategy3],
    periods=[
        Period.Q1(2024),  # 2024-01-01 to 2024-03-31
        Period.Q2(2024),  # 2024-04-01 to 2024-06-30
        Period.Q3(2024),  # 2024-07-01 to 2024-09-30
    ]
)

print(f"Submitted {len(batch.task_ids)} tasks")
print(f"Progress: {batch.progress:.1%}")

# Wait for completion (blocking)
batch.wait()

# Access trades (Polars DataFrame)
all_trades_df = batch.trades  # All trades with period column

# Period-specific results
q1 = batch[Period.Q1(2024).to_key()]
print(f"Q1 trades: {len(q1.trades)}")
print(f"Q1 PNL: {q1.trades['pnl'].sum()}")

Period Objects (Type-Safe Dates)

Use Period objects for type-safe date validation:

from tradepose_client.batch import Period

# Quarterly testing
periods = [
    Period.Q1(2024),  # Jan-Mar
    Period.Q2(2024),  # Apr-Jun
    Period.Q3(2024),  # Jul-Sep
    Period.Q4(2024),  # Oct-Dec
]

# Full year
full_year = Period.from_year(2024)  # 2024-01-01 to 2024-12-31

# Single month
march = Period.from_month(2024, 3)  # 2024-03-01 to 2024-03-31

# Flexible multi-month ranges
three_months = Period.from_month(2024, 3, n_months=3)  # Mar-May 2024
half_year = Period.from_month(2024, 1, n_months=6)     # Jan-Jun 2024
winter = Period.from_month(2024, 11, n_months=3)       # Nov 2024 - Jan 2025

# Custom range
custom = Period(start="2024-01-15", end="2024-02-15")

Benefits:

  • ✅ Compile-time type checking
  • ✅ IDE autocomplete and validation
  • ✅ Automatic validation (start < end)
  • ✅ Clear error messages

Strategy Authoring

Authoring separates tunable values from assembly: direct typed sources + Opportunity → Definition Builder → Definition → current-wire StrategyConfig.

from tradepose_client import authoring as tp


@tp.strategy(SmaParams)
def sma(builder: tp.DefinitionBuilder, params: SmaParams):
    # Params are registered before this callback; keep using the canonical graph.
    primary = params.primary

    fast = builder.col(primary.fast_sma)
    slow = builder.col(primary.slow_sma)
    atr = builder.col(primary.volatility_atr)
    entry = fast > slow
    exit = fast < slow
    volatility_level = build_volatility_level(
        atr,
        window=primary.volatility_window,
    )

    # Register Data outputs before Base seals and assembles the Definition.
    builder.data.set_volatility_scale(primary.volatility_atr)
    builder.data.set_volatility_level(expr=volatility_level)
    builder.base(
        direction=params.opportunity.direction,
        trend=params.opportunity.trend,
        entry=entry,
        exit=exit,
    )

params = SmaParams()
definition = sma.define(params)
variants = SmaParams.sweep().expand(params)
policies = PolicySet.sweep(
    params,
    direction="long",
    entry_kind="favorable",
    entry_distances=(0.3,),
    stop_losses=(1.0, 1.5),
    take_profits=(2.0, 3.0),
)
configs = sma.build(params, policies=policies)

Call SmaParams.sweep() for the strategy author's default search ranges, or replace its typed keyword-only axes with custom tuples, lists, or ranges.

Create policies only after the Base Params seed. The SDK-owned PolicySet.sweep(params, ...) expands the entry/exit search space into Advanced Blueprints inside its Config; strategy authors only call it and do not implement it on their Params class. Conditions, sizing, lot-size behavior, volatility weights, and metadata remain fixed overrides. Distance policies reference the volatility scale declared by Base Data and cannot replace it. Direction accepts "long", "short", or TradeDirection. Use PolicySet.cases(params, Policy(...), ...) for correlated candidates. Base sweep and Advanced policies cannot be used in the same build.

Construct StrategyParams directly from its typed Pydantic fields and recipe defaults. Import tradepose_client.authoring as tp and name each tp.Source by stable strategy role (primary, context), not sweepable instrument/frequency values. Sources contain flat indicators plus pure source-local Data calculations. StrategyRecipe.define() registers the Data graph before the callback; builder.col() resolves declarations. Each indicator owns its independent completed-bar shift. Use ResampledDataSource for a typed, instrument-inheriting lower-resolution role such as primary 15m → trend 1h; automatic registration validates and materializes that DAG. BUILDER_EXAMPLE.md for a complete executable example.

Core Concepts

Batch Testing API (Primary Interface)

BatchTester is the main way to interact with the platform:

from tradepose_client import BatchTester
from tradepose_client.batch import Period

tester = BatchTester(api_key="tp_live_xxx")

# Submit tasks
batch = tester.submit_backtest(
    strategies=[strategy1, strategy2],
    periods=[Period.Q1(2024), Period.Q2(2024)]
)

# Monitor progress
print(f"Progress: {batch.progress:.1%}")
print(f"Completed: {batch.status_counts['completed']}/{len(batch.task_ids)}")

# Wait for completion
batch.wait()  # Blocks until all tasks complete

# Access trades
all_trades = batch.trades  # All trades across periods

# Period-specific results
q1_result = batch[Period.Q1(2024).to_key()]
print(f"Q1 trades: {len(q1_result.trades)}")

Features:

  • Synchronous interface - No async/await required
  • Background polling - Tasks execute in background, results auto-download
  • Type-safe dates - Period objects with validation
  • Polars DataFrames - High-performance data analysis
  • Jupyter-friendly - Automatic event loop setup

Instrument Discovery

Synchronize the Gateway's complete instrument catalog into the current workspace:

tradepose instruments sync
tradepose instruments sync --if-stale 24h
tradepose instruments status --json

The sync writes immutable snapshots below .tradepose/instruments/ and an SDK-managed, IDE-indexable tradepose_generated/ package. Both paths are added to the managed .gitignore block. Generated files are checksum verified; unmanaged files, local edits, missing snapshots, and manifest drift fail closed unless an explicit --repair or --force operation is requested.

After a successful sync, notebooks and ordinary Python applications can use static autocomplete and pass the canonical string leaf directly to a typed Source:

from tradepose_generated.instruments import instruments

instrument = instruments.PEPPERSTONE.FUTURES.NAS100
assert instrument == "PEPPERSTONE:futures:NAS100"

Catalog projection imports never perform network I/O. Strategy Working Sources remain restricted from workspace-local imports until Catalog Binding and portable lineage evidence are implemented; keep generated catalog use in notebooks and application code for this phase.

The legacy synchronous discovery helper remains available:

from tradepose_client import BatchTester

tester = BatchTester(api_key="tp_live_xxx")

# List all available instruments
instruments = tester.list_instruments()
print(f"Available instruments: {len(instruments)}")

for inst in instruments[:5]:
    print(f"  {inst.symbol} - {inst.exchange} ({inst.freq})")

# Filter by exchange
binance = [i for i in instruments if i.exchange == "BINANCE"]

CRUD Resources (v0.3.0)

Manage trading entities via Gateway API:

from tradepose_client import TradePoseClient

client = TradePoseClient(api_key="tp_live_xxx")

# Strategy management
strategies = client.strategies.list()
strategy = client.strategies.create(name="MyStrategy", config={...})

# Portfolio management
portfolios = client.portfolios.list()
portfolio = client.portfolios.create(
    name="MyPortfolio",
    capital=100000,
    currency="USD"
)

# Account management (MT5, Binance, etc.)
accounts = client.accounts.list()

# Binding (connect Portfolio to Account)
binding = client.bindings.create(
    account_id=account.id,
    portfolio_id=portfolio.id
)

Low-Level API (Advanced Users)

For fine-grained control over HTTP connections, custom retry logic, or manual event loop management, see Low-Level API Documentation.

Most users should use BatchTester - it's simpler and handles async complexity automatically.

Task Polling Pattern

Long-running operations return immediately with a task ID. Results are downloaded automatically in the background:

# Submit returns immediately
batch = tester.submit_backtest(strategies=[strategy], periods=[Period.Q1(2024)])
print(f"Task ID: {batch.task_ids[0]}")  # Submitted

# Background polling starts automatically
# Do other work while tasks run...

# Wait when you need results
batch.wait()  # Blocks until completion

# Results ready
trades = batch.trades

Documentation

Features

Current (Alpha)

Batch Testing API

  • ✅ Multi-strategy, multi-period testing
  • ✅ Background polling (daemon thread)
  • ✅ Auto-download on completion
  • ✅ Type-safe Period objects with validation
  • ✅ Convenient constructors (Q1, Q2, from_year, from_month)
  • ✅ Reactive results (lazy loading)
  • ✅ Memory caching
  • ✅ Jupyter support (nest_asyncio auto-applied)

Builder API

  • ✅ Fluent strategy construction
  • ✅ Type-safe indicator references
  • ✅ 60% less boilerplate
  • ✅ TradingContext convenience accessors
  • ✅ Automatic field inheritance

Low-Level Client API

  • ✅ Authentication (API key + JWT)
  • ✅ Resource-based organization (6 resources, 21 methods)
  • ✅ Async-first with HTTP/2
  • ✅ Idempotency recovery for ambiguous submissions and bounded polling/download recovery
  • ✅ Comprehensive error handling (18 exception types)
  • ✅ Type-safe with Pydantic models

CRUD Resources (v0.3.0)

  • ✅ Strategy management (create, list, get, update, delete)
  • ✅ Portfolio management with capital allocation
  • ✅ Account management (MT5, Binance, etc.)
  • ✅ Binding management (Account ↔ Portfolio)
  • ✅ Instrument discovery (list_instruments())
  • ✅ TradingContext convenience accessors

Roadmap

  • ⏳ Webhook support (replace polling)
  • ⏳ GraphQL endpoint (reduce requests)
  • ⏳ Result streaming (large datasets)

Configuration

Environment Variables

# Authentication (required, at least one)
export TRADEPOSE_API_KEY="tp_live_xxx"
export TRADEPOSE_JWT_TOKEN="eyJ..."

# Server (optional)
export TRADEPOSE_SERVER_URL="https://api.tradepose.com"

# HTTP (optional)
export TRADEPOSE_TIMEOUT="30.0"        # Request timeout (1.0 - 600.0s)

# Task polling (optional)
export TRADEPOSE_POLL_INTERVAL="2.0"    # Poll interval (0.5 - 60.0s)
export TRADEPOSE_POLL_TIMEOUT="300.0"   # Max poll duration (10.0 - 3600.0s)

# Logging (optional)
export TRADEPOSE_DEBUG="false"
export TRADEPOSE_LOG_LEVEL="INFO"       # DEBUG/INFO/WARNING/ERROR/CRITICAL

Configuration Methods

# Method 1: Read the environment explicitly
import os
tester = BatchTester(api_key=os.environ["TRADEPOSE_API_KEY"])

# Method 2: Direct parameters
tester = BatchTester(
    api_key="tp_live_xxx",
    poll_interval=2.0,
)

# Method 3: Configuration file (see Configuration Guide)

See Configuration Guide for details.

Error Handling

All exceptions inherit from TradePoseError:

from tradepose_client import (
    BatchTester,
    AuthenticationError,
    RateLimitError,
    TaskTimeoutError,
    ValidationError
)
from tradepose_client.batch import Period

tester = BatchTester(api_key="tp_xxx")

try:
    batch = tester.submit_backtest(
        strategies=[strategy],
        periods=[Period.Q1(2024)]
    )
    batch.wait(timeout=600.0)

except AuthenticationError:
    # Invalid API key
    print("Authentication failed")

except ValidationError as e:
    # Invalid Period or strategy configuration
    print(f"Validation error: {e.errors}")

except RateLimitError as e:
    # Rate limit exceeded
    print(f"Rate limited. Wait {e.retry_after}s")

except TaskTimeoutError as e:
    # Task didn't complete in time
    print(f"Timeout. Task ID: {e.task_id}")

See Error Handling Guide for complete reference.

Period Validation

Period objects automatically validate date ranges:

from tradepose_client.batch import Period

# Valid period
period = Period(start="2024-01-01", end="2024-12-31")  # ✅ OK

# Invalid period (start >= end)
try:
    period = Period(start="2024-12-31", end="2024-01-01")  # ❌ Error
except ValueError as e:
    print(e)  # "Period start (2024-12-31) must be before end (2024-01-01)"

# Invalid date format
try:
    period = Period(start="invalid", end="2024-12-31")  # ❌ Error
except ValueError as e:
    print(e)  # "Cannot parse datetime from type..."

Migration from Tuple-Based Periods

Before (deprecated):

# ❌ No longer supported
batch = tester.submit_backtest(
    strategies=[strategy],
    periods=[("2024-01-01", "2024-12-31")]  # Tuple not accepted
)

After (type-safe):

# ✅ Required: Use Period objects
from tradepose_client.batch import Period

batch = tester.submit_backtest(
    strategies=[strategy],
    periods=[Period(start="2024-01-01", end="2024-12-31")]
)

# ✅ Even better: Use convenience constructors
batch = tester.submit_backtest(
    strategies=[strategy],
    periods=[Period.from_year(2024)]  # Clearer and type-safe
)

This is a Breaking Change in version 0.2.0+. Update your code to use Period objects.

Development Status

Alpha - API is stable but subject to minor changes. Production use at your own risk.

Python Version Support

Requires Python 3.13+ to leverage:

  • Type parameter syntax ([T])
  • Self type hint
  • Performance improvements

License

MIT License - see LICENSE file for details.

Support

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tradepose_client-3.3.1.tar.gz (369.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tradepose_client-3.3.1-py3-none-any.whl (293.6 kB view details)

Uploaded Python 3

File details

Details for the file tradepose_client-3.3.1.tar.gz.

File metadata

  • Download URL: tradepose_client-3.3.1.tar.gz
  • Upload date:
  • Size: 369.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for tradepose_client-3.3.1.tar.gz
Algorithm Hash digest
SHA256 8ede4172d2572402ef845827ca9a849b1037914f6c48b6e3e139b14492902d2b
MD5 806335302952eb89f1936e7eb18ab104
BLAKE2b-256 b6d25b4ff5608c8cf3bf0aa4e8147b21466fd6184c44157a736254e7ca42189e

See more details on using hashes here.

File details

Details for the file tradepose_client-3.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for tradepose_client-3.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a184926307aa4ef0125a772e437345c0fcc4821850fbe61724bda71c6220215a
MD5 d4305430d5634585b70acd4b69f69b77
BLAKE2b-256 ddcd8e7259a1b2efe786fc6ea702be948aac23a5ab3114c4875b0d73fb7dae36

See more details on using hashes here.

Release history Release notifications | RSS feed

3.11.1

2 files

3.11.0

2 files

3.10.0

2 files

3.9.0

2 files

3.8.0

2 files

3.7.0

2 files

3.6.1

2 files

3.6.0

2 files

3.5.1

2 files

3.5.0

2 files

3.4.3

2 files

3.4.2

2 files

3.4.1

2 files

3.4.0

2 files

This release

3.3.1 This release

2 files

3.3.0

2 files

3.2.5

2 files

3.2.4

2 files

3.2.3

2 files

3.2.2

2 files

3.2.1

2 files

3.2.0

2 files

3.1.0

2 files

3.0.0

2 files

2.6.2

2 files

2.6.1

2 files

2.6.0

2 files

2.5.0

2 files

2.4.0

2 files

2.3.0

2 files

2.2.0

2 files

2.1.0

2 files

2.0.0

2 files

1.8.1

2 files

1.8.0

2 files

1.7.1

2 files

1.7.0

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page