33800 Docs

← Retour

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)

Phase 2 : Indicateurs (2 semaines)

Phase 3 : Signaux (2 semaines)

Phase 4 : Paper Trading (2 semaines)

Phase 5 : IA Sentiment (2 semaines)

Phase 6 : Backtesting (optionnel)


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

Service URL
Dashboard https://trading.33800.nowhere84.com
API https://trading-api.33800.nowhere84.com