This project implements a quantitative trading algorithm in Python that dynamically allocates capital between two assets and cash. The core idea is a custom Channel Breakout strategy: it measures where each asset's current price sits relative to its recent high/low range, then translates that into a portfolio weight.
The bot was submitted during the PoC × Ramify Hackathon, where participants competed to maximize risk-adjusted returns on a provided historical dataset.
For each asset, the algorithm computes its normalized position within a rolling price channel:
This gives a value between 0 (at the bottom of the channel) and 1 (at the top), indicating the relative strength of the current price move.
| Asset | High window | Low window | Sensitivity |
|---|---|---|---|
| Asset A | 30 periods | 10 periods | Squared (^2.0) — noise filter |
| Asset B | 13 periods | 4 periods | Power 0.7 (^0.7) — aggressive |
- Asset B is allocated first (higher priority / higher volatility play).
- Asset A fills the remaining allocation proportionally to its signal.
- Whatever is left goes to Cash — the bot stays defensive when signals are weak.
weight_B = clamp(signal_B × 10)
remaining = 1 - weight_B
weight_A = remaining × clamp(signal_A)
weight_Cash = 1 - weight_A - weight_B
The bot holds 100% cash for the first 35 epochs while building a sufficient price history.
trading_bot/
├── bot_trade.py # Core strategy: signal calculation & allocation logic
├── main.py # Entry point: data loading, decision loop, scoring
└── README.md
| File | Role |
|---|---|
bot_trade.py |
make_decision(epoch, priceA, priceB) — the brain of the bot |
main.py |
CLI runner, CSV parsing, decision validation, scoring display |
- Python 3.8+
pandasmatplotlib
Install dependencies:
pip install pandas matplotlibNote: This project also depends on a
scoring/module provided by the hackathon organizers (not included in this repo). Without it,main.pycannot run, butbot_trade.py— the core strategy — is fully standalone.
python main.py <path_to_prices.csv>Display the performance graph:
python main.py <path_to_prices.csv> --show-graphThe CSV file must have two columns (Asset A, Asset B) indexed by epoch:
epoch,Asset A,Asset B
0,100.0,50.0
1,101.2,49.8
...
Every decision is automatically validated to ensure:
- Keys are exactly
{'Asset A', 'Asset B', 'Cash'} - All values are in
[0, 1] - Weights sum to exactly
1.0
Epoch 50:
Asset A price: 105.3 → channel pos (30/10): 0.72 → signal: 0.52
Asset B price: 48.1 → channel pos (13/4): 0.88 → signal: 0.91
weight_B = min(1.0, 0.91 × 10) = 1.0 → 100% in Asset B (strong breakout)
remaining = 0.0
weight_A = 0.0
weight_Cash = 0.0
Decision: {'Asset A': 0.0, 'Asset B': 1.0, 'Cash': 0.0}
Mathis Haba — Second-year student at Epitech
Passionate about algorithms and quantitative finance.
This project is licensed under the MIT License — see the LICENSE file for details.