TradingBot AI - Architecture Technique
Date : 20/12/2025
Priorite : MOYENNE - FIL ROUGE
Status : Draft
Projet : Assistant de trading multi-marchés avec IA
1. AVERTISSEMENT IMPORTANT
⚠️ CE PROJET EST À HAUT RISQUE FINANCIER
- Ne JAMAIS trader avec de l'argent que vous ne pouvez pas perdre
- Commencer en mode PAPER TRADING (simulation) uniquement
- L'IA n'est PAS infaillible - les marchés sont imprévisibles
- Les performances passées ne garantissent PAS les résultats futurs
- Ce projet est ÉDUCATIF et pour USAGE PERSONNEL uniquement
2. Vue d'ensemble
┌─────────────────────────────────────────────────────────────────────┐
│ DASHBOARD │
│ Qwik + TailwindCSS │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Portfolio │ │ Signals │ │Backtest │ │ Alerts │ │ News AI │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ API LAYER │
│ Elysia (Bun) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ /market │ │/strategy │ │ /alerts │ │/backtest │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Supabase │ │ Redis │ │ Ollama │ │ External │
│ PostgreSQL │ │ Realtime │ │ Sentiment │ │ APIs │
│ Trades │ │ Prices │ │ Analysis │ │ (Markets) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│
┌─────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ MARKET DATA SOURCES │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Binance │ │ Yahoo │ │Alpha Van-│ │CoinGecko │ │ News │ │
│ │ Crypto │ │ Finance │ │ tage │ │ │ │ APIs │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3. Marchés supportés
| Marché |
Source |
Temps réel |
Historique |
| Crypto |
Binance API |
WebSocket |
REST |
| Actions US |
Yahoo Finance |
15min delay |
Illimité |
| Actions FR |
Yahoo Finance |
15min delay |
Illimité |
| Forex |
Alpha Vantage |
1min |
20 ans |
| Commodities |
Yahoo Finance |
Delayed |
Illimité |
4. Stack Technique
Frontend
| Techno |
Usage |
| Qwik |
Dashboard SSR |
| TailwindCSS |
Styling |
| Lightweight Charts |
Graphiques trading |
| TanStack Table |
Tables données |
Backend
| Techno |
Usage |
| Elysia (Bun) |
API REST + WebSocket |
| Supabase |
Auth, DB, historique |
| Redis |
Cache prix, pub/sub alertes |
| Bull |
Queue jobs (analyses) |
IA
| Techno |
Usage |
| Ollama (mistral:7b) |
Analyse sentiment news |
| TA-Lib (via Python) |
Indicateurs techniques |
External APIs
| API |
Usage |
Coût |
| Binance |
Crypto spot |
Gratuit |
| Yahoo Finance |
Actions, indices |
Gratuit |
| Alpha Vantage |
Forex, premium data |
Freemium (5 calls/min) |
| NewsAPI |
Actualités marchés |
Freemium |
| Twitter API |
Sentiment crypto |
Payant |
5. Schéma Base de Données
-- Extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "timescaledb"; -- Séries temporelles
-- ============================================
-- CONFIGURATION UTILISATEUR
-- ============================================
CREATE TABLE profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
display_name VARCHAR(100),
risk_tolerance VARCHAR(20) DEFAULT 'medium', -- low, medium, high
default_currency VARCHAR(10) DEFAULT 'EUR',
telegram_chat_id VARCHAR(50), -- Pour alertes
settings JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- ============================================
-- ASSETS & WATCHLISTS
-- ============================================
CREATE TABLE assets (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
symbol VARCHAR(20) NOT NULL UNIQUE, -- BTC, AAPL, EUR/USD
name VARCHAR(200),
asset_type VARCHAR(20), -- crypto, stock, forex, commodity
exchange VARCHAR(50), -- binance, nasdaq, forex
base_currency VARCHAR(10),
quote_currency VARCHAR(10),
logo_url TEXT,
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE watchlists (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
is_default BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE watchlist_items (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
watchlist_id UUID REFERENCES watchlists(id) ON DELETE CASCADE,
asset_id UUID REFERENCES assets(id) ON DELETE CASCADE,
added_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(watchlist_id, asset_id)
);
-- ============================================
-- PRIX (TimescaleDB hypertable)
-- ============================================
CREATE TABLE prices (
time TIMESTAMPTZ NOT NULL,
asset_id UUID REFERENCES assets(id) ON DELETE CASCADE,
open DECIMAL(20, 8),
high DECIMAL(20, 8),
low DECIMAL(20, 8),
close DECIMAL(20, 8),
volume DECIMAL(30, 8),
timeframe VARCHAR(10) -- 1m, 5m, 15m, 1h, 4h, 1d
);
-- Convertir en hypertable TimescaleDB
SELECT create_hypertable('prices', 'time');
-- Index composé pour requêtes rapides
CREATE INDEX idx_prices_asset_time ON prices(asset_id, time DESC);
-- Rétention: garder 1 an de données 1m, 5 ans de 1d
SELECT add_retention_policy('prices', INTERVAL '1 year', if_not_exists => true);
-- ============================================
-- INDICATEURS TECHNIQUES (cache)
-- ============================================
CREATE TABLE indicators (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
asset_id UUID REFERENCES assets(id) ON DELETE CASCADE,
time TIMESTAMPTZ NOT NULL,
timeframe VARCHAR(10),
-- Moyennes mobiles
sma_20 DECIMAL(20, 8),
sma_50 DECIMAL(20, 8),
sma_200 DECIMAL(20, 8),
ema_12 DECIMAL(20, 8),
ema_26 DECIMAL(20, 8),
-- Momentum
rsi_14 DECIMAL(5, 2),
macd DECIMAL(20, 8),
macd_signal DECIMAL(20, 8),
macd_histogram DECIMAL(20, 8),
-- Volatilité
bb_upper DECIMAL(20, 8),
bb_middle DECIMAL(20, 8),
bb_lower DECIMAL(20, 8),
atr_14 DECIMAL(20, 8),
-- Volume
obv DECIMAL(30, 8),
vwap DECIMAL(20, 8),
computed_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_indicators_unique ON indicators(asset_id, time, timeframe);
-- ============================================
-- SIGNAUX DE TRADING
-- ============================================
CREATE TABLE signals (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
asset_id UUID REFERENCES assets(id) ON DELETE CASCADE,
user_id UUID REFERENCES profiles(id), -- NULL = signal système
signal_type VARCHAR(20), -- buy, sell, hold
strength VARCHAR(20), -- weak, medium, strong
-- Source du signal
source VARCHAR(50), -- rsi_oversold, macd_cross, ai_sentiment, etc
timeframe VARCHAR(10),
-- Prix au moment du signal
price_at_signal DECIMAL(20, 8),
-- Cibles suggérées
target_price DECIMAL(20, 8),
stop_loss DECIMAL(20, 8),
risk_reward_ratio DECIMAL(5, 2),
-- Analyse IA
ai_reasoning TEXT,
confidence DECIMAL(3, 2), -- 0.00 à 1.00
-- Validation
is_valid BOOLEAN DEFAULT true,
invalidated_at TIMESTAMPTZ,
invalidation_reason TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_signals_asset ON signals(asset_id, created_at DESC);
CREATE INDEX idx_signals_active ON signals(is_valid, created_at DESC) WHERE is_valid = true;
-- ============================================
-- ALERTES
-- ============================================
CREATE TABLE alerts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE,
asset_id UUID REFERENCES assets(id) ON DELETE CASCADE,
alert_type VARCHAR(30), -- price_above, price_below, rsi_oversold, etc
condition JSONB, -- { "operator": ">", "value": 50000 }
message TEXT,
-- Status
is_active BOOLEAN DEFAULT true,
triggered_at TIMESTAMPTZ,
trigger_count INTEGER DEFAULT 0,
-- Notification
notify_telegram BOOLEAN DEFAULT true,
notify_email BOOLEAN DEFAULT false,
notify_push BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- ============================================
-- PAPER TRADING (Simulation)
-- ============================================
CREATE TABLE paper_portfolios (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE,
name VARCHAR(100) DEFAULT 'Default',
initial_balance DECIMAL(20, 2) DEFAULT 10000,
current_balance DECIMAL(20, 2) DEFAULT 10000,
currency VARCHAR(10) DEFAULT 'EUR',
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE paper_positions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
portfolio_id UUID REFERENCES paper_portfolios(id) ON DELETE CASCADE,
asset_id UUID REFERENCES assets(id),
quantity DECIMAL(20, 8),
avg_entry_price DECIMAL(20, 8),
current_value DECIMAL(20, 2),
unrealized_pnl DECIMAL(20, 2),
unrealized_pnl_percent DECIMAL(8, 4),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE paper_trades (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
portfolio_id UUID REFERENCES paper_portfolios(id) ON DELETE CASCADE,
asset_id UUID REFERENCES assets(id),
signal_id UUID REFERENCES signals(id), -- Lien avec signal si applicable
trade_type VARCHAR(10), -- buy, sell
quantity DECIMAL(20, 8),
price DECIMAL(20, 8),
total_value DECIMAL(20, 2),
fees DECIMAL(20, 2) DEFAULT 0,
-- PnL (pour les ventes)
realized_pnl DECIMAL(20, 2),
realized_pnl_percent DECIMAL(8, 4),
executed_at TIMESTAMPTZ DEFAULT NOW()
);
-- ============================================
-- BACKTESTING
-- ============================================
CREATE TABLE backtests (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE,
name VARCHAR(200),
-- Configuration
strategy_config JSONB, -- Paramètres de la stratégie
assets TEXT[], -- Liste des symboles
timeframe VARCHAR(10),
start_date DATE,
end_date DATE,
initial_capital DECIMAL(20, 2),
-- Résultats
final_capital DECIMAL(20, 2),
total_return_percent DECIMAL(8, 4),
max_drawdown_percent DECIMAL(8, 4),
sharpe_ratio DECIMAL(8, 4),
win_rate DECIMAL(5, 2),
total_trades INTEGER,
profit_factor DECIMAL(8, 4),
-- Détails
trades_log JSONB, -- Historique complet des trades
equity_curve JSONB, -- Évolution du capital
status VARCHAR(20) DEFAULT 'pending', -- pending, running, completed, failed
error_message TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
-- ============================================
-- SENTIMENT / NEWS
-- ============================================
CREATE TABLE news (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
title TEXT NOT NULL,
summary TEXT,
content TEXT,
source VARCHAR(100),
url TEXT UNIQUE,
published_at TIMESTAMPTZ,
-- Assets mentionnés
related_assets UUID[],
-- Analyse sentiment IA
sentiment VARCHAR(20), -- very_bullish, bullish, neutral, bearish, very_bearish
sentiment_score DECIMAL(3, 2), -- -1.00 à +1.00
ai_analysis TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_news_published ON news(published_at DESC);
CREATE INDEX idx_news_assets ON news USING GIN(related_assets);
6. API Endpoints
Market Data
GET /api/market/assets # Liste tous les assets
GET /api/market/assets/:symbol # Détail asset
GET /api/market/prices/:symbol # Prix historiques
GET /api/market/prices/:symbol/live # WebSocket prix temps réel
GET /api/market/indicators/:symbol # Indicateurs techniques
Watchlists
GET /api/watchlists # Mes watchlists
POST /api/watchlists # Créer
POST /api/watchlists/:id/assets # Ajouter asset
DELETE /api/watchlists/:id/assets/:asset # Retirer asset
Signals
GET /api/signals # Signaux actifs
GET /api/signals/:symbol # Signaux pour un asset
POST /api/signals/scan # Lancer un scan
Alerts
GET /api/alerts # Mes alertes
POST /api/alerts # Créer alerte
PATCH /api/alerts/:id # Modifier
DELETE /api/alerts/:id # Supprimer
Paper Trading
GET /api/paper/portfolio # Mon portfolio simulé
POST /api/paper/trade # Exécuter trade simulé
GET /api/paper/trades # Historique trades
GET /api/paper/performance # Statistiques
Backtesting
POST /api/backtest # Lancer backtest
GET /api/backtest/:id # Résultat
GET /api/backtests # Historique
News & Sentiment
GET /api/news # Dernières news
GET /api/news/:symbol # News par asset
GET /api/sentiment/:symbol # Score sentiment agrégé
7. Workers
Price Collector
// /workers/price-collector.ts
import Binance from 'binance-api-node';
const binance = Binance();
// WebSocket pour crypto temps réel
binance.ws.allTickers(tickers => {
for (const ticker of tickers) {
// Publier sur Redis
redis.publish(`price:${ticker.symbol}`, JSON.stringify({
price: ticker.curDayClose,
change: ticker.priceChangePercent,
volume: ticker.volume
}));
// Sauvegarder en DB (agrégé par minute)
await savePriceCandle(ticker);
}
});
// REST pour stocks (toutes les minutes)
cron.schedule('* * * * *', async () => {
const stocks = await getWatchedStocks();
for (const symbol of stocks) {
const data = await yahooFinance.quote(symbol);
await savePriceCandle(data);
}
});
Indicator Calculator
// /workers/indicator-calculator.ts
import talib from 'talib';
async function calculateIndicators(assetId: string, timeframe: string) {
const prices = await getPrices(assetId, timeframe, 200);
const closes = prices.map(p => p.close);
const highs = prices.map(p => p.high);
const lows = prices.map(p => p.low);
const volumes = prices.map(p => p.volume);
const indicators = {
sma_20: talib.SMA(closes, 20),
sma_50: talib.SMA(closes, 50),
sma_200: talib.SMA(closes, 200),
rsi_14: talib.RSI(closes, 14),
macd: talib.MACD(closes, 12, 26, 9),
bb: talib.BBANDS(closes, 20, 2),
atr_14: talib.ATR(highs, lows, closes, 14),
};
await saveIndicators(assetId, timeframe, indicators);
}
Signal Generator
// /workers/signal-generator.ts
async function generateSignals(assetId: string) {
const indicators = await getLatestIndicators(assetId);
const price = await getLatestPrice(assetId);
const signals = [];
// RSI Oversold
if (indicators.rsi_14 < 30) {
signals.push({
type: 'buy',
source: 'rsi_oversold',
strength: indicators.rsi_14 < 20 ? 'strong' : 'medium',
reasoning: `RSI à ${indicators.rsi_14}, zone de survente`
});
}
// RSI Overbought
if (indicators.rsi_14 > 70) {
signals.push({
type: 'sell',
source: 'rsi_overbought',
strength: indicators.rsi_14 > 80 ? 'strong' : 'medium',
reasoning: `RSI à ${indicators.rsi_14}, zone de surachat`
});
}
// MACD Cross
if (indicators.macd > indicators.macd_signal &&
prevIndicators.macd < prevIndicators.macd_signal) {
signals.push({
type: 'buy',
source: 'macd_bullish_cross',
strength: 'medium'
});
}
// Golden Cross (SMA 50 > SMA 200)
if (indicators.sma_50 > indicators.sma_200 &&
prevIndicators.sma_50 < prevIndicators.sma_200) {
signals.push({
type: 'buy',
source: 'golden_cross',
strength: 'strong'
});
}
// Sauvegarder les signaux
for (const signal of signals) {
await supabase.from('signals').insert({
asset_id: assetId,
...signal,
price_at_signal: price.close
});
}
}
Sentiment Analyzer
// /workers/sentiment-analyzer.ts
async function analyzeSentiment(newsId: string) {
const news = await supabase.from('news').select('*').eq('id', newsId).single();
const prompt = `
Analyse le sentiment de cette actualité financière:
Titre: ${news.data.title}
Contenu: ${news.data.content}
Réponds en JSON:
{
"sentiment": "very_bullish|bullish|neutral|bearish|very_bearish",
"score": <nombre entre -1.0 et 1.0>,
"reasoning": "<explication courte>",
"related_assets": ["BTC", "ETH", ...] // symboles mentionnés
}
`;
const response = await fetch('http://192.168.1.30:11434/api/generate', {
method: 'POST',
body: JSON.stringify({ model: 'mistral:7b', prompt })
});
const result = JSON.parse(await response.text());
await supabase.from('news').update({
sentiment: result.sentiment,
sentiment_score: result.score,
ai_analysis: result.reasoning,
related_assets: result.related_assets
}).eq('id', newsId);
}
8. Interface Utilisateur
Dashboard Principal
┌─────────────────────────────────────────────────────────────────────┐
│ TradingBot AI [Paper: €10,245.50 (+2.45%)] [⚙️]│
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ ┌───────────────────────────┐│
│ │ BTC/USDT │ │ SIGNAUX ACTIFS ││
│ │ $43,250.00 +2.3% │ │ ││
│ │ ┌─────────────────────────┐ │ │ 🟢 BTC Buy (RSI 28) ││
│ │ │ [Candlestick] │ │ │ 🟢 ETH Buy (MACD Cross) ││
│ │ │ [ Chart ] │ │ │ 🔴 SOL Sell (RSI 78) ││
│ │ └─────────────────────────┘ │ │ ││
│ │ RSI: 45 MACD: ▲ BB: Middle │ └───────────────────────────┘│
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ WATCHLIST ││
│ │ Symbol Price 24h RSI Signal ││
│ │ BTC $43,250.00 +2.3% 45 - ││
│ │ ETH $2,280.00 +1.8% 52 🟢 Buy ││
│ │ SOL $98.50 +5.2% 78 🔴 Sell ││
│ │ AAPL $178.50 -0.5% 48 - ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │
├─────────────────────────────────────────────────────────────────────┤
│ [Dashboard] [Portfolio] [Signals] [Backtest] [Alerts] [News] │
└─────────────────────────────────────────────────────────────────────┘
9. MVP - Phases
Phase 1 : Data Foundation (2-3 semaines)
- [ ] Setup projet
- [ ] Collector prix crypto (Binance)
- [ ] Collector prix stocks (Yahoo)
- [ ] Stockage TimescaleDB
- [ ] API prix historiques
Phase 2 : Indicateurs (2 semaines)
- [ ] Calcul indicateurs (RSI, MACD, BB, SMA)
- [ ] Cache Redis
- [ ] Affichage graphiques
Phase 3 : Signaux (2 semaines)
- [ ] Générateur signaux basiques
- [ ] Interface signaux
- [ ] Alertes Telegram
Phase 4 : Paper Trading (2 semaines)
- [ ] Portfolio simulé
- [ ] Exécution trades papier
- [ ] Historique & stats
Phase 5 : IA Sentiment (2 semaines)
- [ ] Collector news
- [ ] Analyse sentiment Ollama
- [ ] Intégration dashboard
Phase 6 : Backtesting (optionnel)
- [ ] Moteur backtest
- [ ] Interface résultats
- [ ] Optimisation stratégies
10. Déploiement
services:
tradingbot-dashboard:
build: ./dashboard
ports:
- "4800:3000"
tradingbot-api:
build: ./api
ports:
- "4801:3001"
tradingbot-workers:
build: ./workers
# Workers tournent en continu
timescaledb:
image: timescale/timescaledb:latest-pg15
volumes:
- timescale_data:/var/lib/postgresql/data
ports:
- "5434:5432"
URLs