🐍 Tutoriel Pilier Avancé

Python + API Deriv — Construire Votre Premier Bot Trading

Par Dan Machado · 18 min · Niveau intermédiaire/avancé

Deriv Bot Builder est génial pour débuter. Mais pour vraiment contrôler votre stratégie — gestion d’erreurs sophistiquée, logging CSV, stop-loss dynamique, machine learning — vous avez besoin de Python. Ce tutoriel vous donne un bot complet en 150 lignes, prêt à déployer sur VPS Afrique. Code open-source, commenté en français.

🎯 Ce Que Vous Construirez

Un bot Python complet qui :
✓ Se connecte au WebSocket API officielle Deriv
✓ S’authentifie via OAuth token (sécurisé)
✓ Souscrit aux ticks Volatility 75 Index temps réel
✓ Calcule RSI(14) à chaque nouveau tick
✓ Achète CALL/PUT selon signaux RSI
✓ Applique sizing 2% balance + limite perte journalière
✓ Log chaque trade dans fichier CSV
✓ Gère erreurs réseau avec auto-reconnect

Prérequis

1

Compte Deriv (gratuit)

Si pas déjà : créer compte démo. Commencez TOUJOURS sur démo.

2

Python 3.9+

Téléchargez depuis python.org. Vérifiez : ouvrir terminal, taper python --version. Doit afficher 3.9 ou supérieur.

3

Bibliothèques requises

Dans terminal :
pip install python-deriv-api websockets pandas numpy

4

API Token Deriv

Deriv → Account Settings → API token → Create new token. Scopes : Read, Trade. Copiez le token (vous le verrez UNE SEULE fois).

5

Éditeur de code

VS Code (recommandé) ou PyCharm Community. Tous deux gratuits, support Python excellent.

Architecture du Bot

Notre bot a 3 modules principaux :

  • bot_main.py — boucle principale, gestion WebSocket
  • strategy.py — calcul RSI et logique signaux
  • risk_manager.py — sizing 2% + limites journalières

Code Complet — bot_main.py

▸ Python · Bot Principal
"""
Deriv Trading Bot - Python WebSocket
Author: Dan Machado / IA Trader Pro
License: MIT (use at own risk)
"""
import asyncio
import json
import websockets
import logging
import csv
from datetime import datetime
from strategy import RSIStrategy
from risk_manager import RiskManager

# === CONFIGURATION ===
API_TOKEN = "VOTRE_TOKEN_DERIV_ICI"  # Remplacer
APP_ID = "1089"  # Deriv public app_id (OK pour debut)
SYMBOL = "R_75"  # Volatility 75 Index
WS_URL = f"wss://ws.derivws.com/websockets/v3?app_id={APP_ID}"

# Setup logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[logging.FileHandler('bot.log'), logging.StreamHandler()]
)
log = logging.getLogger(__name__)


class DerivBot:
    def __init__(self):
        self.ws = None
        self.balance = 0
        self.starting_balance = 0
        self.strategy = RSIStrategy(period=14, oversold=30, overbought=70)
        self.risk = RiskManager(max_daily_loss_pct=5.0, position_size_pct=2.0)
        self.csv_init()
    
    def csv_init(self):
        """Init CSV log file"""
        try:
            with open('trades.csv', 'x', newline='') as f:
                w = csv.writer(f)
                w.writerow(['timestamp', 'signal', 'price', 'stake',
                           'balance_before', 'result', 'balance_after'])
        except FileExistsError:
            pass  # File exists, append mode
    
    def log_trade(self, signal, price, stake, balance_before, result, balance_after):
        with open('trades.csv', 'a', newline='') as f:
            w = csv.writer(f)
            w.writerow([datetime.now().isoformat(), signal, price, stake,
                       balance_before, result, balance_after])
    
    async def authenticate(self):
        await self.ws.send(json.dumps({"authorize": API_TOKEN}))
        msg = json.loads(await self.ws.recv())
        if "error" in msg:
            log.error(f"Auth failed: {msg['error']['message']}")
            raise Exception("Authentication failed")
        self.balance = msg["authorize"]["balance"]
        self.starting_balance = self.balance
        log.info(f"Authenticated. Balance: ${self.balance:.2f}")
    
    async def subscribe_ticks(self):
        await self.ws.send(json.dumps({
            "ticks": SYMBOL,
            "subscribe": 1
        }))
        log.info(f"Subscribed to {SYMBOL} ticks")
    
    async def place_trade(self, contract_type, stake):
        """contract_type: 'CALL' (up) or 'PUT' (down)"""
        balance_before = self.balance
        proposal_req = {
            "buy": 1,
            "price": stake,
            "parameters": {
                "amount": stake,
                "basis": "stake",
                "contract_type": contract_type,
                "currency": "USD",
                "duration": 5,
                "duration_unit": "t",  # ticks
                "symbol": SYMBOL
            }
        }
        await self.ws.send(json.dumps(proposal_req))
        msg = json.loads(await self.ws.recv())
        
        if "error" in msg:
            log.error(f"Trade error: {msg['error']['message']}")
            return None
        
        contract_id = msg["buy"]["contract_id"]
        log.info(f"{contract_type} placed: ${stake} @ {SYMBOL}, contract {contract_id}")
        
        # Wait for result (poll contract status)
        await asyncio.sleep(6)  # 5 tick duration + buffer
        await self.ws.send(json.dumps({
            "proposal_open_contract": 1,
            "contract_id": contract_id
        }))
        result_msg = json.loads(await self.ws.recv())
        
        if "proposal_open_contract" in result_msg:
            profit = result_msg["proposal_open_contract"].get("profit", 0)
            self.balance += profit
            self.log_trade(contract_type, msg["buy"].get("buy_price"),
                          stake, balance_before, profit, self.balance)
            log.info(f"Trade result: P/L=${profit:.2f}, Balance=${self.balance:.2f}")
            return profit
        return None
    
    async def process_tick(self, msg):
        if "tick" not in msg:
            return
        
        tick = msg["tick"]
        price = float(tick["quote"])
        
        # Update strategy
        signal = self.strategy.update(price)
        
        if signal is None:
            return  # Not enough data yet, or no signal
        
        # Check risk manager
        if not self.risk.can_trade(self.balance, self.starting_balance):
            log.warning("Risk limit hit. Skipping trade.")
            return
        
        # Calculate stake
        stake = self.risk.calculate_stake(self.balance)
        
        # Place trade
        contract_type = "CALL" if signal == "BUY" else "PUT"
        await self.place_trade(contract_type, stake)
    
    async def run(self):
        log.info("Starting Deriv Bot")
        async with websockets.connect(WS_URL) as ws:
            self.ws = ws
            await self.authenticate()
            await self.subscribe_ticks()
            
            try:
                async for message in ws:
                    msg = json.loads(message)
                    await self.process_tick(msg)
            except websockets.exceptions.ConnectionClosed:
                log.warning("Connection lost. Reconnecting in 5s...")
                await asyncio.sleep(5)
                await self.run()  # Restart


if __name__ == "__main__":
    bot = DerivBot()
    asyncio.run(bot.run())

strategy.py — Stratégie RSI

▸ Python · Strategy Module
"""RSI Strategy Module"""
from collections import deque

class RSIStrategy:
    def __init__(self, period=14, oversold=30, overbought=70):
        self.period = period
        self.oversold = oversold
        self.overbought = overbought
        self.prices = deque(maxlen=period + 1)
        self.gains = deque(maxlen=period)
        self.losses = deque(maxlen=period)
        self.last_rsi = None
        self.prev_rsi = None
    
    def calculate_rsi(self):
        if len(self.prices) < self.period + 1:
            return None
        
        # Calculate price changes
        changes = []
        for i in range(1, len(self.prices)):
            changes.append(self.prices[i] - self.prices[i-1])
        
        # Separate gains and losses
        gains = [c if c > 0 else 0 for c in changes]
        losses = [-c if c < 0 else 0 for c in changes]
        
        # Average
        avg_gain = sum(gains) / self.period
        avg_loss = sum(losses) / self.period
        
        if avg_loss == 0:
            return 100
        
        rs = avg_gain / avg_loss
        rsi = 100 - (100 / (1 + rs))
        return rsi
    
    def update(self, price):
        self.prices.append(price)
        rsi = self.calculate_rsi()
        
        if rsi is None:
            return None
        
        self.prev_rsi = self.last_rsi
        self.last_rsi = rsi
        
        # Signal logic: CROSS oversold/overbought
        if self.prev_rsi is None:
            return None
        
        # BUY signal: RSI crosses ABOVE oversold (was below, now above)
        if self.prev_rsi < self.oversold and rsi >= self.oversold:
            return "BUY"
        
        # SELL signal: RSI crosses BELOW overbought
        if self.prev_rsi > self.overbought and rsi <= self.overbought:
            return "SELL"
        
        return None

risk_manager.py — Gestion du Risque

▸ Python · Risk Manager
"""Risk Management Module"""
from datetime import datetime, date

class RiskManager:
    def __init__(self, max_daily_loss_pct=5.0, position_size_pct=2.0,
                 max_trades_per_day=8):
        self.max_daily_loss_pct = max_daily_loss_pct
        self.position_size_pct = position_size_pct
        self.max_trades_per_day = max_trades_per_day
        self.trades_today = 0
        self.last_trade_date = date.today()
        self.consecutive_losses = 0
        self.cooldown_until = None
    
    def reset_daily(self):
        """Reset counters at midnight"""
        today = date.today()
        if today != self.last_trade_date:
            self.trades_today = 0
            self.last_trade_date = today
    
    def can_trade(self, current_balance, starting_balance):
        self.reset_daily()
        
        # Check daily loss limit
        loss_pct = ((starting_balance - current_balance) / starting_balance) * 100
        if loss_pct >= self.max_daily_loss_pct:
            return False
        
        # Check trades per day
        if self.trades_today >= self.max_trades_per_day:
            return False
        
        # Check cooldown after 3 consecutive losses
        if self.consecutive_losses >= 3:
            if self.cooldown_until and datetime.now() < self.cooldown_until:
                return False
            else:
                self.consecutive_losses = 0
                self.cooldown_until = None
        
        return True
    
    def calculate_stake(self, balance):
        """Position size = balance * position_size_pct / 100"""
        stake = balance * (self.position_size_pct / 100)
        # Round to 2 decimals, minimum $1
        stake = max(round(stake, 2), 1.0)
        # Cap at $100 (safety)
        stake = min(stake, 100.0)
        self.trades_today += 1
        return stake
    
    def record_result(self, profit):
        if profit < 0:
            self.consecutive_losses += 1
            if self.consecutive_losses >= 3:
                # 60min cooldown
                from datetime import timedelta
                self.cooldown_until = datetime.now() + timedelta(minutes=60)
        else:
            self.consecutive_losses = 0

Comment Lancer Le Bot

  1. Créez dossier deriv-bot/
  2. Sauvegardez les 3 fichiers (bot_main.py, strategy.py, risk_manager.py)
  3. Éditez bot_main.py et remplacez API_TOKEN par votre token
  4. Dans terminal, naviguez vers le dossier
  5. Lancez : python bot_main.py
  6. Le bot se connecte, s’authentifie, et commence à trader
  7. Logs apparaissent dans le terminal ET dans bot.log
  8. Trades enregistrés dans trades.csv

✅ Tester Avant Production

1. Lancez sur compte démo Deriv (token démo)
2. Laissez tourner 24 heures minimum
3. Vérifiez bot.log pour erreurs
4. Analysez trades.csv (Excel ou pandas)
5. Calculez win rate, profit factor
6. Si solide après 30 jours démo, considérez réel

Déploiement VPS pour l’Afrique

Pour que le bot tourne 24/7 (les indices synthétiques ne dorment jamais), déployez sur un VPS. Recommandations pour l’Afrique francophone :

🌍 Choix VPS Optimaux

1. Vultr – Paris : latence ~80ms vers Deriv (UE), 6$ /mo (~3,600 FCFA)
2. Vultr – Lagos (Nigeria) : meilleur ping pour West Africa, 6$ /mo
3. OVH – France : 5€ /mo, fiable, support français
4. DigitalOcean – Frankfurt : 6$ /mo, excellent uptime
5. Hetzner – Allemagne : 4€ /mo, ratio prix/performance imbattable

Paiement : carte bancaire (la plupart acceptent FCFA via conversion auto).

Setup Rapide sur Vultr

▸ Bash · Setup VPS
# 1. SSH dans VPS
ssh root@VOTRE_IP_VPS

# 2. Installer Python + git
apt update && apt install -y python3 python3-pip git screen

# 3. Cloner ou copier votre code
scp -r ./deriv-bot/ root@VOTRE_IP:/root/

# 4. Installer dependencies
cd /root/deriv-bot
pip3 install -r requirements.txt

# 5. Lancer en background avec screen
screen -S deriv-bot
python3 bot_main.py
# Ctrl+A puis D pour détacher (bot continue tourner)

# 6. Reconnecter session:
screen -r deriv-bot

# 7. Monitor logs:
tail -f bot.log

Risques et Limites

⚠️ À Garder en Tête

1. Le code est éducatif. Avant production, audit complet du code, tests extensifs, peer review.
2. Win rate démo ≠ réel. Comptez 15-25% de moins en réel (psychologie, slippage).
3. API peut changer. Deriv update parfois — adaptez votre code aux changements.
4. Connectivité VPS. Latence affecte exécution. Choisir VPS proche de Deriv servers.
5. Token security. Ne jamais commit token sur GitHub public. Utilisez .env file ignoré par git.
6. Backup. Sauvegardez code + trades.csv régulièrement.

Améliorations Suggérées

Une fois ce bot de base fonctionnel, ces améliorations valent la peine :

  • Multiple timeframes : analyser ticks ET barres 1min/5min
  • Multiple actifs : V75, V100, R_25, R_50 en parallèle
  • Indicators combinés : RSI + MACD ou RSI + Bollinger
  • Machine Learning : prédire signaux avec scikit-learn ou TensorFlow
  • Dashboard web : Flask + Chart.js pour monitoring temps réel
  • Alertes Telegram : notifications instantanées
  • Backtesting historique : module séparé pour tester sur ticks passés
  • Database : SQLite/PostgreSQL pour archivage long-terme

🚀 Testez ce bot sur Deriv démo gratuit ($10,000 virtuels) :

Ouvrir Compte Démo Gratuit →

Lectures Connexes

DM

Dan Machado

Fondateur IA Trader Pro · Développeur Python 10+ ans

⚠️ Avertissement : Code éducatif. Trading bots = risque élevé. Toujours tester sur démo 30+ jours avant réel. Trading derivatives comporte risque substantiel de perte capital. Deriv régulé MFSA/Vanuatu. Contient des liens d’affiliation Deriv. Avertissement complet.

Publications similaires