A taxonomy of strategies
There are only a handful of genuinely distinct ways to make money in markets, and each one is a bet on a specific recurring behaviour: that trends persist, that ranges hold, that cheap risk pays a premium, that a temporary imbalance will correct. This chapter is a field guide to the archetypes — for each, the mechanism, the market behaviour it exploits, when it works and when it dies, a one-line signal sketch, and whether edgekit ships a template you can start from.
SmaCross (a trend-following crossover) and ORB (an opening-range breakout). The other families are described conceptually; some you would assemble from the indicator primitives. None of them is presented as a working edge — an archetype is a hypothesis, and the gauntlet decides whether any given instance is real.The families at a glance#
| Family | Typical horizon | What it exploits | Main risk | edgekit template |
|---|---|---|---|---|
| Trend-following | Days–months | Persistence / autocorrelation of returns | Whipsaw in ranges; long flat stretches | SmaCross |
| Breakout | Intraday–days | Range expansion / volatility clustering | False breaks; chop | ORB |
| Momentum (cross-sectional) | Weeks–months | Winners keep winning vs peers | Crashes / sharp reversals | conceptual |
| Momentum (time-series) | Weeks–months | An asset's own trend sign | Regime flips; beta in disguise | conceptual |
| Mean-reversion | Minutes–days | Overreaction reverting to a mean | Trends that don't revert (fat left tail) | conceptual |
| Statistical arbitrage / pairs | Hours–days | A stable relationship between assets | Relationship breaking (de-cointegration) | conceptual |
| Carry | Weeks–months | A premium for holding a position | Rare, violent unwinds | conceptual |
| Market-making | Sub-second–minutes | The bid-ask spread; liquidity provision | Adverse selection; inventory | out of scope |
| Event-driven | Event-scoped | Predictable reaction to scheduled news | Gaps; slippage; surprise direction | conceptual |
| ML-based | Any | Weak patterns across many features | Overfitting; leakage | Part V |
Trend-following#
Mechanism. Buy what is going up, sell what is going down, and hold until the trend gives way. Entries key off a moving-average relationship or a channel; exits are trailing, so winners run and losers are cut quickly. What it exploits: positive autocorrelation of returns — the empirical tendency for large moves to extend as capital, information, and herding push in one direction over weeks to months.
Signal sketch: (or when price breaks the -bar high). Works in strong, sustained directional regimes and across many uncorrelated markets at once (diversification smooths the flat spells). Fails in choppy, range-bound markets, where the crossover flips repeatedly and every entry is a small loss; the return profile is a low win rate rescued by a fat right tail, so it demands patience through long drawdowns. edgekit ships SmaCross.
from edgekit.strategy import SmaCross
trades = SmaCross(fast=20, slow=100, atr_n=20, stop_mult=2.0).backtest(h4, warmup=210, bars_per_day=6)Scenario (what it feels like to trade). On BTCUSDT H4 the fast MA crosses up through the slow at 64,900 and you go long with a 2-ATR stop. Price grinds to 78,000 over six weeks and the trail eventually closes you at 74,500 — a fat winner. But that one trade sat inside a run of nine entries: the other eight were small whipsaws in choppy stretches, each closing near . Net across the nine you are positive only because the single trend paid for all the paper cuts. That lopsided arithmetic — many small losers, one outsized winner — is the trend-following experience, and why you must survive the flat stretches to collect the one that matters.
Breakout#
Mechanism. Define a reference range — an opening range, a prior-day range, an -bar channel — and act when price escapes it, stop at the opposite edge. What it exploits: volatility clustering and range expansion — quiet coils tend to resolve into directional bursts, and the moment of escape often precedes the largest part of the move.
Signal sketch: , stop at the range low. Works when a real catalyst drives follow-through (news, session opens, regime shifts). Failsas the classic “false breakout”: price pokes through, triggers the crowd, and snaps back — so unfiltered breakouts are typically net-negative after costs, and the edge, if any, lives in filtering which breaks to trust. edgekit ships ORB (opening-range breakout).
from edgekit.strategy import ORB
rth = bars[ek.data.rth_mask(bars.index, start="09:30", end="16:00", tz="America/New_York")]
trades = ORB(or_bars=30, target_r=2.0).backtest(rth, warmup=5, bars_per_day=390)Scenario (a true break and a false one). US100 opens at 09:30 New York; the first 30 minutes carve a range of 40 points (18,000–18,040). That 40-point width is 1R. Monday: at 10:05 price prints 18,041, the buy-stop triggers, a fresh CPI-driven trend carries it to 18,120 and the 2R target (18,120) fills — . Tuesday: same setup, price ticks to 18,042, triggers the long, then immediately sags back inside the range and slides to 17,999 — stopped at the lower edge for . Identical mechanics, opposite outcome; the raw signal cannot tell them apart in advance, which is the whole reason the edge (if any) lives in a filter, not the break.
ORB across a full history is typically net-negative after costs — that is the honest baseline, and exactly why it makes a good teaching example. Any edge comes from a selection layer (a volatility gate, a retest entry, a meta-label) applied on top, not from the breakout itself.Momentum#
Momentum splits into two related but distinct constructions.
Cross-sectional momentum#
Mechanism. Rank a universe of assets by recent return; go long the top slice, short the bottom, rebalance periodically. It is a relative bet — long the strongest against the weakest — and is naturally market-neutral-ish. Exploits: the persistence of relative performance (winners keep beating losers over weeks to months). Signal sketch: . edgekit ships the cross_sectional_rank primitive for the ranking; the strategy is conceptual.
ranks = ek.indicators.cross_sectional_rank(trailing_return_matrix) # 1.0 = strongest that dateFailsin momentum crashes — sharp reversals where yesterday's losers rip and the short book is run over. The left tail is brutal and clustered.
Time-series momentum#
Mechanism. Trade each asset on the sign of its own trailing return, independent of peers — long if it has been going up, short if down. Exploits: the same persistence, per-asset. Signal sketch: . The trap here is that long-only time-series momentum on a rising asset is often just beta — market exposure dressed as alpha — so the honest test is whether the short side also pays (see alpha vs beta). Conceptual in edgekit.
Mean-reversion#
Mechanism. Fade extremes: buy when price is stretched far below a reference, sell when stretched far above, exit as it reverts. Exploits:short-horizon overreaction — order-flow imbalances and liquidity gaps that push price away from “fair” and then correct. Signal sketch: using the rolling z-score. Works in range-bound, liquid markets (index ETFs are the classic home). Failscatastrophically in a trend — a mean-reverter's losers are open-ended because a genuinely trending price never reverts, giving it a high win rate masking a fat left tail. It is, in a precise sense, the mirror image of trend-following, which is why the two diversify each other. edgekit's shippedSmaCross is a trend template; mean-reversion is conceptual here, built from the zscore / rsi primitives.
Scenario (the fade that works, and the one that doesn't). An index ETF closes 2.5 sigma below its 60-bar mean after a liquidity-driven flush. You buy the dislocation; over the next three bars it snaps back to the mean for a clean . This happens over and over — you win maybe seven times in ten. Then a real regime change hits: price is 2.5 sigma below the mean and keeps going— 3 sigma, 4 sigma, the mean itself sliding down after it. Your stop is far away (that is how the win rate got so high), so the one loser gives back six winners in a single trade. High hit rate, fat left tail — the mean-reverter's signature and its trap.
Statistical arbitrage & pairs#
Mechanism. Find two (or more) assets whose prices move together, trade the spreadbetween them rather than either outright: short the rich leg, long the cheap leg, collect the convergence. Because the market exposure cancels, it is close to market-neutral. Exploits: a stable statistical relationship — cointegration — between assets driven by the same underlying factor.
The construction has three standard ingredients, all of which edgekit provides as primitives:
- Hedge ratio — a rolling regression of one leg on the other gives the spread you actually trade (
ek.indicators.rolling_ols_hedge). - z-score — standardise the spread; enter when is large, exit as it returns toward zero (
ek.indicators.zscore). - Half-life — the Ornstein-Uhlenbeck half-life of the spread measures how fast it reverts; a short half-life is a live pair, an infinite one is a coincidence (
ek.indicators.half_life).
alpha, beta, spread = ek.indicators.rolling_ols_hedge(leg_y, leg_x, win=90)
z = ek.core.lag(ek.indicators.zscore(spread, 60), 1) # trade the spread's z-score
hl = ek.indicators.half_life(spread) # short half-life = a reverting pairScenario (trading the spread, not the leg).Two related equity indices normally move together; the rolling hedge says leg-Y ≈ 1.3 × leg-X, and the spread's z-score is +2.2 with a half-life of 6 days. You do not care which index goes up — you short the rich leg and long the cheap leg so the market exposure nets to roughly zero, and you collect the convergence as z decays toward 0. It works for weeks. Then a sector shock hits only one of the two names: the spread blows out to +5 sigma and never comes back — the relationship de-cointegrated. That open-ended divergence, not a normal loss, is how a pairs book takes its worst hit, and why cointegration that held in-sample must be re-proven out-of-sample before you trust it.
Signal sketch: .Fails when the relationship breaks — a structural change de-cointegrates the pair and the spread walks away instead of reverting, which is how pairs books suffer their worst losses. Cointegration that held in-sample routinely fails to replicate out-of-sample, so this family demands especially ruthless validation. Conceptual in edgekit.
Carry#
Mechanism. Get paid to hold a position: earn the roll/funding/interest differential and hope the spot price does not move against you enough to erase it. Exploits: a structural risk premium — someone pays to hedge, and the carry trader collects it. Examples are FX interest-rate differentials, futures term-structure roll, and perpetual-swap funding. Signal sketch: . Works in calm regimes, where the premium accrues steadily. Failsin the tail: carry returns look like picking up coins in front of a steamroller — long stretches of small gains punctuated by rare, violent unwinds (the “carry crash”). Conceptual; often needs an own-capital venue rather than a CFD account.
Market-making#
Mechanism. Quote a bid and an ask simultaneously and earn the spread when both fill, while managing inventory back toward flat. Exploits: the compensation liquidity providers receive for immediacy. Main risk:adverse selection — you get filled precisely when an informed trader knows something you don't — plus inventory risk when the market runs one way. This is a latency- and infrastructure-bound game measured in microseconds; it is out of scopefor edgekit's bar-based research engine, which assumes you cross the spread as a taker (that cost is charged in R).
Event-driven#
Mechanism. Trade around scheduled or discrete events — earnings, economic releases, index rebalances, expiries — where the reaction is more predictable than the direction. Exploits: structured, repeatable behaviour clustered in time. Signal sketch: . Works when the reaction pattern is stable and you can be positioned before the crowd. Failson the gap-and-slippage problem — the biggest moves happen in an instant with no fill in between, and a surprise flips the sign. Conceptual; edgekit's session and calendar tooling (ek.data.rth_mask, minute_of_day) is the scaffolding you would build the event clock on.
ML-based#
Mechanism.Instead of a hand-written rule on one feature, fit a model across many features and let it learn the mapping to a labelled outcome (e.g. “did this setup reach +1R before −1R?”). Exploits: weak, interacting patterns no single threshold captures — most usefully as a meta-label that filters a base strategy's signals rather than as a standalone predictor. Main risk: overfitting and leakage — with enough features and enough tuning, a model will fit noise perfectly and generalise to nothing. This is the highest-variance family: the ceiling is real, but so is the number of ways to fool yourself. Covered in Part V, built on edgekit.ml.
Choosing a family is choosing a regime bet#
Notice the through-line: trend-following and breakout profit from expansion and continuation; mean-reversion and pairs profit from contraction and convergence; carry profits from calm; event-driven from structure. No family wins in every regime — each is a bet that a particular market behaviour will recur. That is why serious books combine uncorrelated families (trend + reversion, directional + market-neutral) so the one that is suffering is offset by the one that is thriving — the subject of portfolio construction.

Next: Build your first strategy — take two of these templates from data load to trade statistics, end to end.
