MAE, MFE & Stop Optimization
8 min read
Use Maximum Adverse Excursion and Maximum Favorable Excursion data for data-driven risk control and stop optimization.
8 min read
Use Maximum Adverse Excursion and Maximum Favorable Excursion data for data-driven risk control and stop optimization.
You don't need to guess how tight your stop should be. Your trades are already telling you.
TL;DR: MAE (Maximum Adverse Excursion) is the worst paper loss a trade reached before close; MFE (Maximum Favorable Excursion) is the best unrealized gain. By computing the MAE distribution across your winning trades and reading the 85th–90th percentile, you find the smallest stop that keeps your edge intact — provided you validate it on out-of-sample data before risking live capital.
Prerequisites: Stop Placement & Risk Anchoring and ATR-Based vs Structural Stops. Next: Smart Stops operationalizes the dynamic stop logic this lesson describes statistically.
You've placed your stop. You've executed your trade. The post-mortem question is unavoidable:
"Was my stop too tight, too loose, or just right?"
Two execution metrics answer that question with measurement instead of feel:
The metric was named and popularized by John Sweeney in Maximum Adverse Excursion: Analyzing Price Fluctuations for Trading Management (Wiley, 1997). Every Tradervue, Edgewonk, or custom-Python journal you'll touch traces back to that book.
These two numbers turn closed trades into stop and target diagnostics — they tell you how much heat your edge actually takes before it pays out, and how much profit you systematically leave behind.
| Metric | Formal definition (long) | Operational use |
|---|---|---|
| MAE | Lowest price between entry and exit, expressed in R or % of risk | Stop sizing efficiency |
| MFE | Highest price between entry and exit, expressed in R or % of risk | Exit timing optimization |
For a short, flip "lowest" and "highest." Both metrics ignore the direction of the trade outcome — a winner can have a large MAE, and a loser can have a large MFE before reversing into the stop.
Most traders anchor stops on round numbers, widen them after a recent stopout (recency bias), and exit on the first 1R because variance feels like proof. MAE and MFE replace those reflexes with measured distributions of how price actually behaved across your closed trades — not how it felt.
That gives you tractable answers to three concrete questions:
Compared to alternatives covered in ATR-Based vs Structural Stops, MAE/MFE are empirical — they describe what your strategy already did, not what a generic volatility model assumes will happen.
Why winners only? Losers' MAE is censored by your current stop — every loser, by definition, has MAE equal to your stop distance. Including losers in the MAE calculation tells you about your stop, not about your edge. Winners' MAE tells you the heat a real edge takes before paying out.
If the median MAE of your winners is 0.6R (and the 90th percentile is 0.9R), but your stop sits at 1.5R…
Half of winners never went past 0.6R against you before paying out.
Even the worst-heat winners stayed inside roughly 1R of adverse excursion.
0.6R of dead capital that damages your R:R without protecting any real edge.
You're paying for a 1.5R risk envelope and only using ~0.9R of it on the trades that actually work. The rest is dead capital that hurts your R:R ratio without protecting anything.
MAE_R = (entry - lowest_price) / risk_per_R for longs.Tighter stops with the same stop-out rate = higher R:R = more compounding capacity over a 100-trade sample.
If the median MFE of your winners is +2.7R, but you usually exit at 1.0–1.5R…
You are leaving money on the table — consistently — and the journal will prove it across hundreds of trades.
Practically:
MFE distributions also depend on session — a London-session MFE distribution looks different from an Asian-session one, which is why session selection (Killzones) and MFE analysis are paired disciplines.
| Method | Data required | Adapts to regime? | Overfitting risk | Best for |
|---|---|---|---|---|
| MAE percentile (winners) | ≥30 closed trades per setup | Only if recomputed per regime | High — direct in-sample fit | Mature setups with stable trade logs |
| ATR multiple | Recent ATR(14) | Yes — ATR moves with vol | Low — generic volatility model | New setups, regime transitions |
| Structural (swing) | Recent swing highs/lows | Implicit (structure shifts) | Low–medium | Discretionary trend trades |
A practical workflow uses ATR or structural stops in the first 30–50 trades of a new setup, then transitions to MAE-derived stops once a real distribution exists.
You need per trade: entry price, exit price, max-against price (the MAE bar), max-favorable price (the MFE bar), and risk-per-R. If your broker doesn't expose intra-trade extremes, reconstruct them from 1m bars between fills.
| Trade # | MAE | MFE | Exit | Stop Hit? | Notes |
|---|---|---|---|---|---|
| #183 | 0.4R | 3.1R | +1.0R | No | Cut early, feared reversal |
| #184 | 0.7R | 1.8R | +1.7R | No | Full hold, high precision |
| #185 | 1.3R | 0.4R | -1.0R | Yes | MAE exceeded avg, poor entry |
From this snippet (illustrative — three trades is not a sample, it's an anecdote):
For the journaling infrastructure that produces these columns automatically, see Trader Journaling OS.
df.groupby('trade_id').apply(lambda t: (t.entry - t.low).max() / risk_per_R) on tick or 1m bars gives per-trade MAE in R units.Plot MAE and MFE on a scatterplot in R units:
This produces a trade footprint — a visual map of where your edge actually lives. Trades hugging the y-axis (low MAE, high MFE) are your cleanest expressions of edge; trades pressed against a vertical line (large MAE, small MFE) are the ones whose entries need work.
Visualize the relationship between worst drawdown (MAE) and peak profit (MFE) for a synthetic set of trades. Slide stop efficiency from 0.5× to 2.0× of MAE: notice how win-rate plateaus past ~1.2× — that plateau is where you have stopped buying protection and started buying air. Stops larger than the 90th-percentile MAE of winners almost never save trades; they just inflate the loss when the rare invalidation comes.
MAE (Maximum Adverse Excursion) is the worst unrealized drawdown a trade reached between entry and exit. For a long, it is the lowest price during the holding period; for a short, the highest. It is typically expressed in R units or percent of risk.
MFE (Maximum Favorable Excursion) is the best unrealized gain a trade reached between entry and exit — the highest price during the holding period for a long, the lowest for a short. It tells you how much profit was theoretically available before you closed the trade.
John Sweeney introduced and popularized MAE in his 1997 book Maximum Adverse Excursion: Analyzing Price Fluctuations for Trading Management (Wiley). The concept predates the book in informal use, but Sweeney's framework is the canonical reference.
Neither. MAE distributions are right-skewed, so the mean understates worst-case heat. Use the 85th–90th percentile of MAE among winning trades — that captures the typical heat real edges absorb without being dominated by a single outlier.
At least 30 closed trades per setup to get a usable percentile estimate, and 100 or more before adjusting stops on live capital. Below those thresholds, the tail of the distribution is unreliable.
Only after out-of-sample validation. Fitting a stop to the same trades that produced the MAE distribution is in-sample optimization and can curve-fit. Reserve a holdout window or run walk-forward validation before deploying any MAE-derived stop in live capital.
Use the MAE measured up to the first partial exit, not over the full holding period. After the first scale-out the trade's risk profile changes, so post-management MAE mixes pre- and post-management regimes.
You can't improve what you don't measure. MAE and MFE are your execution diagnostics.
Don't set your stop based on fear, and don't tighten it based on a 12-trade backtest either. Compute the MAE distribution of your winners, validate it on data you haven't seen, and let the percentiles tell you the smallest envelope your edge needs. The data already knows what your stop should be — your job is to read it without flinching and without overfitting.