EventTrader
AI-Native Trading
PAPER
Menu
Dark Mode
Plain English Mode
PAPER TRADING MODE — Enable real trading on your Account page
Back

Composer Python SDK

A thin, dependency-light Python client for the Composer AI basket advisor. It wraps the same endpoints documented in the REST API reference: build a draft risk-sized basket from a theme + risk profile, fetch a saved draft, and find historical analogs. Composer returns draft recommendations only — no live trading, nothing bought or sold. Not investment advice.

Install

pip install requests

The SDK is a single file you can drop into your project — no package install required. It talks to the public API over HTTPS.

Quickstart

from composer import ComposerClient

client = ComposerClient(
    base_url="https://cymetica.com",
    email="you@example.com",
    password="…",
)

# Build a draft, risk-sized basket from a theme + risk profile (1-5 Likert)
draft = client.compose(
    theme="data center electricity",
    time_horizon_years=5,
    loss_capacity=3,
    loss_tolerance=3,
    knowledge=3,
    liquidity_need=3,
)
print("draft:", draft["public_ref"], "risk:", draft["risk_score"])
for leg in draft["assets"]:
    print(f"  {leg['symbol']:6} {leg['asset_class']:8} {leg['weight']:.0%}")
print(draft["legal_disclaimer"])

Fetch a Saved Draft

same = client.get_draft(draft["public_ref"])
print(same["rationale"])

Historical Analogs

# How did similar past events perform? (semantic headline-embedding match)
analogs = client.historical_analogs(draft["public_ref"], window_days=30, limit=8)
print(analogs)

Hand Off to MacroMarket (backtest the draft)

Composer is advisory; to backtest a draft as an AI Index Basket, post it to MacroMarket — see the MacroMarket SDK:

import requests
r = requests.post(
    f"https://cymetica.com/api/v1/macromarket/from-composer/{draft['public_ref']}",
    headers={"Authorization": f"Bearer {client.token}"},
    params={"period_days": 365}, timeout=60,
)
print(r.json())   # hypothetical backtest metrics — paper only

SDK Source (paste this file)

"""composer.py — minimal client for the EventTrader Composer basket advisor."""
import requests


class ComposerClient:
    def __init__(self, base_url: str, email: str | None = None, password: str | None = None):
        self.base = base_url.rstrip("/")
        self.s = requests.Session()
        self.token = None
        if email and password:
            r = self.s.post(f"{self.base}/auth/login",
                            json={"email": email, "password": password}, timeout=15)
            r.raise_for_status()
            self.token = r.json()["access_token"]
            self.s.headers.update({"Authorization": f"Bearer {self.token}"})

    def compose(self, theme: str, time_horizon_years: int, loss_capacity: int,
                loss_tolerance: int, knowledge: int, liquidity_need: int):
        r = self.s.post(f"{self.base}/api/v1/composer/instruments", json={
            "theme": theme,
            "time_horizon_years": time_horizon_years,
            "loss_capacity": loss_capacity,
            "loss_tolerance": loss_tolerance,
            "knowledge": knowledge,
            "liquidity_need": liquidity_need,
        }, timeout=60)
        r.raise_for_status()
        return r.json()

    def get_draft(self, public_ref: str):
        r = self.s.get(f"{self.base}/api/v1/composer/instruments/{public_ref}", timeout=15)
        r.raise_for_status()
        return r.json()

    def historical_analogs(self, public_ref: str, window_days: int = 30, limit: int = 8):
        r = self.s.post(
            f"{self.base}/api/v1/composer/instruments/{public_ref}/historical-analogs",
            json={"window_days": window_days, "limit": limit}, timeout=30)
        r.raise_for_status()
        return r.json()

Example: scan several themes by risk score

themes = ["data center electricity", "cures for cancer", "space industry"]
for t in themes:
    d = client.compose(t, 5, 3, 3, 3, 3)
    print(f"{t:28} risk={d['risk_score']} vol={d['projected_vol']} legs={len(d['assets'])}")