VWAP Strategy AI Trading Bot¶
This day trading bot uses VWAP, the volume-weighted average price. Big funds grade their own trades against VWAP, so it is a price level the whole market watches (Berkowitz, Logue and Noser, 1988). When SPY dips below VWAP and then climbs back above it, the bot buys the bounce with a tight stop and is out by the close.
How it works¶
Research agent checks SPY’s minute bars once an hour, starting at 10:00 ET. It reports VWAP, the last price, and whether SPY dipped at least 0.15% below VWAP and then closed back above it since the last check.
Trading agent buys when that bounce happens and the bot is not already in a trade. It puts the stop just under the dip’s low and sizes the trade so hitting the stop loses at most 1% of the account.
The trading agent sells at the next hourly check, and always before the close. It makes at most one new trade a day.
Run it on BotSpot¶
Run this bot on BotSpot without installing anything. BotSpot runs LumiBot in the cloud, backtests it, and connects it to your broker.
Backtest tear sheet¶
GPT-6 Luna, January 5 to 9, 2026, Alpaca minute prices checked hourly, $100,000 start. The bot made three SPY round trips on VWAP bounces and ended at $100,080 (+0.1%) while SPY rose 1%. When no bounce formed it stayed in cash.
Open the full tear sheet. A short backtest shows the bot works as written. It is not a promise of future returns.
The code¶
The whole bot is one short file. The prompts are plain English, and they are the strategy.
"""VWAP Strategy AI Trading Bot.
Day trades SPY around VWAP, the average price big funds watch all day. When SPY
dips below VWAP and then climbs back above it, the bot buys the bounce. A
research agent checks the price every hour. A trading agent sizes the trade from
a stop just under the dip and is out by the close.
"""
from lumibot.strategies import Strategy
class AIVWAPStrategy(Strategy):
parameters = {"symbol": "SPY"}
def initialize(self):
self.sleeptime = "1H"
self.agents.create(
name="researcher",
allow_trading=False,
system_prompt=(
"Compare the symbol's price today with its VWAP. Say whether, since the last hourly check, "
"the price dipped at least 0.15% below VWAP and then closed back above it, and how low the "
"dip went. Do not trade."
),
)
self.agents.create(
name="trader",
allow_trading=True,
system_prompt=(
"Day trade the symbol. If that bounce happened, we hold nothing, and we have not traded "
"today, buy. Put a stop just under the dip's low and size the trade so the stop loses at most "
"1% of the account. Sell at the next hourly check and always before the close."
),
)
def on_trading_iteration(self):
if self.get_datetime().hour < 10: # VWAP needs some of today's prices first
return
facts = {"symbol": self.parameters["symbol"]}
research = self.agents["researcher"].run(task_prompt="Check the VWAP setup.", context=facts)
self.agents["trader"].run(task_prompt="Trade the VWAP bounce.", context={**facts, "research": research.summary})
if __name__ == "__main__":
from lumibot.credentials import IS_BACKTESTING
if IS_BACKTESTING:
from lumibot.backtesting import AlpacaBacktesting
AIVWAPStrategy.backtest(AlpacaBacktesting)
else:
AIVWAPStrategy().run_live()
Run it yourself¶
pip install lumibot
python -m lumibot.example_strategies.ai_vwap
Put these in your .env file: OPENAI_API_KEY, and your broker keys (for example ALPACA_API_KEY, ALPACA_API_SECRET, and ALPACA_IS_PAPER=true for paper trading). With IS_BACKTESTING=false the bot trades. With IS_BACKTESTING=true it backtests instead; set BACKTESTING_START and BACKTESTING_END to pick the dates, and start with a week or two, because every AI call costs a little. Option and minute-bar backtests use Alpaca’s free history, so paper Alpaca keys are enough.
See AI Trading Bot Examples for more AI trading bots and Backtest, paper, or live: choose the runner for backtest and live runs.