I Built a Trading Bot That Doesn't Just Calculate — It Sees, Remembers, and Learns from Its Failures
The complete 7-month engineering journey of an open-source, vision-capable crypto bot.
1. The Wrocław Warehouse Spark
In December 2025, I was living in Wrocław, Poland. By day, I worked 8-hour shifts in a physical warehouse. My back was sore, my energy depleted, but my mind was occupied with a single question: Why are all the "AI trading bots" on the market so incredibly dumb?
I spent my evenings testing open-source strategy templates. I did what every YouTube tutorial recommended: pulled RSI, MACD, and Bollinger Bands values via Python, wrote a basic prompt template, and dumped the floats into the ChatGPT API.
The bot's decisions were confident, articulate, and completely wrong. It would say: "RSI is at 28, oversold. BUY." The next morning, the market would slide another 4.5%, dragging my paper portfolio down with it.
The problem wasn't the AI model. The problem was the architecture. I was building a stateless calculator, not a reasoning engine.
2. Chronological Timeline (Dec 2025 – Jul 2026)
Phase 1: Float Prompts (Dec 2025 – Jan 2026)
Calculated indicators in Python and dumped them as YAML text into Claude/Gemini. The bot was stateless, forgot past trades, and bled capital (-4.2%).
Phase 2: Multimodal Chart Vision (Feb – Mar 2026)
Scrapped 900 lines of hardcoded pattern-matching heuristics. Plotly now renders a 1080p chart image (SMA, RSI, Volume, CMF, OBV) fed directly to Gemini Flash. The visual model spots pattern geometry far better than programmatic rules.
Phase 3: Stateful Vector Memory (Apr – May 2026)
Integrated local SQLite and ChromaDB (768D BAAI/bge-base-en-v1.5 embeddings). Every closed trade is embedded. The bot queries top-5 similar past setups. Introduced the Surprise Ratio metric to filter out market noise.
Phase 4: EV & Falsification Gates (Jun 2026)
Added deterministic Expected Value math (Kelly sizing, min 1.5 R:R threshold) and the Falsification Gate (forcing the LLM to write a strict price invalidation trigger before any trade is executed).
Phase 5: 8-Agent Dev System (Mid-Jul 2026)
Built a local multi-agent system (.ai/ directory). A Supervisor orchestrates 7 specialized developer agents (Bolt, Palette, Sentinel, Refactor, Concise, Bugfixer, Smoke Tests) to maintain the codebase.
Phase 6: Hardened Executor Separation (Late-Jul 2026)
Decoupled the engine into Semantic Signal (reasoning) and llm_trader_executor (CCXT order placement, leverage, OCO stop-losses, and dead-letter queue).
3. The Mathematics & Engineering
Numba JIT Indicator Engine
50+ custom technical indicators written in NumPy and Numba. Every calculation compiles to machine code on first call and caches the result, running in microseconds on a standard CPU:
@njit(cache=True)
def _ema_numba(prices: np.ndarray, period: int) -> np.ndarray:
alpha = 2.0 / (period + 1)
result = np.empty_like(prices)
result[0] = prices[0]
for i in range(1, len(prices)):
result[i] = alpha * prices[i] + (1 - alpha) * result[i - 1]
return resultThe Surprise Ratio Metric
To prevent the bot from learning bad habits from lucky trades (e.g. buying a support breach that won due to random news spikes):
Trades with a surprise ratio > 1.5 carry a ⚠️ high surprise tag in vector memory so the LLM discounts them in future cycles.
Deterministic Expected Value Gate
If EV is negative or Risk-to-Reward ratio is under 1.5, the signal is rejected outright, overriding the LLM.
4. Quick Start
git clone https://github.com/qrak/LLM_trader.git && cd LLM_trader
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp keys.env.example keys.env # Add GOOGLE_STUDIO_API_KEY (free tier works)
python start.py # Dashboard launches at http://localhost:8000