Training the brain

🦉 AthenaAI is an AI-powered ensemble machine-learning trading bot for PocketOption, built on BinaryOptionsToolsV2Get it on GitLab
💬 Need help? Join the Chipa Discord · ⚡ Go no-code with ChipaEditor

train.py is the standalone trainer. It builds the bot’s model state (the “brain”) from a historical candle CSV — no PocketOption connection, no session ID, no network access required. The resulting brain file is what main.py loads at startup via PO_BRAIN_PATH.

The trainer automatically uses your GPU for the neural model when PyTorch with CUDA (NVIDIA) or MPS (Apple Silicon) is available; everything else runs on CPU with scikit-learn. See GPU training.

Quick start

python train.py                                   # EURUSD_M1.csv → athena_brain.pkl
python train.py --data GBPUSD_M1.csv --out brains/gbpusd.pkl
python train.py --expiry 120                      # label for 2-minute trades
python train.py --no-nn                           # skip the neural model
python train.py --cpu --epochs 50                 # force CPU, train longer
python train.py --check-gpu                       # show detected device and exit

A successful run ends with a walk-forward report and:

✅ Training complete — brain saved to athena_brain.pkl

Point the bot at it (this is already the default path):

PO_BRAIN_PATH=athena_brain.pkl python main.py

Command-line overview

Each flag has its own page in the CLI reference; this table is the summary.

FlagDefaultDescription
--dataEURUSD_M1.csvInput candle CSV. HistData semicolon format or any headered CSV (see Data formats).
--outathena_brain.pklOutput brain file. Must match the bot’s PO_BRAIN_PATH. Parent directories are created automatically.
--timeframe60Seconds per candle in the dataset. Must match the data (e.g. 60 for M1).
--expiry300Trade duration to label for, in seconds. Train for the expiry you actually intend to trade — a brain labeled for 5-minute outcomes is not optimal for 1-minute trades.
--window20Rolling window (in candles) used by the feature engine’s indicators.
--lookback200Maximum candle history fed into each feature vector.
--max-candles500000Keep only the N most recent candles. Bounds memory and training time on large histories.
--test-split0.30Fraction of samples (the most recent, chronologically) held out for the walk-forward test. Never trained on.
--no-nnoffSkip the neural model entirely; train the sklearn ensemble only.
--cpuoffForce CPU even when a GPU is detected.
--epochs30Neural model training epochs.
--batch-size2048Neural model mini-batch size. Lower it if you hit GPU out-of-memory errors.
--lr0.001Neural model learning rate (AdamW).
--hidden128,64Neural hidden layer sizes, comma-separated (e.g. 256,128,64).
--check-gpuPrint the detected training device and exit without training.

How --expiry and --timeframe interact

Each sample is labeled by looking expiry / timeframe candles into the future (the label horizon). With the defaults, 300 s expiry on 60 s candles means: “did the close rise 5 candles later?” If you retrain for a different expiry, keep --timeframe matched to the dataset’s actual candle period — it describes the data, not a preference.

Data formats

The trainer’s load_candles() (src/training/dataset.py) auto-detects HistData semicolon files and headered CSVs (comma or semicolon delimited), covering histdata.com and MetaTrader 5 exports out of the box. Malformed rows are skipped silently. Full column/timestamp specification: Data formats.

Requirements: at least 50 parsed candles to run at all, and at least 200 valid samples after feature generation. Realistically you want tens of thousands of candles — a month of M1 data (~30k candles) is a reasonable minimum, a year or more is better.

What the trainer does

The pipeline in src/training/trainer.py:

  1. Load & trim — parse the CSV, keep the most recent --max-candles.
  2. Build samples — slide over the candles; for each position, compute a feature vector from the preceding --lookback candles and label it 1 if the close is higher after the label horizon (a CALL would win) or 0 if lower. Flat closes are skipped. On datasets above ~20k samples this fans out across up to 16 CPU worker processes.
  3. Chronological split — the last --test-split fraction is held out. There is no shuffling: the model is always tested on data strictly newer than anything it trained on (walk-forward), which prevents look-ahead leakage and gives an honest estimate.
  4. Train online models — SGD, Passive-Aggressive, and Naive Bayes are fed the training samples in chunks via partial_fit, mirroring how they learn incrementally during live trading.
  5. Train batch models — Gradient Boosting and Random Forest are fit on the full training set (Random Forest uses all CPU cores).
  6. Train the neural model (unless --no-nn) — a PyTorch MLP (TorchMLPClassifier) with ReLU + dropout layers trains on the GPU when available. Its holdout accuracy becomes its vote weight inside the ensemble, so a weak net simply gets less say rather than poisoning predictions.
  7. Walk-forward evaluation — the full ensemble predicts every holdout sample and reports the honest win rate (see below).
  8. Save — the entire ensemble is pickled to --out. See Persistence for exactly what’s inside.

Reading the walk-forward report

🧪 WALK-FORWARD TEST (30% holdout): 41780 trades
   Win: 22120 | Loss: 19660 | HONEST WR: 52.9%
   ✅ EDGE: +0.8% above breakeven (52.1%)
  • HONEST WR is the win rate on data the models never saw, in chronological order — the closest offline proxy for live performance.
  • Breakeven is derived from the payout (default 0.92 in TrainerConfig): with a 92% payout you must win 1 / 1.92 ≈ 52.1% of trades just to break even.
  • EDGE is the margin above breakeven. Even +1–2% is meaningful at volume; a result below breakeven means the brain would lose money on this data — don’t deploy it, get more/better data or adjust parameters.

Note that live results will differ: the bot additionally applies confidence gating (PO_MIN_CONF/PO_MAX_CONF) and indicator alignment, which filter out the weakest signals the walk-forward test still counts.

GPU training

python train.py --check-gpu
# Device: cuda  (GPU: NVIDIA GeForce RTX 4070 (12.0 GB VRAM))
  • NVIDIA: install a CUDA build of PyTorch, e.g. pip install torch --index-url https://download.pytorch.org/whl/cu121.
  • Apple Silicon: plain pip install torch — MPS is detected automatically.
  • No PyTorch at all: the trainer logs PyTorch not installed — skipping neural model and the sklearn ensemble still trains fine.

Only the neural model uses the GPU. Sample generation and the sklearn models are CPU-bound regardless.

Portability: the MLP stores its weights as a CPU state dict inside the brain file, so a brain trained on a GPU machine loads and predicts on a CPU-only machine. If PyTorch is missing on the loading machine, the MLP degrades to a neutral 0.5 vote instead of breaking the brain. Details: GPU training.

Recipes

Retrain for a different asset:

python train.py --data GBPUSD_M1.csv --out gbpusd_brain.pkl
PO_ASSET=GBPUSD PO_BRAIN_PATH=gbpusd_brain.pkl python main.py

Match training to your live expiry — if the bot trades with PO_DEFAULT_EXPIRY=120, label for that duration:

python train.py --expiry 120

Fast iteration while experimenting:

python train.py --max-candles 100000 --no-nn

Squeeze out more from the neural model:

python train.py --epochs 60 --hidden 256,128,64 --lr 5e-4

Troubleshooting

SymptomCause / fix
Dataset too small (N candles)Fewer than 50 candles parsed. Check the file path and that the format matches Data formats — the log prints which columns/format were detected.
Only N valid samples — need at least 200Data parsed but too short after the feature warm-up and horizon are trimmed. Use a longer history.
Parsed far fewer candles than expectedTimestamp format not recognized; rows are skipped silently. Compare the file’s date column with Data formats.
PyTorch not installed — skipping neural modelInformational, not an error. pip install torch to enable it, or pass --no-nn to silence it intentionally.
--check-gpu says CPU despite having an NVIDIA GPUYou have the CPU-only PyTorch wheel. Reinstall from the CUDA index URL above.
CUDA out of memoryLower --batch-size (e.g. 512), or shrink --hidden.
Holdout too small — skipping walk-forward testFewer than 100 holdout samples. Use more data or a larger --test-split.
Training is slow on sample generationIt parallelizes automatically above ~20k samples; cap the data with --max-candles or reduce --lookback if it’s still too slow.
Walk-forward WR below breakevenThe models found no edge on this data. Try more history, a different --expiry, or a different asset — do not deploy the brain live.

More general problems: Troubleshooting.

See also

💬 Questions about running AthenaAI? Ask in the #trading-bots channel on the Chipa Discord — and if you’d rather design strategies without touching Python, try ChipaEditor.