Rules Decide, LLMs Advise
When people hear I built a trading bot that uses LLMs, they always ask the same question: "so the AI decides what to buy?"
The question everyone asks about my trading bot
When people hear I built a trading bot that uses LLMs, they always ask the same question: "so the AI decides what to buy?"
No. And the reason is the most important architecture decision in the whole project.
In my bot, the AI never touches money. Not once, not indirectly, not through a clever loophole. Every trade is decided by boring, deterministic math, and executed inside hard limits the model cannot override. The LLM's job is to explain, to score its own confidence, and, in exactly one place, to say "wait".
This post is about why that split exists, how it is enforced structurally, and the one exception I allowed after a lot of thought.
The two brains
My bot has two brains, and they are not equals.
The rule engine is the decider. It reads daily candles, computes indicators (RSI, MACD, moving averages, volume), and looks for confluence: multiple independent signals agreeing. Out of that comes a verdict per instrument: buy candidate, hold, watch, or exit. This brain is deterministic. Same inputs, same verdict, every time. I can test it, replay it, and audit any decision it ever made.
The LLM is the narrator. After the verdicts exist, one batched call sends the rule engine's own output (verdicts, reason codes, scored news evidence) to a language model, which writes a short plain-English comment per ticker and a confidence score. That commentary is for me, the human reading the daily digest. It changes nothing.

Why not let the model trade?
Because I can list what the rule engine will do in every market condition, and I cannot list what a language model will do in any of them.
A trading system's worst failures are not wrong predictions. They are unbounded behaviors: revenge-trading a loss, averaging down into a collapse, position sizes that creep. My rails make those failures structurally impossible: order caps, daily spend caps, per-position percentage caps, a fee budget, and compliance gates enforced in three places (where an order is drafted, where it is checked, and in the database itself). A model with direct market access would put all of those behind a probability distribution. No thank you.
There is also a discipline benefit nobody talks about: when the LLM is only a narrator, a bad model is a bad paragraph, not a bad trade. I can swap models, compare them, even run several in parallel and grade them, all without risking a cent. The blast radius of AI failure in this system is a typo.
The one exception: the devil's advocate
After months of running, I added exactly one path where an LLM can influence execution, and it is deliberately one-directional.
Before the bot places an automatic buy that has already passed every deterministic rail, one extra LLM call plays risk officer. The prompt asks for the single strongest concrete case AGAINST the trade, then a decision: confirm or veto. A veto does not delete the trade. It downgrades it to an advisory: a message that tells me what the bot wanted to do and why the reviewer objected, leaving the final call to my human hands.
The critical design property: fail-open. If the reviewer is disabled, over budget, times out, or returns something unparseable, the trade proceeds as the rules decided. The gate can only ever PREVENT a trade, never cause one, and its failure mode is "no gate", never "no trades".

So the AI in my system holds a brake pedal it can tap once, on one specific corner, with a written justification. It does not hold the steering wheel and it cannot reach the accelerator.
What this looks like day to day
Every market close, the pipeline runs: math produces verdicts, the narrator writes its commentary, the executor acts inside the rails, and a digest lands on my phone. When the devil's advocate vetoes something, I see exactly what would have happened and why it was stopped, and I can overrule it by hand if I disagree.
The bot is fully automated and I am fully informed. Neither of us is guessing.
The principle, portable to any AI system
This is not really a trading lesson. It is an AI systems lesson:
Give deterministic code the authority, give the model the microphone, and if the model must touch a decision, make it fail-open and one-directional.
Every place I have applied that split, the system got safer AND more useful, because I could trust the automation enough to leave it alone.
Pictures to add later
- The daily Telegram digest (redact amounts if preferred)
- Bot dashboard overview
- A real veto advisory message, when one happens