English | 中文 | हिंदी | Español | Français | العربية | বাংলা | Русский | Português | Bahasa Indonesia
An expert decision-support system for NASDAQ and Oil (WTI) ETF trading, leveraging an 11-model hybrid artificial intelligence for robust and nuanced trading signals.
This project is an expert decision-support system for ETF trading, using an 11-model hybrid AI approach. It is designed to provide a comprehensive and robust analysis by combining several AI perspectives.
The system uses an innovative approach to maximize model accuracy:
- High-Fidelity Analysis: AI models analyze global reference indices (
^NDXfor Nasdaq,CL=Ffor WTI Crude Oil). These indices offer longer history and "purer" trends, without the noise related to trading hours or ETF fees. - ETF Execution: Real orders are placed on the corresponding tickers on Trading 212 (
SXRV.DE,CRUDP.PA), using T212 live prices (via positions API) for position sizing. Portfolio state is synchronized directly from T212 (sync_state_from_t212()), and live prices are injected into the analysis pipeline (_inject_t212_live_price()insrc/data.py).
The system merges eleven distinct signals (plus a meta-model):
- Classic Quantitative Model: RandomForest/GradientBoosting/LogisticRegression ensemble trained on technical and macroeconomic indicators.
- TimesFM 2.5 (Google Research): State-of-the-art foundation model for time-series forecasting.
- TensorTrade / PPO (Reinforcement Learning): RL agent (stable-baselines3) training a PPO policy in a custom Gymnasium trading environment with persistence across cycles.
- Oil-Bench Model (Gemma 4 12B (Unsloth)): Energy-specialized model merging EIA fundamental data (Stocks, Imports, Refinery utilization) and sentiment for WTI trading.
- Textual LLM (Gemma 4 12B (Unsloth)): Contextual analysis of raw data, real-time news via the AlphaEar skill, and integration of dynamic macro-economic web research. It explicitly consumes the overnight Morning Brief report to gain deep fundamental awareness before making decisions.
- Visual LLM (Gemma 4 12B (Unsloth)): Direct analysis of technical charts (
enhanced_trading_chart.png). - Sentiment Analysis: Hybrid analysis combining Alpha Vantage and "hot" trends from AlphaEar (Weibo, WallstreetCN).
- Decentralized Data (Hyperliquid): Analysis of speculative sentiment on Oil (WTI) via Funding Rate and Open Interest.
- Vincent Ganne Model: Geopolitical and cross-asset analysis (WTI, Brent, Gas, DXY, MA200) for detecting macroeconomic bottoms.
- Grebenkov Model: Trend-Following mathematical model calibrated for cross-asset analysis using Agnostic Risk Parity.
- Hidden Markov Model (HMM): Probabilistic model for market regime detection (bullish/bearish) based on historical price variations.
- Hybrid Fusion Engine: The meta-model orchestrating dynamic weighting and cognitive consensus across all sub-models.
The goal is to produce a final decision (BUY, SELL, HOLD) with an absolute priority on Accuracy First.
Unlike classic trading algorithms that panic as soon as volatility explodes, this system applies an informed investor approach:
- Strong Consensus Required: A quantitative model (Classic) may cry wolf (
SELL), but if cognitive models (Text LLM, Vision, TimesFM) remain neutral, the system will preferHOLD. - Confidence Filter: A movement decision (Buy or Sell) is only validated if the global confidence exceeds a safety threshold (generally 40%). Below this, the system considers the signal as "noise" and remains on standby.
- Capital Protection: In
VERY_HIGHrisk mode,HOLDserves as a shield. It prevents entering an unstable market and avoids exiting prematurely on a simple technical correction if fundamentals (News/Vision/Hyperliquid) do not confirm an imminent crash.
-
Dual-Ticker Approach: Analyze the index, trade the ETF.
-
T212 Live Prices: Real-time recovery of EUR prices via the Trading 212 API (0.2s), with yfinance fallback and parquet cache.
-
Dated Brent Spread: Monitoring of physical market tension via the spread between Brent Spot (Dated) and Brent Futures.
-
Network Resilience: yfinance circuit breaker with separate trackers (info vs. download), 10s timeout on all network calls.
-
Cache Auto-Invalidation: Parquet cache auto-detects staleness (> 2 days) and forces a refresh. Use
refresh_cache.pyfor manual cache clearing. -
LLM Call Parallelization: Independent model calls (
text_llm,visual_llm,search_query,timesfm,tensortrade,grebenkov) run in aThreadPoolExecutorto overlap Ollama inference with I/O. Critical path typically 4–6 min on CPU vs 10+ min sequential. -
24h Search-Query Cache: The LLM-generated web-search query is cached under
data_cache/search_queries/<ticker>_<date>_<price-sig>.json. Keyed by date + a price-action signature (log2 bucketing of close + RSI bucket), so a regime change invalidates it. Fallback queries are never cached (one transient Ollama failure cannot poison the cache for 24h). -
Hard Cycle Timeout: Each ticker cycle is wrapped in a 15-min budget (
CYCLE_TIMEOUT_SECONDSinmain.py). On timeout, the worker thread isshutdown(wait=False)so the next ticker starts immediately; HOLD is applied to the timed-out ticker. Individual futures have their own per-task timeouts (search 240s, visual 300s, text 240s, CPU models 180s each, news 90s, web crawl 30s). -
Orphan-Thread Safety: On cycle timeout, a per-ticker
threading.Eventis set so the orphan worker bails out before anyexecute_t212_tradecall — preventing real-money trades after the user has been shown the "HOLD appliqué" panel. A per-tickerthreading.Lockfurther serializes T212 order placement, eliminating double-trade risk under scheduler overlap or duplicate--tickerinvocations. -
LLM Failure Sentinel: When
_query_ollamaexhausts all retries, the fallback dict carries a"failed": Trueflag so downstream consensus logic can distinguish "model chose HOLD" from "model crashed" (currently propagated but not filtered — a known follow-up). -
Advanced Cognition: Use of Gemma 4 12B with dual-layer JSON defence:
- Server-side schema enforcement (
format: SCHEMA_*withadditionalProperties: false) — the load-bearing layer; passed via Ollama'sformatparameter at every call site. Schemas defined insrc/llm_client.py(SCHEMA_TRADING_DECISION,SCHEMA_SEARCH_QUERY,SCHEMA_OIL_ALLOCATION). - Defensive system-prompt suffix (
"...never add a 'thought' key.") — redundant-but-harmless second line, kept as belt-and-braces against any future regression of the schema layer.
The
<|think|>reasoning token is active in all four production system prompts (re-enabled 2026-06-06 onmainafter validation onthink-modebranch). The schema layer is what actually neutralises the historical<|channel>thoughtJSON-debris defect (May 2026 root cause):tests/check_llm_json.pyconfirms that schema-strict cases (v3_schema,v6_schema,v7_schema_strict) produce clean JSON even with<|think|>enabled, while the looseformat:jsonvariants fail. Seedocs/ADR-001-think-mode-dual-layer-defence.mdfor the full analysis and reversal procedure. - Server-side schema enforcement (
-
Autonomous Morning Brief Agent: An overnight
smolagents-based workflow (morning_brief/morning_brief.py) scheduled to run automatically at 01:00 AM viaschedule.py. It independently crawls daily API logs, downloads fundamental EIA inventory data, and arbitrates a Bull vs Bear debate. The resulting markdown report (morning_market_brief.md) is automatically injected into the Textual LLM's system prompt during the daily trading cycle, granting the main AI deep contextual memory and fundamental awareness without slowing down live market execution. -
News & Blockchain Sentiment: Integration of AlphaEar and Hyperliquid to capture social and speculative sentiment.
-
Automated Scheduler:
schedule.pyscript for continuous execution (8:30 AM - 6:00 PM) on a server. -
Centralized Risk Management: The
AdvancedRiskManagercentralizes Anti-Loss (Stop-Loss) and Trailing Stop logic. Individual models no longer manage these risks, ensuring a unified and strict capital protection strategy across varying market regimes. -
Strict Data Contracts: All AI models are fully standardized to return a strongly-typed
ModelResultdataclass (signal,confidence,reasoning), ensuring 100% uniformity across the consensus engine. -
Code Health Audited: Project maintains a Grade B code health standard via automated audits (0 dead code, high maintainability index).
-
Production Backtesting: Standalone backtest engine (
backtest_prod.py) replaying real prod signals against real prices with T212 fees — no external dependencies. -
Debug Dump Control: Set
TRADING_DEBUG_DUMP=0to disable the capped (5 MB)data_cache/llm_debug_fail.txtLLM-failure dump.
- Language:
Python 3.12+ - Calculations & Data:
pandas,numpy,yfinance,pyarrow,pandas_datareader,hyperliquid-python-sdk - Machine Learning:
scikit-learn,shap - AI & LLM:
requests,ollama - Web Scraping & Search:
beautifulsoup4,duckduckgo_search,crawl4ai - Visualization:
matplotlib(Agg backend for thread safety),seaborn,mplfinance - Utilities:
tqdm,rich,python-dotenv,schedule
The system is designed to be performant on consumer hardware without requiring a dedicated GPU.
- CPU Only: LLM inference (Gemma 4 12B Q6_K via Ollama) and TimesFM run entirely on CPU. Throughput is ~3–4 tokens/s on a modern 8-core CPU.
- Recommended RAM: 16 GB minimum (32 GB suggested to run Gemma 4 12B comfortably alongside TimesFM and TensorTrade).
- Ollama Concurrency: Set
OLLAMA_NUM_PARALLEL=8(already in the recommended.env) so multiple LLM calls can share model load. With the default 4 GB context budget, parallel slots get ~512 tokens each — Ollama will serialize if prompts exceed the per-slot ctx, but theThreadPoolExecutorkeeps the wall-clock overlap beneficial for I/O-bound steps (news fetch, web crawl, CPU models). - Execution Time: ~6 to 9 minutes per ticker on CPU (cold), ~3 to 5 minutes per ticker with search-query cache hit. Default runs two tickers (CRUDP.PA + SXRV.DE), so plan ~15 min total.
- Cycle Timeout: Each ticker cycle is bounded at 15 min (
CYCLE_TIMEOUT_SECONDS). If exceeded, HOLD is applied and the next ticker starts immediately. - API Speed: Ultra-fast Trading 212 integration (<1s for live price recovery).
The project is organized modularly for better maintainability.
Trading-AI/
├── morning_brief/ # Overnight autonomous agent for deep fundamental analysis
│ ├── morning_brief.py # Agent orchestrator and smolagents configuration
│ └── output/ # Generated daily markdown reports (morning_market_brief.md)
├── src/ # Core modules
│ ├── adaptive_weight_manager.py # Dynamic model weighting based on performance
│ ├── advanced_risk_manager.py # Trend-Aware risk management and sizing
│ ├── bootstrap.py # Core initialization logic
│ ├── chart_generator.py # Generates technical charts for visual LLM
│ ├── classic_model.py # Scikit-learn quantitative models ensemble
│ ├── config_weights.py # Base weights configuration for the hybrid engine
│ ├── data.py # Data fetching, caching, and preprocessing
│ ├── database.py # SQLite database management for metrics
│ ├── eia_client.py # Energy Information Administration API client
│ ├── enhanced_decision_engine.py # Hybrid fusion engine orchestrating all models
│ ├── enhanced_trading_example.py # Example scripts for model utilization
│ ├── features.py # Technical and macroeconomic feature engineering
│ ├── grebenkov_model.py # Trend-Following math model (Agnostic Risk Parity)
│ ├── hmm_model.py # Hidden Markov Model for regime detection
│ ├── llm_client.py # Ollama integration for local LLM inference
│ ├── news_fetcher.py # Financial news crawling and parsing
│ ├── oil_bench_model.py # Energy-specialized WTI trading model
│ ├── performance_monitor.py # Tracking model accuracy and history
│ ├── read_simul.py # Tools for reading simulation outputs
│ ├── sentiment_analysis.py # Alpha Vantage & AlphaEar sentiment integration
│ ├── t212_executor.py # Trading 212 API real execution and portfolio
│ ├── tensortrade_model.py # Reinforcement Learning (PPO) signal
│ ├── timesfm_model.py # TimesFM 2.5 time-series forecasting integration
│ └── web_researcher.py # Macro-economic web scraping with Crawl4AI
├── data_cache/ # All caches (gitignored)
│ ├── *.parquet # OHLCV data per ticker (yfinance)
│ ├── macro/ # Macro time series (FRED, multi-source)
│ ├── search_queries/ # 24h LLM search-query cache (per ticker+date+price-sig)
│ └── llm_debug_fail.txt # Capped (5 MB) LLM failure dump — disable with TRADING_DEBUG_DUMP=0
├── tests/ # Test and validation scripts
│ ├── test_full_cycle.py # End-to-end T212 buy/wait/sell test
│ ├── test_enhanced_decision_engine.py # Tests for the hybrid fusion engine
│ ├── check_llm_json.py # LLM JSON-schema diagnostic (tests all 4 Ollama call sites)
│ ├── check_live.py # Live market prices verification script
│ └── ... # Other unit and integration tests
├── i18n/ # Internationalization (Translated READMEs)
├── assets/ # Static assets (images, banners)
├── memory-bank/ # AI assistant memory and context
├── backtest_prod.py # Standalone production backtest engine
├── main.py # Single entry point (Analysis & Trading)
├── pyproject.toml # Project dependencies and configuration (uv)
├── refresh_cache.py # CLI utility to force-refresh Parquet cache
├── schedule.py # Live scheduler for automated execution
├── setup_timesfm.py # Installation script for TimesFM 2.5 vendor
├── .env.example # Example environment variables
└── README.md # This documentation
Follow these steps to set up your local development environment.
- Python 3.12+ (via
uv) - Ollama installed and running locally.
- Downloaded LLM model:
ollama pull hf.co/unsloth/gemma-4-12b-it-GGUF:Q6_K
-
Clone the repository:
git clone https://github.com/laurentvv/Trading-AI.git cd Trading-AI -
Install
uv(if not already done): See astral.sh/uv for installation instructions. -
Create and activate the virtual environment (CRUCIAL Step): You must create and activate the
.venvbefore installing the foundation models.uv venv source .venv/bin/activate # On Windows, use `.\.venv\Scripts\activate.ps1`
-
Install Foundation Models: Run the installation scripts to clone the models into
vendor/and apply patches:python setup_timesfm.py
-
Initialize and synchronize the environment:
uv sync
-
Install browsers for Web research (Crawl4AI):
uv run python -m playwright install chromium
-
Configure your API keys: Create a
.envfile in the project root:ALPHA_VANTAGE_API_KEY="YOUR_KEY" EIA_API_KEY="YOUR_KEY"
The system trains its models on the most recent data at each execution before giving a decision.
To test the system without risk with a fictitious capital of €1000, use the --simul flag. The system will manage a strict history of buys and sells.
# Run a simulated analysis (Default: SXRV.DE - Nasdaq 100 EUR)
uv run main.py --simul
# Run on Oil (WTI)
uv run main.py --ticker CRUDP.PA --simulThe system is now fully integrated with Trading 212:
- Portfolio Verification: Before any action, the robot consults your real cash and positions.
- API Management: Includes automatic retry mechanisms against request limits (Rate Limiting).
# Run analysis with real execution (Demo or Real according to .env)
uv run main.py --t212The system includes a standalone production backtest engine (backtest_prod.py) that replays actual prod signals from logs_prod/trading_journal.csv against real prices from data_cache/ Parquet files.
- Real signals: Replays the exact decisions of the 11-model hybrid engine.
- Real prices: Uses actual ETF OHLCV data (SXRV.DE, CRUDP.PA) — no US proxies.
- T212 fees: Simulates Trading 212's 0.1% per-trade fee model.
- Baseline comparison: Automatically computes buy-and-hold performance as benchmark.
- Metrics: Sharpe Ratio, Maximum Drawdown, Win Rate, Alpha, Total Return per ticker.
uv run python backtest_prod.pyResults saved to logs_prod/backtest_report.json with equity curves CSV.
Contributions are welcome! Feel free to fork the project and open a Pull Request.
Distributed under the MIT License.
Project Link: https://github.com/laurentvv/Trading-AI
