AI-Only Iron Condor¶
ai_iron_condor.py is a minimal AI-only options strategy. Python creates one
trading agent in initialize() and runs it in on_trading_iteration().
The agent owns market retrieval, contract selection, sizing, four-leg order
construction, submission, verification, and position management.
The system prompt contains only the strategy policy: underlying, delta, DTE,
wing width, exits, and risk limits. Reusable options mechanics are supplied by
LumiBot’s built-in options-trading skill. Active rules.json entries are
loaded again before every agent call and appended to the runtime instructions.
The example uses gemini-3.5-flash-lite explicitly. Existing saved
strategies keep the model identifier already stored in their code.
How it works¶
The agent loads the built-in options skill when options become relevant.
It reads the account, underlying, chain, exact contracts, Greeks, and quotes.
It prices and submits all four legs as one atomic multi-leg package.
It verifies the returned order and current signed positions before reporting state.
Verified backtest evidence¶
The preserved 2026-08-05_00-33_9dcawc seven-day backtest opened one atomic
SPY iron condor with the 685/690 put spread and 771/776 call spread, all using a
single 2026-09-04 expiration. The backtest ended near flat with a -0.00% rounded
total return and a -0.08% maximum drawdown. This short window proves mechanics,
not expected performance.
The refactored strategy was also rerun over two current seven-day windows. The active downloader reported no historical option chain, so the agent correctly made no trade instead of inventing contracts. The release-gated real-model eval provides a chain fixture and separately verifies chain retrieval, four valid legs, explicit package pricing, one atomic submission, and post-submit state verification.
Run a seven-day backtest ending today with an options-capable backtest data source:
export GEMINI_API_KEY="your-key"
export BACKTESTING_DATA_SOURCE="ThetaData"
export DATADOWNLOADER_BASE_URL="https://<your-downloader-host>:8080"
export DATADOWNLOADER_API_KEY="your-downloader-key"
python -m lumibot.example_strategies.ai_iron_condor
Set BACKTESTING_START and BACKTESTING_END in YYYY-MM-DD format to
choose an exact historical window.
1"""AI-only iron-condor strategy driven entirely by a LumiBot agent."""
2
3import os
4from datetime import datetime, timedelta
5from pathlib import Path
6
7from lumibot.strategies.strategy import Strategy
8
9
10def build_iron_condor_system_prompt(params: dict) -> str:
11 underlying = str(params.get("underlying", "SPY")).upper()
12 return f"""
13You are the complete decision-maker for an AI-only {underlying} iron-condor
14strategy. Use the LumiBot options skill for all option mechanics and execution.
15
16Strategy policy:
17- Trade only {underlying} iron condors with one shared expiration.
18- Prefer {params['preferred_dte']} DTE, require {params['min_dte']} to
19 {params['max_dte']} DTE.
20- Select short puts near -{params['target_delta']} delta and short calls near
21 +{params['target_delta']} delta. Verified absolute short delta must be within
22 {params['delta_band']} of the target.
23- Wings must be exactly {params['wing_width']} points beyond the short strikes.
24- Require a net credit and liquid markets for every exact leg.
25- Risk no more than {params['max_risk_pct']:.2%} of portfolio value and never
26 exceed {params['max_contracts']} contracts.
27- Hold at most one {underlying} option structure. Manage existing exposure before
28 considering a new entry.
29- Close when {params['profit_take_fraction']:.0%} of opening credit is captured,
30 closing debit reaches {params['loss_multiple']} times opening credit, DTE is
31 {params['time_stop_dte']} or less, the underlying breaches a short strike, or
32 either short option reaches 0.30 absolute delta.
33- Use a no-trade decision whenever current evidence cannot prove every condition.
34
35You own research, contract selection, sizing, order construction, submission,
36verification, and position management. Python contains no trading decisions.
37""".strip()
38
39
40class AIIronCondorStrategy(Strategy):
41 parameters = {
42 "underlying": "SPY",
43 "wing_width": 5.0,
44 "target_delta": 0.16,
45 "delta_band": 0.04,
46 "min_dte": 30,
47 "max_dte": 45,
48 "preferred_dte": 35,
49 "profit_take_fraction": 0.50,
50 "loss_multiple": 2.0,
51 "time_stop_dte": 21,
52 "max_risk_pct": 0.02,
53 "max_contracts": 10,
54 }
55
56 def initialize(self):
57 self.sleeptime = "1D"
58 self.agents.create(
59 name="iron_condor",
60 model="gemini-3.5-flash-lite",
61 allow_trading=True,
62 system_prompt=build_iron_condor_system_prompt(self.parameters),
63 rules_path=Path(__file__).with_name("agent_rules") / "ai_iron_condor.rules.json",
64 )
65
66 def on_trading_iteration(self):
67 self.agents["iron_condor"].run(
68 task_prompt="Run the complete iron-condor workflow for this iteration.",
69 context={
70 "current_datetime": self.get_datetime().isoformat(),
71 "strategy_parameters": dict(self.parameters),
72 },
73 )
74
75
76def _parameters_from_env(defaults: dict) -> dict:
77 params = dict(defaults)
78 float_keys = ("wing_width", "target_delta", "delta_band", "profit_take_fraction", "loss_multiple", "max_risk_pct")
79 int_keys = ("min_dte", "max_dte", "preferred_dte", "time_stop_dte", "max_contracts")
80 if os.environ.get("AI_IC_UNDERLYING"):
81 params["underlying"] = os.environ["AI_IC_UNDERLYING"].strip().upper()
82 for key in float_keys:
83 if os.environ.get(f"AI_IC_{key.upper()}"):
84 params[key] = float(os.environ[f"AI_IC_{key.upper()}"])
85 for key in int_keys:
86 if os.environ.get(f"AI_IC_{key.upper()}"):
87 params[key] = int(os.environ[f"AI_IC_{key.upper()}"])
88 return params
89
90
91if __name__ == "__main__":
92 backtesting_end = datetime.fromisoformat(os.environ.get("BACKTESTING_END", datetime.now().date().isoformat()))
93 backtesting_start = datetime.fromisoformat(os.environ.get("BACKTESTING_START", (backtesting_end - timedelta(days=7)).date().isoformat()))
94 AIIronCondorStrategy.backtest(None, backtesting_start=backtesting_start, backtesting_end=backtesting_end, benchmark_asset="SPY", budget=100_000, parameters=_parameters_from_env(AIIronCondorStrategy.parameters))