Raxx · internal docs

internal · gated

Model Card — Layered Covered Call Income Cycle

Strategy ID: lcc-income-cycle Status: Ready for feature-dev handoff. OQ-1 through OQ-5 locked 2026-06-05. Intended Consumer: feature-developer (Raptor/Antlers implementation), software-architect (service design) Date: 2026-05-05 Last Updated: 2026-06-05 Tracking Issue: #3282


1. What This Strategy Does

The Layered Covered Call Income Cycle is a paper-trading strategy module that manages a share position paired with weekly covered calls distributed across multiple strike zones. The strategy tracks premium income, assignment events, tax-lot selection, and re-entry decisions as explicit, rule-based state transitions.

It is NOT a prediction engine. It does NOT recommend trades. It enforces a pre-committed rule set against a paper-trading position and records what happened.


2. Inputs Required

2.1 Per-Cycle Inputs (provided by the trader, pre-market)

{
  "sentiment_label": "string (Neutral | Bullish | Bearish | HighUncertainty)",
  "sentiment_committed_at": "string (ISO 8601 date — used for staleness check)",
  "ticker": "string",
  "options_chain": {
    "expiration_date": "string (ISO 8601 date)",
    "strikes": [
      {
        "strike": "number",
        "bid": "number",
        "ask": "number",
        "delta": "number",
        "extrinsic": "number"
      }
    ]
  },
  "underlying_open_price": "number",
  "underlying_prior_close": "number"
}

2.2 System State Inputs (maintained by paper-trading engine)

2.3 Historical Data (for backtest only)


3. Outputs

3.1 Per-Cycle Outputs

{
  "cycle_id": "string (uuid4)",
  "sentiment_was_fallback": "boolean (true if staleness fallback applied)",
  "proposed_call_structure": [
    {"zone": "string (ITM|ATM|OTM)", "contracts": "integer", "target_delta_range": "string"}
  ],
  "opening_sell_timing": {
    "market_condition": "string",
    "recommended_delay_minutes": "integer",
    "reason": "string"
  },
  "alerts": ["array of Alert objects"],
  "re_entry_decision": "ReentryDecision object or null"
}

3.2 Ledger Records (written per event)

3.3 Dashboard Metrics (computed on demand from ledger)

See metrics.py for implementations of all 14 metrics.


4. What Can Fail

Failure Impact Detection Resolution
Options chain data missing for target expiration Cycle cannot start — no strikes to select Null check on options_chain input Surface "chain unavailable" alert; skip cycle
Sentiment label stale (>1 market day) More conservative call structure applied (High-Uncertainty fallback) STALE_SENTIMENT_LABEL alert Strategy continues; operator notified; provide fresh label to override
Shares drop below configured N Cycle blocked; LCC auto-disabled SHARES_BELOW_MIN_THRESHOLD alert; state=DISABLED Operator card: buy shares back + re-enable / reconfigure N / close strategy
Roll debit exceeds per-instance threshold Roll refused; operator must decide refuse_roll action returned; operator notified 3-option card: take assignment / close-and-reopen / one-shot override
Early assignment (American-style) State holds at EARLY_ASSIGNMENT_PENDING early_assignment_flag=True in AssignmentEvent; full-screen card opens Operator selects from 4-option card; no autonomous action
State machine consistency violation Naked call recorded, data corruption NAKED_CALL_DETECTED + STATE_CONSISTENCY_ERROR alerts Block all actions; require manual reset
Options data vendor outage Can't price open calls for exit evaluation Circuit breaker: mark data as stale; surface warning Hold state; do not auto-act on stale data
FIFO lot selection diverges from broker P/L attribution wrong Documented known limitation CPA disclaimer; verify per broker before live

5. What to Monitor in Production (Phase 3+)

Metric Alert Threshold Frequency
Consecutive below-cost assignments ≥3 in 30 days Per-cycle
Consecutive all-ITM weeks ≥3 Per-cycle
NAKED_CALL_DETECTED alert Any firing Real-time
SHARES_BELOW_MIN_THRESHOLD alert Any firing Real-time
EARLY_ASSIGNMENT_PENDING cards unresolved >4h without operator selection Real-time
STALE_SENTIMENT_LABEL fallback rate >3 cycles in a rolling 2-week window Weekly
Assignment surprise rate >20% of assignments were not flagged as "high assignment risk" 24h before Weekly
Premium below minimum rate >40% of cycles unable to meet minimum premium criterion Weekly
State machine error rate Any Real-time

6. Compute and Storage Budget

Scale Compute per Cycle Storage per Year
1 user, 1 ticker < 10ms (pure Python, no ML) ~500KB (JSON ledger)
10 users, 1-3 tickers each < 100ms aggregate ~5MB
100 users, 1-5 tickers each < 1s aggregate ~50MB
1,000 users Recommend async Celery task per user cycle ~500MB

Storage is append-only ledger records. Historical backtest artifacts are stored separately under docs/data-science/backtests/lcc-income-cycle/ and not part of the per-user runtime storage.


7. Broker Agnosticism

This module is broker-agnostic. It operates on: - Share counts and lot records (internal state) - Options chain data (passed in from whatever data source the platform uses) - Fill confirmation (paper fills provided by the MBT paper-trading engine)

No brokerage vendor name appears in user-facing copy. The broker is plumbing. Raxx is the strategy layer.

For live trading (Phase 4, after paper validation): the paper-trading engine's fill confirmations are replaced by actual broker fill events. The strategy module itself does not change.


8. Regulatory Notes


9. Implementation Scope for v1 (Phase 1 + 2)

Phase 1 — Manual Paper Sim (minimal Raptor work): - Data schema (Postgres tables matching data-schema.md; includes OQ-1/OQ-3/OQ-5 schema changes) - State machine service (Python, deterministic, no ML) - Alert log table + basic alert surfacing in Antlers dashboard - AMZN single-ticker support only

Phase 2 — Chain Ingestion + Delta Filters: - Options chain ingestion from Alpaca options API - Delta-based strike selection (pull nearest strike in each zone's delta range) - Earnings calendar check (Alpaca corporate events) - Dashboard metrics (all 14, computed from ledger) - Early assignment educational card (OQ-2 full-screen 4-option flow)

Phase 3 — Recommendations + Alerts + Backtest: - Automated opening bell rule (condition classification, delay logic) - Full alert routing (push notifications for WARNING+; email for CRITICAL) - Roll-refusal operator notification card (OQ-1) - Uncovered-shares operator card (OQ-3) - Backtest runner (Python script, not real-time) - Walk-forward validation report

Phase 4 — Live Broker Integration: - After Phase 3 walk-forward passes - Alpaca live options order submission (or BYOB equivalent) - This phase is out of scope for the current research handoff


10. Key Behavioral Decisions (all locked 2026-06-05)

Decision Value
Max roll debit Per-instance config; default 50% of original credit (OQ-1)
Early assignment flow 4-option operator card; no autonomous action; state=EARLY_ASSIGNMENT_PENDING (OQ-2)
Shares-below-N behavior Auto-disable + push + email; 3-option operator card (OQ-3)
Sentiment staleness threshold 1 market day; High-Uncertainty fallback; strategy continues (OQ-4)
Tax-lot default FIFO; per-trade override at order ticket (OQ-5)

11. Dependencies

Dependency Required By Notes
Alpaca Market Data API Phase 1+ Daily OHLCV, corporate events
Alpaca Options API Phase 2+ Live options chain; verify options data tier
ORATS historical options Backtest only License required; do not use without confirmed subscription
MBT paper-trading engine Phase 2+ Fill simulation; see docs/architecture/mbt-paper-trading-engine.md
Postgres + TimescaleDB Phase 1+ Ledger storage; workflow UUID tracing per project_workflow_uuid_tracing_decisions.md
Push notification service Phase 2+ Required for EARLY_ASSIGNMENT_PENDING + SHARES_BELOW_MIN_THRESHOLD real-time alerts
Email delivery (Postmark) Phase 2+ Required for SHARES_BELOW_MIN_THRESHOLD email alert

This model card is a research handoff document. It does not constitute investment advice. The strategy described is a paper-trading simulation. Real-world outcomes will differ.