Metadata-Version: 2.5
Name: alphaboard
Version: 0.1.0
Summary: AlphaBoard SDK — strategy-level monitoring for algorithmic traders. Pushes trades, positions, equity, and heartbeats to an AlphaBoard server without ever blocking your trading loop.
Project-URL: Homepage, https://github.com/opmau/AlphaBoard
Project-URL: Repository, https://github.com/opmau/AlphaBoard
Project-URL: Issues, https://github.com/opmau/AlphaBoard/issues
Project-URL: Documentation, https://github.com/opmau/AlphaBoard/tree/main/docs
Author-email: Adam King <adm.king@gmail.com>
License: Apache-2.0
License-File: LICENSE
Keywords: algotrading,monitoring,observability,quant,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28.0
Requires-Dist: tomli>=2.0; python_version < '3.11'
Description-Content-Type: text/markdown

# alphaboard

Python SDK for [AlphaBoard](https://github.com/opmau/AlphaBoard) — strategy-level monitoring and reconciliation for algorithmic traders. (Formerly `stratops`; renamed to the single brand in OPM-762.)

```python
from alphaboard import AlphaBoard

tracker = AlphaBoard(
    strategy="momentum_eth",
    broker="hyperliquid",
    account="main",
)

# Inside your trade execution function:
tracker.log_trade(symbol="ETH-PERP", side="buy", quantity=0.5, price=3800)

# Periodic sync:
tracker.sync_positions([{"symbol": "ETH-PERP", "quantity": 1.5, "avg_entry_price": 3750}])
tracker.log_equity(equity=50_000, cash=10_000)
tracker.heartbeat(open_positions=1)
```

## Configuration

Connection settings resolve in this order (highest priority first):

1. **Constructor parameters** — `AlphaBoard(api_url=..., api_key=...)`
2. **Environment variables** — `ALPHABOARD_API_URL`, `ALPHABOARD_API_KEY`
3. **Config file** — `~/.alphaboard/config.toml` (override path via `ALPHABOARD_CONFIG`)
4. **Built-in defaults** — `http://localhost:8000`, no key

The legacy `STRATOPS_*` env vars and `~/.stratops/config.toml` are still read
as a fallback (one-time deprecation warning) — switch to the new names.

Example `~/.alphaboard/config.toml`:

```toml
api_url = "https://alphaboard.example.com"
api_key = "sk_..."
# Optional: turn on the durable spool (see below)
spool_dir = "C:/alphaboard-spool"
```

## Is it actually connected? (`alphaboard doctor`)

Installing the SDK and seeing no errors proves nothing — the SDK never raises,
by design, so a completely misconfigured client looks exactly like a working
one from inside your strategy. `alphaboard doctor` is the one command that
answers *am I being watched?*:

```bash
alphaboard doctor
alphaboard doctor --api-url https://alphaboard.example.com --api-key sk_...
```

It runs four checks in order and stops at the first failure, so you fix causes
rather than symptoms:

| Check | Answers |
| --- | --- |
| `api` | Is the server reachable, and is its database connected? |
| `auth` | Does your API key authenticate? |
| `probe` | Does ingestion accept a real write? |
| `coverage` | The census: every strategy and account, the age of each stream, and a verdict of LIVE / DEGRADED / SILENT. |

Exit codes make it usable from a scheduled task or a CI step: **2** if the API
or the key is broken, **1** if everything is reachable but something is not
reporting, **0** if all four pass.

Two properties are worth knowing about, because they are the difference between
a diagnostic and a placebo:

- **It creates nothing.** The write probe is a single infrastructure heartbeat
  that deliberately carries **no strategy name**. A probe posted under a real
  strategy would refresh that strategy's heartbeat stream *and* forward a
  success ping to its external monitor — so a strategy that had been dead for a
  day would read LIVE on the very next line of the diagnostic's own output, and
  its real alert would be silenced. Pass `--no-probe` to skip the write
  entirely and run read-only.
- **Zero strategies is a failure, not a pass.** "0/0 live" is technically full
  coverage and is exactly the reassuring lie that hides a pipe that was never
  connected.

## Durable spool (no-data-loss mode)

By default the SDK buffers events in memory only — a crash or an extended
server outage can drop events (your trading is never affected either way).
Setting a `spool_dir` (constructor param, `ALPHABOARD_SPOOL_DIR`, or the config
file) turns on a disk-backed outbox:

```python
tracker = AlphaBoard(strategy="momentum_eth", spool_dir="C:/alphaboard-spool")
```

- Events are mirrored to a SQLite WAL file by the background worker and
  deleted only after the server confirms receipt — they survive `SIGKILL`,
  power loss, and outages of any length.
- Replays reuse the **same** idempotency keys and carry the **original**
  event timestamps, so the server deduplicates them: at-least-once on the
  wire, effectively-once end-to-end.
- The spool is bounded by rows, bytes, and age (defaults: 1M rows / 512 MB /
  7 days; tune via `spool_max_rows`, `spool_max_bytes`, `spool_max_age_s`).
  On breach it drops oldest and surfaces the count via
  `tracker.spool_dropped_count` — an indefinite outage can't fill your disk.
- Any spool failure (disk full, locked, corrupt) degrades the SDK back to
  memory-only. Durability never becomes a new way to crash the host.

## Backfill (historical seeding + gap recovery)

`alphaboard backfill` replays a historical CSV — a broker statement, a Zorro
log, your engine's own journal — through the server's batch endpoints with
**deterministic** idempotency keys (UUIDv5 of each row's business key), so
re-running the same file or window is a no-op, never a duplicate:

```bash
alphaboard backfill trades.csv  --kind trades --strategy momo --broker ib --account main
alphaboard backfill equity.csv  --kind equity --strategy momo --mapping '{"Time": "snapshot_at", "Equity": "equity"}'
alphaboard backfill positions.csv --kind positions --strategy momo --broker ib --account main --dry-run
```

- `--kind` is `trades`, `equity`, or `positions`; `--mapping` renames CSV
  headers to canonical fields (same convention as the server's CSV import).
- `--strategy/--broker/--account` fill in routing fields the CSV doesn't
  carry; columns present in the file win.
- `--since/--until` window on the row's *event* time; `--dry-run` validates
  and counts without sending.
- Rows must carry their original `executed_at`/`snapshot_at` — backfill
  refuses to stamp wall-clock-at-import times onto history.
- Also available in code: `tracker.backfill("trades.csv", kind="trades")`.

## Design

The SDK is **observation-path only**. It never sits between your strategy and the broker. The single hard guarantee:

> `tracker.log_trade(...)` returns in microseconds, never blocks, and never raises.

Every public method enqueues an event into a bounded in-memory deque (default 10 000 items, drop-oldest on overflow), and returns immediately. A daemon background thread batches events, posts them to the AlphaBoard API with exponential backoff, and never lets an exception escape back to user code.

If the AlphaBoard server is unreachable, events back up in the queue until it returns or the queue overflows. **Your trading continues unaffected.**

On process shutdown, an `atexit` hook drains the queue with a bounded timeout (default 5s) so events from the final loop iteration aren't lost.

## Install

```bash
pip install alphaboard
```

That pulls in `httpx` and its transitive dependencies and nothing else —
eight packages total. The SDK deliberately has no dependency on the API server,
the dashboard, or anything else in the workspace, so it installs cleanly into a
strategy process that shares none of them.

Working on the SDK itself? Install it from a checkout instead:

```bash
pip install ./packages/sdk
```

## Licence

Apache 2.0.
