src.training.dataset
🦉 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/dataset.py. Dataset loading and training-sample generation, extracted from the bot so training can run standalone (via train.py) without a PocketOption connection.
load_candles(path: str) -> list[Candle]
| Parameter | Type | Meaning |
|---|---|---|
path | str | Path to the candle CSV |
Returns a chronological list[Candle] (order as in the file). Opens with encoding="utf-8-sig" (BOM-tolerant). Two formats are auto-detected from the first line:
- HistData semicolon format — first line contains
;but none oftime/open/high/date(case-insensitive): headerless rowsYYYYMMDD HHMMSS;open;high;low;close[;volume]. A time string of only 8+ chars is parsed as a date-onlyYYYYMMDD. Rows with < 5 fields or parse errors are skipped silently. - Headered CSV — comma- or semicolon-delimited
csv.DictReader. Time column:time,timestamp,date, orDate; parsed asYYYY-MM-DD HH:MM:SSwhen it contains both-and:, otherwise as a numeric epoch float. OHLC columns accept lower- or capitalized names (open/Open…). Volume falls back throughtick_volume→volume→Volume→real_volume→ 0.
Timestamps are produced with naive datetime.strptime(...).timestamp(), i.e. interpreted in the local timezone of the machine. Side effects: log lines Loading dataset from … , format detection, and Parsed N candles from file. Failure: FileNotFoundError propagates; malformed rows never raise.
See the data formats guide for examples of both formats.
build_samples(candles, feature_engine, window=20, lookback=200, label_horizon=5) -> tuple[np.ndarray, np.ndarray]
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candles | list[Candle] | — | Chronological candles |
feature_engine | FeatureEngine | — | Engine used to compute each feature vector (pickled to workers, so its mask travels too) |
window | int | 20 | Rolling feature window |
lookback | int | 200 | Max trailing candles per feature vector |
label_horizon | int | 5 | Candles ahead used for the label (the trainer passes expiry // timeframe) |
Slides over indices [max(window, 26), len(candles) − label_horizon). For each index i: compute features on candles[i−lookback : i+1] (skip if None), np.nan_to_num them, and label 1 if close[i+horizon] > close[i] (CALL wins), 0 if lower; flat closes are skipped.
Returns (X, y) — X an (n, 57) float array (np.vstack), y int64. If no samples were produced, returns (np.empty((0, 0)), np.empty((0,))).
Parallelism internals
- Worker count:
min(os.cpu_count(), 16). Runs serially when workers ≤ 1 or there are fewer than 20,000 candidate indices. - Otherwise the index range is split into
workerscontiguous chunks. Each task ships a self-contained candle slice (its range pluslookbackcontext before andlabel_horizonafter) to aProcessPoolExecutor, so worker processes never share memory. Progress is logged as chunks finish (… N samples generated (k/n chunks done)), and results are reassembled in chronological chunk order regardless of completion order — output is deterministic. - Because it uses process workers, calling
build_sampleson a large dataset from your own script requires the standardif __name__ == "__main__":guard on Windows.
_build_range(...) / _build_range_task(args) (internal)
_build_range(candles, start, end, feature_engine, window, lookback, label_horizon) is the serial core returning (list[np.ndarray], list[int]); _build_range_task is the picklable worker entry point that unpacks a task tuple and returns (order, X, y).
Usage example
from src.core.feature_engine import FeatureEngine
from src.training.dataset import load_candles, build_samples
if __name__ == "__main__":
candles = load_candles("EURUSD_M1.csv")
X, y = build_samples(candles, FeatureEngine(), window=20,
lookback=200, label_horizon=5) # 5 x 60s = 300s expiry
print(X.shape, y.mean()) # fraction of CALL-win labelsSee also
- trainer.md — the pipeline that calls these functions
- Data formats guide
💬 Unsure how this interacts with the rest of the configuration? Ask in the Chipa Discord — or prototype strategies no-code with ChipaEditor.