Strategy ID: lcc-income-cycle
Version: 0.1 (research)
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.
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)"
}
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)
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)"
}
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"
}
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"]
}
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.
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)"
}
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 |