A quantitative, rule-based market-analysis and decision-support system for crypto and FX — with transparent signal logic, full backtesting, a Telegram bot front-end, and a machine-learning pipeline in active development.
Status: Working (rule engine + backtester + bot) · ML layer in progress Role: Sole developer — design, quant logic, data engineering, deployment Stack: Python 3.12 · pandas · NumPy · matplotlib / mplfinance · python-telegram-bot · DuckDB · scikit-learn (planned)
Crypto Analyser ingests market candle data, scores each bar against a stack of 10 deterministic quantitative rules, and produces a clear BUY / WAIT decision — with every rule’s individual pass/fail shown. Nothing is hidden behind a black box: if the tool says WAIT, you can see exactly which rule(s) failed and why.
It is deliberately a decision-support tool, not an autotrader. It does the maths, quantifies the risk, and presents the evidence; the human makes the final call. This design choice keeps the logic auditable and the user accountable — which is also what makes it a good base for layering machine learning on top.
The project is now being extended from purely hand-tuned thresholds toward a data-driven model that learns which setups historically led to profitable outcomes.
Most retail trading tools fall into two camps: opaque “signal” services that just print BUY/SELL with no reasoning, or raw charting tools that leave all the analysis to you. Both make it hard to learn why a decision is good or bad.
Crypto Analyser sits in between:
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Candle │ │ Indicator │ │ 10-Rule │ │ Decision + │
│ data │──▶│ computation │──▶│ scoring │──▶│ risk sizing │
│ (API+cache) │ │ (SMA, RSI, vol) │ │ (all-pass = BUY)│ │ + breakdown │
└─────────────┘ └──────────────────┘ └─────────────────┘ └──────────────┘
│ │
└────────────────────────▶ Backtester ◀──────────────────────┘
(validate on history)
Candles are fetched from public market APIs (Binance / Coinbase for
crypto, yfinance for FX) — no account or API key
required for the core analysis. Results are cached to local
CSVs (data/{SYMBOL}_{INTERVAL}.csv) so repeated runs are
fast and work offline. Supports BTC, ETH and FX pairs across timeframes
from 1-minute to 1-day.
From the raw OHLCV candles the engine derives:
(high − low) / close, plus rolling averages over several
windows to detect volatility contraction (a calm market about
to move).This is the heart of the system (src/signal.py). Each bar is graded against
10 independent rules. All 10 must pass
to produce a BUY; a single failure yields WAIT. Each rule is also
exported as its own column (r_trend, r_rsi, …)
so the output is fully transparent.
| # | Rule | What it checks | Why it matters |
|---|---|---|---|
| 1 | Trend | Close above short SMA and SMA rising | Only buy when momentum is up |
| 2 | Entry band | Price within X% above the short SMA | Don’t chase an overextended candle |
| 3 | Stability | Today’s range ≤ recent average range × multiplier | Avoid abnormally volatile bars |
| 4 | Regime | Close above long SMA (with tolerance) | Confirm the broader uptrend |
| 5 | Volatility contraction | Short-window range ≤ long-window range | Enter as volatility coils, not expands |
| 6 | Volume | Volume ≥ rolling median | Require genuine participation |
| 7 | Price rising | Close ≥ close N bars ago | Confirm price has stopped falling |
| 8 | Sideways filter | 5-bar range/mean below threshold | Prefer calm, range-bound setups |
| 9 | Not stuck | Fewer than N consecutive closes below SMA | Reject persistently weak assets |
| 10 | RSI | RSI below overbought threshold | Avoid buying into an exhausted rally |
A WAIT is also returned for the warm-up period until
enough history exists (min_history) for the indicators to
be valid.
Signals are useless without sizing. The risk module (src/risk.py) implements fixed-fractional position sizing:
risk_usd = portfolio_value × risk_per_trade% (e.g. 2%)
risk_per_unit = entry_price − stop_price (e.g. 3% below entry)
quantity = risk_usd / risk_per_unit
So you always risk a fixed fraction of your portfolio per trade, regardless of the asset’s price. The module also tracks every exit condition:
Before trusting the rules, you can simulate them on historical data (src/backtest.py). The backtester is built to avoid the usual beginner traps:
It reports the metrics that actually matter:
The current engine relies on hand-tuned thresholds. The next phase replaces fixed thresholds with a model that learns entry quality from historical outcomes.
Built so far — a labelled dataset pipeline (ml/prepare_dataset.py) that:
fwd_peak_return / fwd_trough_return — best
high / worst low over the next 168 hours (7 days).label_hit_3pct / label_hit_5pct — did
price reach the +3% / +5% target?label_valid_window) so partial rows at the end of the
series are dropped cleanly.Planned — time-based train/test split (no shuffling,
to respect causality) and scikit-learn models that predict
the probability of a successful entry. This turns the binary BUY/WAIT
output into a ranked, probability-weighted signal, and
lets the system learn relationships the fixed rules can’t express.
The analysis runs as a live monitoring service via Telegram (monitor.py, src/telegram_bot.py):
Agg mode).Deployment — runs as a background worker on Railway
or any VPS via the included Procfile
(worker: python monitor.py) and runtime.txt
(Python 3.12). A persistent volume mounted at /app/data
keeps trade history (my_trades.json), bot state
(alert_state.json), and cached candles across
redeploys.
crypto-analyser/
├── run.py # CLI entry point
├── config.py # ALL tuneable strategy parameters (single source of truth)
├── monitor.py # Telegram monitoring bot / scheduler
├── src/
│ ├── data.py # API fetching + CSV caching
│ ├── signal.py # 10-rule deterministic scoring engine
│ ├── risk.py # Position sizing + stop-loss / exit logic
│ ├── backtest.py # Historical simulation (next-bar entry, real fees)
│ ├── display.py # Terminal dashboard
│ ├── chart*.py # Chart rendering
│ └── telegram_*.py # Bot commands, callbacks, charts
├── ml/
│ └── prepare_dataset.py # Feature + label pipeline for ML
└── data/ # Cached candle CSVs + trade/state JSON
Design principles
config.py; the engine also accepts per-call overrides for
per-timeframe chart analysis, without touching engine code.# Install
pip install -r requirements.txt
# Today's analysis (ETH by default)
python run.py
# Analyse BTC on 4-hour candles
python run.py --symbol BTCUSDT --interval 4h
# Backtest the strategy over 2 years of history
python run.py --backtest --days 730
# Check exit conditions for a position you're already holding
python run.py --holding 2500 --peak 2800 --held-days 12
# Run the live Telegram monitoring bot
python monitor.py
# Build the ML training dataset
python -m ml.prepare_dataset --days 400 --symbols ETHUSDT| Area | Tools |
|---|---|
| Core / quant | Python 3.12, pandas, NumPy |
| Visualisation | matplotlib, mplfinance |
| Bot / delivery | python-telegram-bot, Railway deployment |
| Market data | Binance & Coinbase APIs, yfinance (FX) |
| Analytical store | DuckDB, PyArrow / Parquet |
| ML (in progress) | scikit-learn (planned) |
Educational analysis tool only. Not financial advice. Always do your own research and never risk more than you can afford to lose.