redditalpha logoredditalpha
← Back to dashboard
Share
151%
r/optionsr/options· u/saffystaffie· 5d ago 11

I used ChatGPT to backtest a SPY 0DTE strategy and Codex to build an automated IBKR bot

Investor summaryNeutral

Author shares a SPY 0DTE opening-range breakout strategy and an automated IBKR bot built with AI, seeking feedback before live testing.

Post body

Over the past few weeks I’ve been working on a mechanical SPY 0DTE opening-range breakout strategy.

I used ChatGPT to help develop the rules, analyse historical SPY data and backtest different variations. Once the rules were finalised, I used Codex to write a fully automated Python bot that connects to Interactive Brokers Trader Workstation through the official TWS API.

I’m planning to test it on a live account tomorrow. I’ll be using limited capital initially because this is the first real-world test and 0DTE options are obviously extremely risky.

This is not financial advice, and I’m not claiming the strategy is profitable. I’m sharing it to get feedback, especially on the automation, execution assumptions and any weaknesses in the rules.

What it trades

Underlying: SPY

Product: same-day-expiry SPY options

Bullish setup: buys calls

Bearish setup: buys puts

Maximum one setup per trading day

A setup can contain multiple contracts

Time settings

Everything runs in New York time.

Opening range: 09:30:00–10:29:59 ET

No new entry at or after 14:00 ET

Force-close all remaining contracts at 15:30 ET

No trading on weekends, US market holidays or early-close sessions

Opening range and breakout

The bot builds the opening range from the first 60 one-minute SPY candles.

It records:

Opening-range high

Opening-range low

Opening-range width

The triggers are:

Bullish trigger = opening-range high + $0.80

Bearish trigger = opening-range low − $0.80

Whichever trigger is touched first after 10:30 locks the direction for the day.

If the bullish trigger is touched first, the bot only considers calls.

If the bearish trigger is touched first, the bot only considers puts.

It will not reverse direction later.

Five-candle confirmation

The confirmation window consists of:

The one-minute candle where the trigger was first touched

The following four one-minute candles

For a bullish setup, at least one of those completed candles must close strictly above the bullish trigger.

For a bearish setup, at least one must close strictly below the bearish trigger.

A close exactly equal to the trigger does not count.

As soon as a candle confirms, the bot prepares the entry for the beginning of the next one-minute candle.

If none of the five candles confirms, there is no trade that day.

Option selection

The bot selects:

A SPY option expiring that same day

A call for a bullish setup

A put for a bearish setup

The strike numerically closest to the current live SPY price

Tie rule:

Call: choose the lower strike

Put: choose the higher strike

It does not select contracts using delta, implied volatility, volume, open interest or cheapest premium.

Quote requirements

Before entering, the bot requires:

Live SPY market data

Live option market data

Positive bid and ask

Ask greater than or equal to bid

SPY quote no older than two seconds

Option quote no older than three seconds

No delayed or frozen data

Spread calculation:

spread percentage = (ask - bid) / midpoint

The maximum permitted spread is 15% of the midpoint.

Position sizing

The strategy uses cash only.

Cash basis:

min(SettledCash, TotalCashValue)

It does not include:

Margin buying power

Existing stocks

Existing options

Unrealised profit

Net liquidation value

Borrowed funds

The maximum trade budget is:

20% of available eligible cash

The bot calculates affordability using:

Initial option ask

A maximum allowed entry price of initial ask × 1.10

The 100-share option multiplier

Estimated commissions and fees

It buys as many whole contracts as fit within the 20% cash limit.

There is no fixed maximum number of contracts.

Contract allocation

The allocation depends on the opening-range width.

If the opening range is below $4.50

No runner contracts are bought.

The allocation pattern repeats:

TP1 → TP2 → TP2

Examples:

1 contract: 1 TP1

2 contracts: 1 TP1, 1 TP2

3 contracts: 1 TP1, 2 TP2

6 contracts: 2 TP1, 4 TP2

If the opening range is $4.50 or more

The allocation pattern repeats:

TP1 → TP2 → TP2 → conditional runner

Examples:

4 contracts: 1 TP1, 2 TP2, 1 runner

8 contracts: 2 TP1, 4 TP2, 2 runners

12 contracts: 3 TP1, 6 TP2, 3 runners

A runner is never bought when the opening range is below $4.50.

Entry execution

The bot submits a marketable buy limit order.

Initial limit: current option ask

Reprice increment: $0.02

Reprice interval: every 0.50 seconds

Maximum entry attempt: three seconds

Maximum option price: 10% above the initial ask

Maximum favourable SPY chase: $0.25 beyond the buffered trigger

For calls, the unfilled entry is cancelled if SPY moves more than $0.25 above the bullish trigger.

For puts, it is cancelled if SPY moves more than $0.25 below the bearish trigger.

If the order partially fills:

Filled contracts are kept

The unfilled remainder is cancelled

The bot does not retry or top up later

Allocation is recalculated using the actual filled quantity

Once any entry order is transmitted, no second setup is allowed that day.

Profit targets

All targets are based on SPY’s movement from the buffered trigger, not on the option premium or fill price.

Long setup

TP1 = bullish trigger + $1.50

TP2 = bullish trigger + $2.00

TP5 = bullish trigger + $5.00

Short setup

TP1 = bearish trigger − $1.50

TP2 = bearish trigger − $2.00

TP5 = bearish trigger − $5.00

A target is triggered when a live SPY trade touches or passes the level. A candle close is not required.

Once triggered, the bot continues the option exit even if SPY reverses immediately.

Runner rules

Runner contracts only exist if the opening range is at least $4.50.

At TP2, the bot checks four conditions:

TP2 was reached within 30 minutes of the intended entry candle opening

SPY made at least a $1.50 favourable move within the first 30 minutes

Maximum adverse movement before TP2 was no more than $0.50

No completed one-minute candle closed back through the buffered trigger before TP2

The runner needs at least three of the four conditions to pass.

Score 3/4 or 4/4: hold all runners for TP5

Score below 3/4: sell all runners at TP2

Exit execution

The bot uses sell limit orders.

Initial exit limit: current option bid

Reprice downward by $0.02

Normal repricing interval: approximately one second

Forced-close repricing interval: approximately 0.50 seconds

Partial fills are tracked

Only the remaining quantity is resubmitted or modified

The bot never intentionally submits more sell contracts than are actually held.

End-of-day close

At 15:30 ET, the bot force-closes every remaining strategy contract.

This overrides:

TP1 allocation

TP2 allocation

Runner status

Pending target logic

The goal is to finish the day with zero remaining strategy contracts.

Stops

There is currently no early strategy stop.

The bot does not use:

SPY stop loss

Option-premium stop

Trailing stop

Breakeven stop

Percentage stop

Early time stop

The only exits are:

TP1

TP2

Runner rejection at TP2

TP5

Forced close at 15:30

I know this is one of the biggest risks in the system, and it is one of the things I’ll be watching closely during testing.

Bot safety and recovery

The bot also includes:

Correct live-account verification

Live-mode acknowledgement

Startup reconciliation

Persistent SQLite state

Duplicate-order protection

Unique order references

Position and execution reconciliation

Partial-fill handling

Reconnection handling

Unknown-position/order lockout

Stale-data checks

Forced-close protection

Notifications for entries, fills, targets, errors and disconnects

The system refuses to open a new trade if it detects an unknown SPY same-day option position or order.

Development process

I used ChatGPT to:

Help create the strategy

Analyse historical one-minute SPY data

Backtest the entry and target rules

Refine the runner criteria

Turn the strategy into a detailed coding specification

I then used Codex to build the Python automated trading bot for the Interactive Brokers TWS API.

Tomorrow will be the first test on a live account.

I’m starting cautiously because live fills, spreads, API behaviour and option pricing can differ substantially from a candle-based backtest.

I’d be interested in feedback on:

Whether the confirmation logic makes sense

The 20% cash allocation

The lack of an early stop

The runner qualification rules

The entry chase limits

Potential IBKR/TWS automation problems

Any look-ahead bias or backtesting errors I may have missed

Discussion · top comments12 selected
u/RationalBeliever 16· 5d ago

I highly suggest paper trading. You have so much complexity to your system that there is real risk of overfitting.

u/Shoggophant 10· 5d ago

How did it fare in backtesting, or on a paper account?

If you're trusting codex to write something without error and willing to put money on the line for a first test, I'd say you're gambling in more ways than one.

If the question is 'what do you think of these rules, will thia be profitable? ' the answer is perform backtesting.

That being said, way to vibe code, must have had a lot of work put in, sounds like you put a lot of work Into it.

Worst case scenerio you taught yourself a lot of stock trading mechanics details, which even if the program flops, will be useful some way or another.

u/SometimesWr0ng 5· 5d ago

This looks great, what could possibly go wrong. Try out on paper first, please.

u/saffystaffie 1· 1d ago

I listened to those that mentioned a stop loss, and I changed the strategy- i posted my new one. the first one didn't run, partly because of me not being able to leave my laptop running and partly due to the trades not filling the requirements. I also looked at QQQ as well, and made a similar strategy. have a look at my new post on here.

u/options-ModTeam 1· 4d ago

Removed for RULE: No spam, no cross-posts, no copy/paste of posts.

We incorporate the existing site-wide anti-spam rules explicitly. We consider cross-posting of all types and/or copy/pasting of posts as spam. Posts to this sub are expected to be unique and custom tailored to our community.

u/CODE_HEIST 1· 4d ago

Paper trade it first. The weak point is not that AI wrote code, it is that 0DTE plus IBKR automation gives tiny bugs real money consequences fast. Log every decision, order, fill, rejection, and skipped trade before letting it touch size.

u/ThetaEdgeHQ 1· 4d ago

The rules are the part everyone backtests and the part that matters least here. On a same day SPY breakout system your edge lives or dies on execution, and that is the one thing a historical bar backtest cannot see. You are almost certainly filling at the mid in the test. Live, you cross a bid ask that on 0DTE can be 10 to 20 percent of the premium, and an opening range breakout puts your entries in the widest spread window of the whole session. Round trip that on every signal and a system that shows positive expectancy on paper can sit underwater before the rules ever get a chance to work. Before you risk real capital, rerun it charging yourself the full spread plus a tick of slippage on every fill and see if the edge survives. If it only works at the mid, it does not work.

u/Miamiconnectionexo 1· 4d ago

this is genuinely helpful, not just the usual fluff. bookmarking this thread.

u/Worf_Of_Wall_St 1· 4d ago

You didn't explain your data source, but you should backtest whatever you come up with on historical tick by tick data to get any confidence on how it would perform on a live feed. You won't get the same result as backtesting on aggregated bars, and even tick data is not identical to what you would have received in real time because of data errors and latency.

u/Automate_The_Boring 1· 4d ago

Where did you get the data for option premium

u/Fauxial 1· 4d ago

Good luck, please post results of testing.

u/FURyannnn 1· 5d ago

For backtesting, it may be worth exploring the parameter set and seeing how various parameter changes (i.e. chosen range level plus +.90 instead of .80, etc) affect profit factor or PnL. A robust strategy exists when the hyperparameter changes but what you're optimizing (i.e. profit factor or PnL or whatever metric) is still roughly consistent and doesn't drastically change.

A good metaphor is a mountain range: if your strategy results in a continuous set of elevation across parameter changes, that's good. But if you have a few defined peaks of your metric and a set of valleys where a slight parameter change results in drastic performance changes, it's something to be more skeptical of