Doctor Money
A systematic Bitcoin
trend-following algorithm
Long-only, 24/7, running on Kraken. Enters on 4h EMA crossovers confirmed by six independent filters. Exits via a ratcheting ATR trailing stop. No discretion - every decision is deterministic.
BTC / GBP
Kraken
4-hour candles
240 min
Long-only
No shorts
Paper + live
Opt-in live
6 confirmation layers
All must pass
Multi-leg
Up to 2 concurrent
+108%
Net return
Jan 2024 – Mar 2026 backtest
8.2%
Max drawdown
Single trailing stop config
50%
Win rate
6 trades over 26 months
8.06×
Profit factor
Gross winners / gross losers
Backtested on Kraken OHLCV data. Past performance is not indicative of future results. Paper mode by default - live trading requires explicit opt-in.
Strategy overview
Quality over quantity
The algorithm makes very few trades - typically one to six per quarter. Each entry requires all six independent confirmations to align simultaneously. This is by design: fewer, higher-conviction trades with longer hold times produce better risk-adjusted returns than frequent signals in a noisy market.
Backtesting BTC/GBP 2024–2026 shows bearish EMA crossovers have negative expected value - price rises after short-side signals more often than not. The strategy is therefore long-only and holds winning positions for weeks rather than days.
Filter the noise
ATR% and ADX gates reject flat, directionless markets before any other evaluation runs.
Confirm the trend
Price must be above the 200-bar EMA and the daily EMA(50). Trend alignment on two timeframes.
Detect the breakout
EMA(9) must freshly cross above EMA(21) - a one-bar event. Continuation signals are ignored.
Gate on momentum
MACD histogram must be positive at the cross. Bollinger squeeze must have occurred within 20 bars.
Size and trail
Position sized to risk exactly 2% of equity. ATR trailing stop ratchets up every candle.
Signal engine
How a trade fires
Every candle close runs through a layered evaluation. All conditions must pass in sequence for a BUY to fire. Click any layer to see the full logic.
BUY signal fires
All required layers passed - position opened at current candle close. Risk manager calculates size and sets ATR-based stops. L7 (VWAP) is optional and disabled by default.
Technical indicators
Eight inputs, one signal
Each indicator serves a specific role in the decision pipeline. Select one to see how it is calculated and why it is here.
Select an indicator to see its formula and role in the signal pipeline.
Risk management
Sizing, stops, and safeguards
Every position is sized to risk exactly the same fraction of equity. Stops are calculated from ATR - not arbitrary percentages.
Each trade risks a fixed fraction of current account equity. As the account grows, position sizes grow proportionally. As it shrinks, they shrink. No fixed lot sizes.
free_gbp × RISK_PER_TRADEFraction of uncommitted GBP risked. Capital already committed to open legs is excluded from sizing.
SL_ATR_MULTIPLIER × ATRHow far price must move before the initial stop is hit.
risk_amount / stop_distanceSized so that if the stop is hit, loss equals exactly risk_amount.
position_size_btc × entry_priceExecution model
How signals become orders
Signal fires at candle close
Every 4h candle close triggers indicator recalculation. If all conditions pass, a BUY is recorded at the current close price. The position cannot be opened and closed on the same candle.
Stop and take-profit checked from the next candle
From candle[i+1] onward, each candle's high and low are checked against the stop loss and take-profit. If the low touches the stop, the position closes at the stop price. If both SL and TP are touched in the same bar, SL wins (pessimistic assumption).
Trailing stop updated every candle
On every closed candle, the stop is moved to max(current_stop, candle.high − trailing_distance). ATR is frozen at the value measured at entry - the trail distance does not expand during volatile reversals.
Fees deducted at close
Kraken taker fees (0.26% per side) are calculated on the full notional and deducted from realised PnL. The position sizing formula accounts for this - the risk amount represents net-of-fee expected loss if the initial stop is hit.
Second leg opens when new balance is available
If a BUY signal fires while a position is already open and uncommitted GBP is available (e.g. a deposit just landed), the bot opens a second independent leg at the current price with its own stop-loss, take-profit, and trailing stop. The two legs are sized and managed separately and close independently. A MACD exit (if enabled) closes all legs simultaneously. Capped at MAX_OPEN_POSITIONS (default 2).