Raxx · internal docs

internal · gated ↑ index

LCC Income Cycle — Data Schema

Strategy ID: lcc-income-cycle Version: 0.1 (research)


1. EquityLot

Represents a single tax lot of shares. Multiple lots exist per position when shares are purchased at different times/prices.

{
  "lot_id": "string (uuid4)",
  "ticker": "string",
  "acquired_date": "string (ISO 8601 date)",
  "acquired_price": "number (USD per share)",
  "shares": "integer (positive)",
  "lot_method_tag": "string (LIFO | FIFO | HighCost | LowCost | SpecificID)",
  "status": "string (open | assigned | sold)"
}

Constraints: - shares must be a positive integer. - lot_method_tag on each lot does not mean that method is active — the active method is on the Position record. This tag supports SpecificID targeting.


2. Position

Aggregates all lots for a single ticker in the simulation.

{
  "position_id": "string (uuid4)",
  "ticker": "string",
  "total_shares": "integer",
  "lots": ["array of lot_id strings"],
  "avg_cost_basis": "number (USD per share, weighted average of open lots)",
  "active_lot_method": "string (LIFO | FIFO | HighCost | LowCost | SpecificID)",
  "state": "string (NO_POSITION | LONG_SHARES | CC_ACTIVE | NEAR_EXPIRATION | ASSIGNED)",
  "last_updated": "string (ISO 8601 datetime UTC)"
}

3. ShortCall

Represents a single short covered call contract.

{
  "call_id": "string (uuid4)",
  "position_id": "string (fk → Position)",
  "lot_id_covered": "string (fk → EquityLot, nullable if uncovered tracking enabled)",
  "ticker": "string",
  "strike": "number (USD)",
  "expiration_date": "string (ISO 8601 date)",
  "dte_at_entry": "integer",
  "delta_at_entry": "number (0.0 – 1.0)",
  "zone": "string (ITM | ATM | OTM)",
  "sentiment_label": "string (Neutral | Bullish | Bearish | HighUncertainty)",
  "premium_received": "number (USD per share, i.e. credit × 100 = contract value)",
  "premium_received_gross": "number (USD, = premium_received × 100)",
  "commission_paid": "number (USD)",
  "entry_datetime": "string (ISO 8601 datetime UTC)",
  "entry_underlying_price": "number (USD)",
  "exit_datetime": "string (ISO 8601 datetime UTC, nullable)",
  "exit_price": "number (USD per share, nullable)",
  "exit_reason": "string (expired_worthless | bought_back | assigned | rolled_to)",
  "rolled_to_call_id": "string (fk → ShortCall, nullable)",
  "pnl_option": "number (USD, positive = profit, set at close)"
}

Zone assignment logic (at entry): - delta_at_entry ≥ 0.60 → ITM - delta_at_entry 0.45–0.59 → ATM - delta_at_entry 0.25–0.44 → OTM - delta_at_entry < 0.25 → OTM (flag as far-OTM)


4. AssignmentEvent

Created when a ShortCall results in assignment.

{
  "assignment_id": "string (uuid4)",
  "call_id": "string (fk → ShortCall)",
  "position_id": "string (fk → Position)",
  "lot_ids_assigned": ["array of lot_id strings"],
  "shares_assigned": "integer",
  "assignment_price": "number (USD per share, = strike)",
  "assignment_datetime": "string (ISO 8601 datetime UTC)",
  "lot_cost_basis": "number (USD per share, weighted avg of assigned lots)",
  "stock_pnl": "number (USD, = (assignment_price - lot_cost_basis) × shares_assigned)",
  "early_assignment_flag": "boolean",
  "early_assignment_reason": "string (ex_div | deep_itm_extrinsic | null)"
}

5. Cycle

Groups all events belonging to one income cycle: one buy-in → one call layer → resolution → optional re-entry.

{
  "cycle_id": "string (uuid4)",
  "position_id": "string (fk → Position)",
  "ticker": "string",
  "cycle_start_date": "string (ISO 8601 date)",
  "cycle_end_date": "string (ISO 8601 date, nullable while active)",
  "shares_at_start": "integer",
  "call_ids": ["array of call_id strings"],
  "assignment_ids": ["array of assignment_id strings"],
  "total_premium_gross": "number (USD)",
  "total_commission": "number (USD)",
  "total_stock_pnl": "number (USD)",
  "net_cycle_pnl": "number (USD, = total_premium_gross - total_commission + total_stock_pnl)",
  "uncovered_shares": "integer (shares held with no corresponding short call)",
  "sentiment_label": "string",
  "market_condition_at_open": "string (flat | gap_up | gap_down | gap_down_severe)",
  "opening_sell_timing_minutes": "integer (minutes after open that sells were executed)",
  "notes": "string"
}

6. ReentryDecision

Logs the re-entry evaluation after each assignment or NO_POSITION state.

{
  "decision_id": "string (uuid4)",
  "cycle_id": "string (fk → Cycle)",
  "evaluation_datetime": "string (ISO 8601 datetime UTC)",
  "ticker": "string",
  "current_price": "number",
  "criteria_results": {
    "ticker_approved": "boolean",
    "price_not_extended": "boolean",
    "premium_justifies_cycle": "boolean",
    "no_concentration_breach": "boolean",
    "no_binary_event": "boolean",
    "not_chasing": "boolean"
  },
  "all_criteria_passed": "boolean",
  "decision": "string (reenter | wait)",
  "blocked_by": ["array of criterion name strings, empty if all passed"]
}

7. Alert

Operational log of every risk-control alert fired during simulation.

{
  "alert_id": "string (uuid4)",
  "cycle_id": "string (fk → Cycle, nullable)",
  "call_id": "string (fk → ShortCall, nullable)",
  "alert_code": "string (see Alert Spec)",
  "severity": "string (info | warning | critical)",
  "fired_at": "string (ISO 8601 datetime UTC)",
  "message": "string",
  "acknowledged": "boolean",
  "acknowledged_at": "string (ISO 8601 datetime UTC, nullable)"
}

Alert codes: See alert-spec.md in this strategy directory.


8. SimulationConfig

Captures the parameters for a given paper-trading simulation run. Enables reproducibility.

{
  "config_id": "string (uuid4)",
  "run_date": "string (ISO 8601 datetime UTC)",
  "tickers": ["array of strings"],
  "max_shares_per_ticker": "integer",
  "default_lot_method": "string (LIFO | FIFO | HighCost | LowCost)",
  "naked_calls_enabled": "boolean (always false for paper v1)",
  "commission_per_contract": "number (USD)",
  "fill_model": "string (mid | bid | ask | nbbo_sim)",
  "gap_up_threshold_pct": "number (default 0.005)",
  "gap_down_threshold_pct": "number (default 0.005)",
  "gap_down_severe_threshold_pct": "number (default 0.015)",
  "min_premium_pct_of_price": "number (default 0.003, i.e. 0.3%)",
  "max_roll_debit": "number (USD per share, default 0.25)",
  "buyback_pct_captured": "number (default 0.80, i.e. buy back when 80% of credit captured)",
  "extrinsic_iv_crush_threshold_pct": "number (default 0.50)",
  "high_assignment_risk_extrinsic_threshold": "number (USD, default 0.15)",
  "re_entry_price_extension_multiplier": "number (default 1.5)"
}

9. Backtest Run Artifact Manifest

Every backtest run produces the following files under docs/data-science/backtests/lcc-income-cycle/<YYYY-MM-DD-run-id>/:

File Description
config.json SimulationConfig snapshot for this run
trades.csv One row per ShortCall, including all fields
lots.csv One row per EquityLot lifecycle event
cycles.csv One row per Cycle
assignments.csv One row per AssignmentEvent
alerts.csv All alerts fired
equity_curve.csv Daily portfolio value (stock mark-to-market + cum premium)
equity_curve.png Equity curve chart (matplotlib)
summary.json Aggregate metrics (see Dashboard Metric List)
git_sha.txt Git commit hash at time of run