We taught an AI to roll options positions. Here is how we made sure it never rolls for a debit.
AutoQuant's Strategy Chat can turn a plain-English wheel description into a real backtest, and now that backtest can roll challenged puts. The hard part was not writing the roll code. It was making sure a strategy that promises credit-only rolls cannot secretly take a debit.
You can now describe a wheel strategy to AutoQuant in plain English, tell it to roll challenged puts to the next cycle for a credit and never a debit, and get back a real backtest that actually enforces that promise. This post is about the part that took real engineering: making sure “credit only” is not just something the AI says, it’s something the engine refuses to violate.
The problem with asking an AI to promise a credit
An LLM can write code that claims to only roll for a credit. It can even add a field called credit_only: true right there in the JSON. None of that makes it true. The model can misjudge the math, skip the check under a refinement, or just be wrong about a strike selection, and the generated code would run fine and lie to you the whole time.
So the same rule we use everywhere else in AutoQuant applies here. It’s the same split we landed on for the daily trade ideas feed, where the model picks the setup and deterministic code picks the real strike. The AI proposes the strategy. It does not get to grade its own homework.
The LLM writes the trade logic. The engine enforces the guarantee.
How a roll actually works
A roll is really two trades pretending to be one: close the position you have, open the position you want, same day. Our options backtester already knew how to open and close positions. What it didn’t have was a way to treat those two trades as a single atomic decision with a rule attached to the combination.
We added a roll action to the strategy sandbox. When a strategy emits one, the engine finds the existing position, prices what it would cost to close it today, prices what the replacement legs would collect or cost to open, and adds the two together.
roll_credit = old_position_close_value + new_position_open_cash
If credit_only is set on the roll and that number comes out negative, the roll is rejected outright. Not flagged, not logged as a warning. It does not happen. The position stays exactly as it was, and the strategy has to wait for a bar where the roll is actually a credit.
That check lives in the backtest engine, not in the generated Python. A strategy cannot argue its way around it, because it never gets the chance to run the math itself.
What “Build with AI” actually produced for a real wheel
Here is the request that started this, typed into the chat exactly like this: wheel strategy on SPY, roll challenged puts to the next cycle, always for a credit, never a debit.
The interview came back before any code did. What counts as challenged, SPY closing below the short strike, or something else? What counts as the next cycle? Any exit rules for the rolled position? Real answers went in: challenged means SPY closes below the short put strike, roll to the next monthly expiration 30 to 45 days out, sell the 30 delta put, 50% profit target, 200% stop loss, close at 21 days to expiration.
The first draft that came back was honest about what it could and could not model. It flagged that the backtester settles in-the-money shorts to cash rather than assigning real shares, so the covered-call half of a full wheel is not modeled yet. But it was explicit that rolling a challenged put to avoid assignment, the actual feature this post is about, is modeled and safe to test.
The bug that proved the design
That first draft only knew how to roll a put it already held. It never opened one in the first place. Point it at an empty account and it would sit there forever, checking positions that did not exist, never placing a trade.
That’s a real gap, and it’s the kind of thing that’s easy to miss reading generated code casually, because the roll logic looked completely correct in isolation. One more turn in the chat, asking it to also sell a new cash-secured put under the same terms whenever the account was flat, and the second draft opened positions correctly and rolled them correctly. The same regenerate-and-recheck loop that catches lookahead bias and syntax errors elsewhere in Strategy Chat caught a missing entry condition here too.
The proof
The finished strategy backtested on SPY from January through July: 6.7% return, a 1.29 Sharpe, a 5.6% max drawdown, 64% of trades closed as winners, 25 total trades, $2.14 in average theta captured per day held.
The trade log is where the credit-only guarantee actually shows up. Roll after roll closes and reopens on the same date, exactly the atomic behavior the engine is supposed to enforce: a position exits on 2026-01-22 with reason roll, and the very next row opens that same day. Same pattern on 2026-02-25, 2026-03-02, 2026-03-03, 2026-03-17. Every one of those pairs passed the credit check before the engine let it happen. Any roll that would have taken a debit simply never appears in the log, because it was never allowed to execute.
What you get
Strategy Chat now handles this end to end for both stocks and options: describe a strategy, get interviewed until the rules are unambiguous, get a real sandboxed backtest before anything is saved to your library. Rolling with a credit-only gate ships in v0.9.14. Real share assignment, the other half of a full wheel, is next.
AutoQuant v0.9.14 is live now at autoquant.ai/download.
Subscribe to the AutoQuant blog
One post every Friday. Backtest thinking, options mechanics, and AI-assisted strategy discovery. No spam.