Alpha Trade Sync
Purpose
This dashboard now syncs Alpha option-trade rows from the canonical Alpha export endpoint in ~/server instead of the old placeholder OMS JSON shape.
The sync is:
- portfolio-scoped, not crypto-currency-scoped
- cursor/watermark-based, not single-shot
limitbased - strict about contract validation
- explicit about per-contract price vs total USD premium
Required Backend Configuration
Set these on the backend service:
ALPHA_TRADE_FEED_URL- Full internal export URL, for example:
https://api.bitwiseinvestments.com/api/v1/alpha/optionTrades/export
ALPHA_TRADE_FEED_API_KEY- API key with
alphaAccesspermission for the~/serverexport endpoint - Send the raw key in the
Authorizationheader; do not prefix it withBearer
- API key with
ALPHA_TRADE_FEED_PORTFOLIOS- Comma-separated Alpha portfolios; production is currently configured as
IMST,ICOI
- Comma-separated Alpha portfolios; production is currently configured as
Optional:
ALPHA_TRADE_FEED_INCLUDE_PENDING- Default
false - Operators can override this per run with the
Include pendingcheckbox on/trades
- Default
ALPHA_TRADE_FEED_TIMEOUT_SECONDS- Default
20
- Default
Stored Trade Semantics
For synced Alpha rows:
price: per-contract price inprice_currencycontract_multiplier: source multiplier from Alphaquantity: filled contract countpremium_usd: total trade premium in USDfees_usd: total USD fees for the tradetrade_status: source trade statusrecon_status: source-provided Alpha reconciliation status
Do not interpret price as total dollars.
Market Proxy Mapping
Alpha rows store the traded underlying, for example MSTR or COIN. Many dashboard opportunity and regime signals are keyed by crypto market, for example BTC, ETH, or SOL. The backend resolves this split through back-end/market_proxy.py.
Current production mappings:
| Alpha underlying | Dashboard market proxy | Mapping quality | Interpretation |
|---|---|---|---|
MSTR | BTC | proxy_mapped | Use BTC dashboard context for opportunity/regime attribution, but use MSTR option quotes for execution and outcome marks. |
COIN | BTC | proxy_mapped | Use BTC dashboard context for opportunity/regime attribution, but use COIN option quotes for execution and outcome marks. |
BTC / ETH / SOL | Same market key | available | Direct crypto market mapping. |
Unknown symbols return unmapped with market_proxy = null. The dashboard must not silently default an unknown Alpha underlying to BTC. Downstream enrichment should skip or explicitly label unmapped trades until a mapping is added to back-end/market_proxy.py.
Trade-Time Market Context Backfill
The trade-performance phase adds a backend backfill path:
POST /api/internal/trades/context/backfill
The endpoint is admin-protected and defaults to dry run. It joins Alpha-synced trades to nearest available dashboard context using the market proxy mapping above.
Currently captured when available:
- market proxy, mapping method, mapping confidence, and mapping quality
- nearest
gex_hourlyspot and GEX imbalance - nearest
vol_metrics_snapshotsDVol, VRP, 30d IV, and 30d RV - DVol percentile over the lookback window
- gamma regime from historical GEX imbalance thresholds
- context quality and missing-field list
Currently not captured by this first backfill:
- smile rich/cheap state at exact trade time
- 24h volume and open interest at exact trade time
Smile is intentionally not sourced for Alpha trade rows in this phase. BTC smile is still useful on market analytics pages, but it is not stamped onto MSTR/COIN option trades as a contract-level smile proxy. Other missing fields are persisted as unavailable/missing until a later enrichment step can source them safely. Missing context is not converted to zero.
Execution Benchmark Backfill
Execution-quality enrichment uses a separate admin-protected backfill path:
POST /api/internal/trades/execution-benchmarks/backfill
The benchmark hierarchy is strict:
- Use a fresh Amberdata TradFi level-1 quote for the actual traded underlying and contract when available.
- Mark quote-derived values as
staleif the nearest quote is outside the configured tolerance. - Use a surface/model mark only as
estimated; never populate bid, ask, or mid from a model. - Return
unavailablewhen no defensible quote or estimate exists.
For current Alpha scope:
| Alpha underlying | Benchmark source |
|---|---|
MSTR | Amberdata TradFi level-1 quotes for MSTR options |
COIN | Amberdata TradFi level-1 quotes for COIN options |
Direction signs:
- Buy slippage uses
fill_price - benchmark_mid; positive means worse than mid. - Sell slippage uses
benchmark_mid - fill_price; positive means worse than mid.
The dashboard must not fabricate bid, ask, mid, or slippage when quote data is missing.
Position Lifecycle View
Alpha rows are executions, not positions. The dashboard groups them into derived option-contract lifecycles with:
GET /api/internal/trades/positions?source=alpha_sync
Grouping keys:
- source portfolio
- traded underlying
- option symbol or instrument
- option type
- strike
- expiry
Accounting rules:
- Each execution quantity is treated as a positive contract count; direction controls the sign.
- Buys increase long exposure or close short exposure.
- Sells increase short exposure or close long exposure.
- Matching uses FIFO within the grouped option contract.
average_open_priceis weighted by remaining quantity and contract multiplier.total_gross_premium_usdandnet_premium_cashflow_usdare populated only when every execution in the lifecycle has a defensible USD premium.known_gross_premium_usdandknown_net_premium_cashflow_usdshow the sum of available premium rows when premium data is incomplete.- Fees follow the same pattern:
total_fees_usdrequires complete fee data;known_fees_usdreports the known subset. - Derived lifecycle cashflow is calculated for internal investigation, but it is not displayed as user-facing realized P&L until validated against authoritative accounting or explicit source open/close intent.
Lifecycle states:
| State | Meaning |
|---|---|
closed | Buys and sells fully offset to zero net quantity. |
open_long | Net quantity remains long after matching closes. |
open_short | Net quantity remains short after matching closes. |
Lifecycle quality:
| Quality | Meaning |
|---|---|
clean | Closed lifecycle with complete required grouping and economics. |
open | Valid lifecycle, but a missing close remains by design. |
incomplete_economics | Grouping is usable but price, premium, fee, or realized-P&L inputs are incomplete. |
ambiguous | Required identifiers or execution fields are missing/invalid. Do not use as clean position-level analytics. |
Flips are allowed and flagged. For example, buying 5 contracts and then selling 8 contracts closes 5 long contracts and opens 3 short contracts. The lifecycle remains deterministic, but lifecycle_flags includes flipped so downstream screens can disclose the path.
Opportunity Alignment
Opportunity alignment is a signal-consistency score, not a P&L score. It asks whether the trade direction matched the dashboard opportunity backdrop at execution time.
GET /api/internal/trades/opportunity-alignment?source=alpha_sync
Assumption boundary:
strategy_intentisunknownuntil a future workflow explicitly tags intent.- Buy-option rows are scored under an
assumed_strategyoflong_vol. - Sell-option rows are scored under an
assumed_strategyofshort_vol. - Call versus put is carried through the output, but the first scoring pass does not infer directional delta intent from option type.
Scoring rules:
| Signal | Buy/long-vol alignment | Sell/short-vol alignment |
|---|---|---|
| DVol percentile | Low percentile is a driver; high percentile is a detractor. | High percentile is a driver; low percentile is a detractor. |
| VRP | Negative/low VRP is a driver; rich positive VRP is a detractor. | Rich positive VRP is a driver; negative/low VRP is a detractor. |
| Smile bucket | cheap is a driver; rich is a detractor. | rich is a driver; cheap is a detractor. |
| Gamma regime | short_gamma modestly supports long-vol exposure. | long_gamma modestly supports short-vol exposure. |
| Stationarity | stable modestly improves the score; unstable reduces score and confidence. | Same. |
| Term structure | Near-term risk concentration modestly supports long-vol exposure. | Benign carry/contango modestly supports short-vol exposure. |
Confidence is separate from score. It is reduced when:
- context is stale, unavailable, or unmapped
- the Alpha underlying uses a proxy mapping such as MSTR/COIN to BTC
- stationarity is unstable or insufficient
- signal coverage is incomplete
Labels:
| Label | Meaning |
|---|---|
aligned | Available signals mostly supported the assumed strategy. |
partially_aligned | More supportive than not, but not conclusive. |
mixed | Drivers and detractors were balanced. |
weak_alignment | Available signals were mostly weak. |
misaligned | Available signals contradicted the assumed strategy. |
insufficient_data | Required context was unavailable or unmapped. |
The API also returns aggregate summaries by portfolio, underlying, gamma regime, signal, and month.
Outcome And Regime Attribution
Outcome attribution measures what happened after entry only when a sourced forward mark is available.
GET /api/internal/trades/outcomes?source=alpha_sync&horizons=1,7,30
By default the endpoint reads persisted forward outcome marks from trade_forward_outcome_marks. It returns explicit pending or unavailable horizon outcomes when no usable persisted mark exists. When fetch_marks=true, the backend can look up Amberdata TradFi level-1 quotes at each requested horizon for a small ad hoc batch, but production use should backfill marks through:
POST /api/internal/trades/outcomes/backfill
The backfill is admin-protected, defaults to dry run, and upserts rows keyed by (source, source_trade_id, horizon_key).
Outcome states:
| State | Meaning |
|---|---|
unrealized_mark | P&L is computed from a fresh sourced forward mark. |
pending | The requested horizon has not matured yet, so P&L remains blank. |
unavailable | Required mark, entry premium, direction, quantity, or source data is unavailable. |
Mark quality:
| Quality | Meaning |
|---|---|
quoted | Fresh sourced Amberdata TradFi mark was used. |
stale | A quote existed but was outside the allowed time tolerance, so P&L is not computed. |
unavailable | No usable sourced mark was available. |
P&L rules:
- Buy-option P&L before fees:
mark_premium_usd - entry_premium_usd. - Sell-option P&L before fees:
entry_premium_usd - mark_premium_usd. mark_premium_usd = mark_price * quantity * contract_multiplier.pnl_after_fees_usdis populated only whenfees_usdis available.- Missing marks, stale marks, missing premium, or missing quantity produce null P&L, never zero.
Expiry outcomes remain unavailable unless a sourced quote or settlement mark exists. The dashboard should not silently substitute intrinsic/model expiry values.
Aggregates answer which portfolios, underlyings, gamma regimes, alignment labels, and DVol buckets produced positive/negative sourced outcomes for a selected horizon.
Sync State
Persisted in internal_trade_sync_state:
last_successful_cursorlast_successful_watermarklast_successful_sync_atlast_errorscope_key
Scope key format is portfolio-based:
portfolio_names=<sorted list>|include_pending=<true|false>
Operator Workflow
Use the OMS/PMS Sync card on /trades.
Dry run
Use Dry run for a preview.
Check:
- fetched row count
- normalized row count
- rejected row count
- inserted / updated / unchanged breakdown
- quantity delta
- premium delta
- unmatched source trade ids
- unmatched local trade ids
- next watermark
Full-scope sync diagnostic
Enable the full-scope diagnostic before the dry run when you need a complete sync-completeness check for the configured scope.
Use this before interpreting Performance from a freshly changed feed scope, or after changing sync logic.
Real sync
Turn Dry run off only after the preview looks correct.
After a real sync:
- confirm last successful sync time updates
- confirm next watermark advances
- confirm the trade table shows
source_portfolio,trade_status,recon_status - confirm price is shown per contract and premium in USD
Verification Checklist
Before moving the trade-sync milestone to In Review:
-
ALPHA_TRADE_FEED_URLpoints at the canonical server export endpoint -
ALPHA_TRADE_FEED_API_KEYhasalphaAccesspermission - configured portfolio names resolve in Alpha
- dry run succeeds without contract-validation surprises
- full-scope diagnostic shows acceptable quantity and premium deltas
- re-running a real sync does not duplicate rows
- updated rows show changed-field evidence when the source changed
- the trade table labels price, premium, fees, and P&L unambiguously
Known Scope Boundary
This milestone makes ingestion and valuation semantics explicit and adds a bounded path for sourced forward marks. If Amberdata TradFi coverage is missing, stale, or not entitled for a synced row, P&L should remain blank rather than guessed. Expiry and authoritative realized P&L remain unavailable until backed by settlement, source accounting, or another approved source.