src.training.trainer
π¦ AthenaAI is an AI-powered ensemble machine-learning trading bot for PocketOption, built on BinaryOptionsToolsV2 β Get it on GitLab
π¬ Need help? Join the Chipa Discord Β· β‘ Go no-code with ChipaEditor
Source: src/training/trainer.py. The standalone trainer: trains the full ensemble (online SGD/PA/NB + batch GBM/RF + optional GPU MLP) on a historical CSV and saves a brain file the live bot loads at startup. Run via train.py (see the CLI reference); the package re-exports Trainer, TrainerConfig, and detect_device from src/training/__init__.py.
@dataclass TrainerConfig
| Field | Type | Default | Meaning |
|---|---|---|---|
dataset_path | str | "EURUSD_M1.csv" | Input candle CSV (--data) |
brain_path | str | "athena_brain.pkl" | Output brain file β matches main.pyβs PO_BRAIN_PATH default (--out) |
timeframe | int | 60 | Seconds per candle (--timeframe) |
expiry | int | 300 | Trade duration to label for, seconds (--expiry) |
feature_window | int | 20 | Rolling feature window in candles (--window) |
lookback | int | 200 | Max candle history per feature vector (--lookback) |
max_candles | int | 500_000 | Keep only the N most recent candles (--max-candles) |
test_split | float | 0.30 | Walk-forward holdout fraction (--test-split) |
online_batch | int | 5000 | partial_fit chunk size (no CLI flag) |
payout | float | 0.92 | Payout fraction used only for the breakeven-WR display (no CLI flag) |
use_nn | bool | True | Train the neural model (--no-nn sets False) |
force_cpu | bool | False | Skip GPU detection (--cpu) |
nn_epochs | int | 30 | MLP epochs (--epochs) |
nn_hidden | tuple | (128, 64) | MLP hidden layer sizes (--hidden) |
nn_batch_size | int | 2048 | MLP mini-batch size (--batch-size) |
nn_lr | float | 1e-3 | MLP learning rate (--lr) |
class Trainer
__init__(self, cfg: TrainerConfig)
Creates a fresh EnsemblePredictor and FeatureEngine, and resolves the training device via detect_device(force_cpu=cfg.force_cpu).
run(self) -> dict
The full pipeline. Returns the walk-forward metrics dict (see _walk_forward). Steps:
- Banner β logs dataset/brain paths and the device line (
β‘ Training device: β¦orπ₯ β¦). - Load candles β
load_candles(cfg.dataset_path). Fewer than 50 candles βraise SystemExit("Dataset too small (N candles)."). More thanmax_candlesβ keep the most recent. - Build samples β label horizon =
max(1, expiry // timeframe)candles;build_samples(...)produces(X, y)wherey=1means the close rose over the horizon (CALL wins). Fewer than 200 samples βSystemExit. - Chronological split β no shuffle (walk-forward): first
1 β test_splitfor training, the rest held out. - Online models β feed training samples to the ensemble in
online_batch-sized chunks, callingensemble.partial_fit()after each chunk (this also fits the scaler). - Batch models β
ensemble.train_batch_models()(GBM + RF; RF already uses all CPU cores). - Neural model β
_train_nn(...)unlessuse_nnisFalse. - Walk-forward evaluation β
_walk_forward(test_X, test_y). - Save β creates the output directory (
os.makedirs(..., exist_ok=True)), thenensemble.save_brain(cfg.brain_path)and logsβ Training complete β brain saved to <path>.
Note the trainer does not write the _expiry.pkl companion file β expiry stats are learned live only.
_train_nn(self, train_X, train_y, test_X, test_y) (internal)
Imports TorchMLPClassifier and torch; if PyTorch is missing, logs PyTorch not installed β skipping neural model (pip install torch for GPU training). and returns β training continues without the MLP.
Otherwise: builds the MLP with cfg.nn_hidden / nn_epochs / nn_batch_size / nn_lr on the detected device, fits it on scaler-transformed training data, and measures holdout accuracy (0.5 if the holdout is empty). The holdout accuracy becomes the modelβs vote weight (accuracy_ema) in the ensemble. It then removes any existing "MLP" entry from ensemble._batch_models, appends {"name": "MLP", "clf": mlp, "accuracy_ema": acc}, and sets _batch_fitted = True. Because EnsemblePredictor.load_brain() rebuilds _batch_models from the saved list, the MLP survives the round-trip into the live bot, where it votes with weight acc Γ 0.75 like the other batch models.
_walk_forward(self, test_X, test_y) -> dict (internal)
If the holdout has fewer than 100 samples, warns and returns {"samples": 0}. Otherwise predicts each holdout sample (direction only β confidence ignored; unlike the botβs _load_dataset, no online learning during the test), counts wins/losses, and logs:
π§ͺ WALK-FORWARD TEST (30% holdout): 41230 trades
Win: 21876 | Loss: 19354 | HONEST WR: 53.1%
β
EDGE: +1.0% above breakeven (52.1%)
Breakeven = 1 / (1 + payout) Γ 100 with payout = 0.92 β β 52.1%. Returns {"samples", "wins", "losses", "win_rate", "breakeven"} (win_rate and breakeven in percent).
Usage example
from src.training import Trainer, TrainerConfig
cfg = TrainerConfig(dataset_path="EURUSD_M1.csv", brain_path="athena_brain.pkl",
expiry=300, use_nn=True)
metrics = Trainer(cfg).run()
print(metrics["win_rate"], metrics["breakeven"])
Or from the shell: python train.py --data EURUSD_M1.csv --expiry 300 β see the training guide.
Risk note
A walk-forward win rate above breakeven on historical data does not guarantee live profitability. Binary options trading can lose money.
See also
π¬ Unsure how this interacts with the rest of the configuration? Ask in the Chipa Discord β or prototype strategies no-code with ChipaEditor.