Initial commit
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
# DRL‑MT5‑Lab
|
||||
|
||||
Deep Reinforcement Learning (SB3) + MetaTrader 5 (MT5) for **backtesting** and **live trading**.
|
||||
|
||||
This repo keeps research and production concerns separate:
|
||||
- **Notebooks** for data/feature engineering, training, optimization, backtesting and reports.
|
||||
- **CLI** for **live inference only** (stable, safe, log‑rich).
|
||||
|
||||
> ⚠️ Educational use only. Trading involves risk. You are responsible for your own deployment and keys.
|
||||
|
||||
---
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Stable‑Baselines3** agents (PPO primary; A2C, DQN optional in notebooks).
|
||||
- Clean **live trading CLI** (`live_bot_ascii_market.py`) with multi-algorithm support:
|
||||
- **DRY‑RUN** by default (no orders until `--live`).
|
||||
- **Market guard**: weekend + stale tick check (configurable).
|
||||
- FinRL‑style **verbose logs** + rotating file logs.
|
||||
- Feature snapshot (e.g., `close`, `ma_fast`, `ma_slow`, `rsi`).
|
||||
- Backtest notebook with equity curve; optional QuantStats HTML report.
|
||||
- Config via `.env` + CLI flags.
|
||||
- Windows‑safe ASCII logs (no Unicode issues in CP1252 consoles).
|
||||
|
||||
---
|
||||
|
||||
## Repo layout (typical)
|
||||
|
||||
```
|
||||
.
|
||||
├─ notebooks/
|
||||
│ ├─ 1_Data_Features.ipynb
|
||||
│ ├─ 2_Train_Optimize.ipynb
|
||||
│ ├─ 3_Backtest.ipynb
|
||||
│ └─ 4_Live_Demo.ipynb
|
||||
│ └─ models/
|
||||
│ ├─ selected_features.json # list of columns used by the model
|
||||
│ └─ ppo_{SYMBOL}_{TF}.zip # exported Stable‑Baselines3 model
|
||||
├─ adapters/
|
||||
│ └─ broker.py # MT5 wrapper used by the CLI
|
||||
│ └─ mt5.py
|
||||
├─ features.py # add_indicators(...) etc.
|
||||
├─ live_bot.py # ASCII logs + market‑hours guard ← recommended
|
||||
├─ utils.py # ASCII logs
|
||||
├─ requirements.txt
|
||||
├─ .env.example
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
> Names may vary slightly depending on your local structure. The CLI only needs: `adapters/broker.py`, `features.py`, `models/selected_features.json`, and a model zip.
|
||||
|
||||
---
|
||||
|
||||
## Quickstart
|
||||
|
||||
### 1) Environment
|
||||
```bash
|
||||
# create and activate your venv/conda, then:
|
||||
pip install -r requirements.txt
|
||||
# TA‑Lib on Windows: you may prefer a prebuilt 'ta-lib' wheel or conda-forge.
|
||||
```
|
||||
|
||||
### 2) Create `.env`
|
||||
Copy `.env.example` → `.env` and fill your MT5 credentials and defaults.
|
||||
|
||||
### 3) Train / export a model
|
||||
Use the notebooks (recommended) to train and save:
|
||||
- `models/ppo_{SYMBOL}_{TF}.zip`
|
||||
- `models/selected_features.json` (list of feature column names)
|
||||
|
||||
> Alternatively point `--model`/`--features` at your own paths.
|
||||
|
||||
### 4) Run the live CLI (default DRY‑RUN)
|
||||
```bash
|
||||
# Windows PowerShell
|
||||
python live_bot_ascii_market.py --symbol EURUSD --timeframe M15
|
||||
|
||||
# Place real orders (be careful)
|
||||
python live_bot_ascii_market.py --symbol EURUSD --timeframe M15 --live
|
||||
```
|
||||
|
||||
The bot will:
|
||||
1) Pull latest bars via `adapters/broker.fetch_last_n(...)`
|
||||
2) Build features with `features.add_indicators(...)`
|
||||
3) Predict action with SB3
|
||||
4) Close opposite‑side positions if any
|
||||
5) Place a market order (unless DRY‑RUN)
|
||||
6) Sleep to the next bar boundary
|
||||
|
||||
Logs are streamed to console and to `logs/live_bot.log` (rotating).
|
||||
|
||||
---
|
||||
|
||||
## CLI options
|
||||
|
||||
```bash
|
||||
python live_bot_ascii_market.py --help
|
||||
```
|
||||
|
||||
Important flags:
|
||||
|
||||
- `--symbol EURUSD` Trading symbol
|
||||
- `--timeframe M15` M1/M5/M15/M30/H1/H4/D1 etc.
|
||||
- `--model PATH` Model zip (default: models/ppo_{SYMBOL}_{TF}.zip; also checks notebooks/models/)
|
||||
- `--features PATH` JSON list of feature columns (default: models/selected_features.json)
|
||||
- `--volume 0.01` Lot size
|
||||
- `--live` Actually place orders (otherwise DRY‑RUN)
|
||||
- `--dry-run` Force dry‑run even if `--live` was set
|
||||
- `--order-comment DRL-Live` MT5 order comment (shows up in the terminal)
|
||||
- `--log-file logs/live_bot.log`
|
||||
- `--skip-market-check` Bypass weekend/stale‑tick guard
|
||||
- env: `WEEKEND_TRADING=true` Allow weekend trading (e.g., crypto)
|
||||
|
||||
> **Action mapping:** This CLI maps **`0=BUY, 1=HOLD, 2=SELL`** by default (legacy-friendly).
|
||||
> If your model uses **`0=BUY, 1=HOLD, 2=SELL`** (common in your legacy notebook), edit `action_to_signals(...)` in the file accordingly.
|
||||
|
||||
---
|
||||
|
||||
## .env example
|
||||
|
||||
See **.env.example** in this repo. Key fields:
|
||||
|
||||
```ini
|
||||
# MT5 connection
|
||||
MT5_LOGIN=12345678
|
||||
MT5_PASSWORD=your_password
|
||||
MT5_SERVER=YourBroker-Server
|
||||
MT5_PATH=C:\Program Files\MetaTrader 5 erminal64.exe
|
||||
|
||||
# Defaults (used if CLI flags are not provided)
|
||||
TRAINING_SYMBOL=EURUSD
|
||||
TIMEFRAME=M15
|
||||
VOLUME=0.01
|
||||
ORDER_COMMENT=DRL-Live
|
||||
|
||||
# Optional Telegram (enable in code where noted)
|
||||
TELEGRAM_BOT_TOKEN=
|
||||
TELEGRAM_CHAT_ID=
|
||||
|
||||
# Live behavior
|
||||
WEEKEND_TRADING=false
|
||||
ALGO=auto
|
||||
MAGIC=234002
|
||||
USE_SLTP=false
|
||||
SL_ATR=2.0
|
||||
TP_ATR=3.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backtesting
|
||||
|
||||
- Use `notebooks/3_Backtest.ipynb` for a full workflow:
|
||||
- Load test split
|
||||
- Roll the policy
|
||||
- Plot equity curve
|
||||
- Compute rough Sharpe (rescaled by bar frequency)
|
||||
- (Optional) `QuantStats` report
|
||||
|
||||
Minimal snippet you can adapt inside the notebook:
|
||||
```python
|
||||
from stable_baselines3 import PPO
|
||||
import pandas as pd, numpy as np, matplotlib.pyplot as plt
|
||||
|
||||
model = PPO.load("models/ppo_EURUSD_M15.zip")
|
||||
# df_test & feature_cols prepared earlier…
|
||||
obs, _ = env.reset()
|
||||
equity = [1.0]
|
||||
while True:
|
||||
action, _ = model.predict(obs, deterministic=True)
|
||||
obs, reward, terminated, truncated, info = env.step(int(action))
|
||||
equity.append(equity[-1] * (1.0 + reward))
|
||||
if terminated or truncated: break
|
||||
|
||||
equity = pd.Series(equity, index=df_test.index[:len(equity)])
|
||||
equity.plot(title="Equity Curve")
|
||||
plt.show()
|
||||
```
|
||||
|
||||
> Tip: export static assets (equity PNG, HTML report) to `reports/` and link them in your model registry notes.
|
||||
|
||||
---
|
||||
|
||||
## Broker adapter
|
||||
|
||||
All live operations go through `adapters/broker.py`. It should implement:
|
||||
|
||||
- `open_session(login, password, server, path) -> bool`
|
||||
- `close_session() -> None`
|
||||
- `fetch_last_n(symbol, timeframe, n) -> pd.DataFrame[open,high,low,close,tick_volume,…]`
|
||||
- `current_positions(symbol) -> pd.DataFrame[ticket,type,volume,profit,magic?,…]`
|
||||
- `place_market_order(symbol, side, volume, comment, sl=None, tp=None, **kwargs) -> dict`
|
||||
- (optional) `last_tick(symbol) -> dict` with `bid/ask/time`
|
||||
|
||||
> If you want **magic‑number scoping** and **ATR‑based SL/TP**, expose `magic` in positions and accept `sl/tp/deviation` in the order call, then wire the CLI through (tiny patch).
|
||||
|
||||
---
|
||||
|
||||
## Logging & Windows notes
|
||||
|
||||
- Console + rotating file logs (`logs/live_bot.log`).
|
||||
- On legacy Windows consoles you can also enable UTF‑8:
|
||||
- PowerShell: `[Console]::OutputEncoding = [System.Text.Encoding]::UTF8`
|
||||
- CMD: `chcp 65001`
|
||||
|
||||
---
|
||||
|
||||
## Safety checklist
|
||||
|
||||
- Start in **DRY‑RUN**. Inspect logs for a few bars.
|
||||
- Confirm **action mapping** matches your trained model.
|
||||
- Verify **volume**, **symbol**, **timeframe**, **order comment**.
|
||||
- Test with a **demo** account first.
|
||||
- Use **market guard** unless you’re sure about weekend/overnight behavior.
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: The bot says “market closed” on Saturday**
|
||||
A: Expected for most FX pairs. Either wait for Monday or set `WEEKEND_TRADING=true` and `--skip-market-check` (only if your instrument trades on weekends).
|
||||
|
||||
**Q: No trades are placed in DRY‑RUN**
|
||||
A: That’s by design. Add `--live` to actually send orders.
|
||||
|
||||
**Q: My BUY/SELL seem inverted**
|
||||
A: Update `action_to_signals(...)` to match your model’s action semantics (see note above).
|
||||
|
||||
---
|
||||
|
||||
## Backtesting Report
|
||||
|
||||
The `3_Backtest.ipynb` notebook evaluates all trained models and generates a comparison of their equity curves, along with detailed individual performance reports.
|
||||
|
||||
### Equity Curve Comparison
|
||||
================ ppo_EURUSD_M15.zip | PPO ================
|
||||
bars 9956.000000
|
||||
Sharpe 0.896809
|
||||
Sortino 1.245242
|
||||
CAGR 0.065507
|
||||
Calmar 1.755408
|
||||
MaxDD -0.037317
|
||||
WinRate 0.476195
|
||||
ProfitFactor 1.018795
|
||||
Exposure 0.995078
|
||||
Trades 238.000000
|
||||
AvgHoldBars 847.694255
|
||||
dtype: float64
|
||||
|
||||

|
||||

|
||||
### Individual Model Reports
|
||||
|
||||
- **[View PPO Report](notebooks/reports/quantstats_report_ppo_EURUSD_M15.html)**
|
||||
- **[View A2C Report](notebooks/reports/quantstats_report_a2c_EURUSD_M15.html)**
|
||||
- **[View DQN Report](notebooks/reports/quantstats_report_dqn_EURUSD_M15.html)**
|
||||
|
||||
> Note: You may need to download the HTML files to view the interactive charts. GitHub provides a static preview.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT (or your choice).
|
||||
|
||||
---
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This repository is for educational and research purposes only.
|
||||
Nothing herein constitutes financial, investment, or trading advice.
|
||||
Trading involves substantial risk. You are solely responsible for any
|
||||
use of the code and any resulting outcomes.
|
||||
|
||||
Reference in New Issue
Block a user