Case Study · March 2026

Apex
Overlay

Building an AI-powered autonomous trading signal engine from scratch, going from a blank folder to live ES futures sessions in three weeks.

3 wks
Build Duration
80
Live Trades Tested
+$777
Net P&L · 7 Sessions
69.2%
Peak Win Rate
01

Overview

Apex Overlay is a real-time Windows desktop application that captures screenshots of two professional trading platforms simultaneously, sends them to a Google Gemini Vision AI model every 30 seconds, and automatically identifies and logs high-probability trade signals based on a proprietary liquidity pool strategy.

The system removes emotion from trade execution by replacing gut-feel decisions with a structured, rules-based AI signal engine. It was built entirely from scratch over three weeks through iterative AI-assisted development, going from a blank folder to a live-tested desktop application trading real ES JUN26 futures during New York pre-market hours.

The Problem
Professional futures traders using Bookmap and NinjaTrader must watch two complex platforms simultaneously, identify liquidity pool setups in real time, and execute without emotional interference. That requires sustained focus across a 4-hour window with inconsistent human results.
The Solution
An always-on-top transparent overlay that captures both trading screens, runs AI vision analysis on every scan, and fires structured signals only when conditions are met across multiple consecutive readings. It enforces discipline a human cannot sustain consistently.
02

Trading Strategy

The strategy is based on order flow analysis, specifically the behavior of resting limit orders (liquidity pools) visible on Bookmap's heatmap. Price in futures markets moves like a magnet toward areas of high resting order concentration. The AI reads both platforms and evaluates a structured decision tree on every 30-second scan.

▲ Long Entry Requirements
NinjaTrader 1M chart shows confirmed UPTREND: 3+ consecutive higher highs AND higher lows
Bookmap heatmap shows heaviest liquidity pools ABOVE current price
CVD (Cumulative Volume Delta) is positive or turning positive
At least one bullish confirmation candle on 1M (green, hammer, or bullish engulf)
Entry positioned near the bottom boundary pool, never mid-range
Trend and Bookmap bias must agree; any conflict outputs WATCH, not LONG
▼ Short Entry Requirements
NinjaTrader 1M chart shows confirmed DOWNTREND: 3+ consecutive lower highs AND lower lows
Bookmap heatmap shows heaviest liquidity pools BELOW current price
CVD is negative or turning negative
At least one bearish confirmation candle (red, shooting star, or bearish engulf)
Entry positioned near the top boundary pool during ranging conditions
Trend and Bookmap bias must agree; any conflict outputs WATCH, not SHORT

Pools above price during a downtrend are resistance ceilings, not bullish targets. Pools below price during an uptrend are support floors, not bearish targets. This directional pool context was the single most important logic fix applied during testing and produced the largest improvement in win rate.

03

System Architecture

Layer
Technology
Role
UI / Overlay
Python + PyQt6
Frameless transparent always-on-top window
Screen Capture
mss + Pillow
Captures calibrated Bookmap + NinjaTrader regions
AI Vision Engine
Google Gemini Vision
Reads heatmap, identifies signals, returns structured JSON
Signal Logic
Custom Python engine
Confirmation, memory buffer, tier system, pool tracking
Trade Manager
Python class
P&L tracking, win rate, equity curve, auto-exit
Key Storage
Windows Credential Manager
Secure API key management for end users
Calibration Tool
PyQt6 canvas
Visual drag-to-draw screen region setup
Safe Tier
Trigger2 consecutive 30s scans + trend + candle confirmation
Re-entryNever re-enters same pool
PurposeDisciplined capital protection
Aggressive Tier
Trigger3 consecutive scans with bias + trend count ≥ 3
Re-entryClears fired pools after stop-out
PurposeCaptures continuation moves
Component
Size
Purpose
signal_buffer
maxlen=5
Tracks recent signal readings for confirmation
bias_buffer
maxlen=5
Tracks Bookmap bias across scans
trend_buffer
maxlen=5
Tracks 1M trend across scans
fired_safe_pools
set
Permanent: SAFE never re-enters same pool
fired_aggressive_pools
set
Cleared on stop-out, so AGGRESSIVE can re-enter
04

Build Journey

Built incrementally through focused sessions, each solving a specific layer before moving to the next. The architecture, dual-tier system, memory buffer, and prompt engineering all emerged from live trading feedback rather than theoretical design.

01
Environment
Resolved Python 3.14 venv failures, pinned to 3.11.9, installed PyQt6, mss, Gemini SDK, Pillow
02
Overlay UI
Frameless PyQt6 window with 6 tabs, drag-to-move, resize grips, system tray, audible alerts
03
Screen Calibration
Visual drag-to-draw calibration tool capturing exact coordinates of each platform region
04
AI Engine
Full strategy encoded into Gemini prompt, structured JSON response, base64 image pipeline
05
Memory System
5-snapshot rolling buffer comparing current scan to prior readings, pool change detection
06
Dual-Tier System
SAFE and AGGRESSIVE tiers with independent confirmation logic and pool tracking sets
07
Auto-Execution
Auto-log on confirmed signal, auto-exit on price hit, bias flip, or reversal alert
08
Live Testing
7 sessions of real ES JUN26 futures with iterative prompt and logic refinement
05

Pain Points and Solutions

Problem
Impact
Solution
Python 3.14 venv broken
Could not create virtual environment
Pinned to 3.11.9, used --without-pip, bootstrapped manually
mss crashes in QThread
Screen capture failed every scan
Moved capture to main thread, passed images to worker
Single-frame AI noise
Signal flip every 60 seconds
5-snapshot memory buffer requiring 2 consecutive confirming reads
LONGs during downtrend
-$418 session loss
Hard rule: trend + bias must agree or output WATCH
Stops too tight for ES
Stops swept before target
2-point buffer beyond pool, AGGRESSIVE re-entry after stop-out
Opposite direction trades
LONG + SHORT simultaneously
Open direction check so the opposite cannot fire if position open
Wrong target direction
SHORT target above entry
Added _validate_target() checking direction before logging
30s scan delay
Exits logged past actual stop/target
MCP integration planned for direct NinjaTrader execution
06

Testing Results

Seven live sessions on ES JUN26 futures during New York pre-market and morning hours (4:00 AM to 12:00 PM EST). All P&L figures corrected for the 30-second scan delay where verified trade targets were hit but logged exit was delayed.

Session
Trades
Win Rate
P&L
Key Event
Mon Mar 23
8
50.0%
+$275.00
Prompt fix applied mid-session
Tue Mar 24
26
69.2%
+$1,350.01
Best session, both tiers at 69.2%
Wed Mar 25
18
41.2%
-$418.77
Pre-fix LONGs during downtrend
Thu Mar 26
8
37.5%
-$62.50
30s delay causing late exits
Fri Mar 27
10
20.0%
-$481.24
Stops swept, 2pt buffer fix applied
Mon Mar 30
6
66.7%
+$411.26
All targets hit, delay corrected
Tue Mar 31
4
0.0%
-$296.89
LONGs mid-range, range fix applied
Total
80
~48%
+$777.87
Net positive, losses from identifiable bugs

Tuesday March 24, the cleanest session with 26 trades at 69.2% win rate and +$1,350 P&L, proves the strategy and system work when logic is correct. Every dollar lost across all sessions is directly traceable to a specific, identified, and subsequently fixed bug. The losses were execution layer problems, not strategy problems.

07

Prompt Engineering Evolution

The Gemini vision prompt evolved significantly across the testing period. Each session revealed a specific gap in the AI's understanding of the strategy, corrected with explicit rules. The prompt went from 12 JSON output fields to 17, and from no absolute rules to 11.

Version
Key Addition
Impact
V1 Original
Basic pool detection, signal output
No trend check, so LONGs fired during downtrends
V2 Trend Gate
Trend must match bias before any signal fires
Win rate: 41% to 69.2% in next session
V3 Absolute Rules
11 hard rules including target/stop direction validation
Blocked wrong-direction targets and stops
V4 Trend Stability
2 consecutive CONSOLIDATION required before accepting
Stopped premature exits from single bad scans
V5 Range + CVD
Range detection, CVD alignment gate, boundary entry rule
Blocked mid-range entries during consolidation sessions
08

Roadmap

Immediate
Trade persistence database (SQLite): 10 prior scans saved per trade
Price reading accuracy fix, since Gemini occasionally misreads price level from screen
Re-enable 4AM to 12PM EST time filter after testing phase
Commercial Release
Windows installer packaging (.exe) for end-user distribution
First-launch API key setup and user onboarding
Gumroad product listing and pricing strategy
User documentation and screen calibration guide
NinjaTrader MCP Integration
MCP server exposing NinjaTrader as callable tools: place_order, close_position, get_account_info
Fully autonomous execution closing the 30-second scan delay entirely
Long-term: MiroFish swarm intelligence integration for self-improving signal quality
09

Key Learnings

AI Vision for Finance
Vision models can read complex financial charts with high accuracy when the prompt is sufficiently specific. Single-frame reads are unreliable, so a memory buffer requiring multi-scan confirmation is essential. The most common failure mode is the AI correctly identifying a bias but misreading the directional implication.
Iterative Product Dev
Every loss in testing was traceable to a specific fixable bug, and the strategy was sound from session one. Live testing feedback is irreplaceable. Issues that seemed theoretical became immediately visible with real P&L. Prompt engineering is a real engineering discipline requiring careful failure mode analysis.
Architecture
Threading model matters: mss screen capture cannot run in a QThread due to Windows GDI device context constraints. Modularity was the right call, so separating capture, engine, trade manager, and UI made each component independently testable. The MCP roadmap maps cleanly to a standardized tool server pattern.