TRIX Backtest on BTC/USDT: Triple-Smoothing Momentum and the 25bp Cliff
The TRIX oscillator on real hourly BTC/USDT 2023: +111.94% naive, +64.74% with fees/funding, -39.65% at 25bp across 201 trades. A momentum line smooth enough to catch trends and active enough to pay for it.
TRIX Backtest on BTC/USDT (2023, hourly, real fees)
TRIX takes the triple-EMA idea from the TEMA post and applies it to momentum: triple-smooth the price, then take the percentage change of the smoothed line, then run a signal EMA over that. The result is a clean oscillator with almost none of the wiggle of a raw price-rate. Long when TRIX sits above its signal line β that was my rule, with the standard 15/9 periods. It posted the second-best naive momentum return of the lab (+111.94%), a solid +64.74% after fees and funding, and then a textbook 25bp cliff to -39.65%. The momentum family keeps telling the same story: smooth enough to be right, active enough to be expensive. Strategy Lab #32.
Results
| Strategy | Category | Total return | CAGR | MaxDD | Sharpe | Trades |
|---|---|---|---|---|---|---|
| trix | momentum | +64.74% | +64.97% | -18.44% | 1.75 | 201 |

The zero-cost run, +111.94% with a Sharpe of 2.56, is the momentum family's best β closer to buy & hold's +154.94% than anything in that family, with a tighter drawdown (-14.32%). TRIX's triple smoothing removes so much noise that its crosses genuinely mark the big swings of 2023. The problem is that it also marks them repeatedly: 201 trades.
The fee bill
| Scenario | Cost/leg | Total return | MaxDD | Sharpe | Trades | |---|---:|---:|---:|---:|---:|---:| | naive (zero cost) | 0.00% | +111.94% | -14.32% | 2.56 | 201 | | taker fee 0.05%/leg | 0.05% | +73.43% | -17.25% | 1.92 | 201 | | + funding 0.01%/8h | 0.05% | +64.74% | -18.44% | 1.75 | 201 | | + slippage 10bp/leg | 0.15% | +10.27% | -29.49% | 0.47 | 201 | | + slippage 25bp/leg | 0.30% | -39.65% | -50.47% | -1.43 | 201 |

+111.94% β -39.65%. The descent is gentle until the last column, then sudden: 401 legs at 25bp is ~25% of principal a year. Win rate 44.8% (90/201) β the same low-hit/high-payoff shape as every trend-family strategy. The honest reading of this table: TRIX is the best gross momentum strategy in the lab, and it still needs slippage under ~15bp to be worth running. That's not a criticism of TRIX; it's the fee reality every high-frequency idea meets.
The momentum family scoreboard (all hourly BTC, 2023)
| Strategy | Trades | Naive | Fees+funding | 25bp |
|---|---|---|---|---|
| MACD (post 15) | 333 | +79.08% | +22.21% | -76.89% |
| OBV (post 16) | 734 | +63.78% | -24.95% | -98.10% |
| ROC (post 31) | 700 | +97.20% | -6.61% | -97.19% |
| TRIX (this) | 201 | +111.94% | +64.74% | -39.65% |
| Awesome (post 34) | 216 | +84.99% | +41.14% | -52.04% |
| Momentum (post 35) | 785 | +74.31% | -24.00% | -98.51% |
The ranking at every column follows trade count almost perfectly. TRIX trades the least and survives the best; Momentum and ROC trade constantly and collapse. Within one family, the strategy's frequency is a better predictor of survival than its indicator logic.
What this does NOT prove
- 15/9 is the classic TRIX pair; the signal-period and the source (using log changes is common) are real knobs.
- One strong-trend year is TRIX's ideal habitat β its triple smoothing is a trend tool wearing an oscillator costume.
- The 201-trade churn suggests a filter (e.g., only long when ADX > 20, post 06) is the natural upgrade. That's the combination post 41 of this series explores.
Code
from backtest_base import fetch, backtest_signal, metrics
df = fetch("BTCUSDT", "binance", "2023-01-01", "2023-12-31", "1h")
c = df["close"]
e1 = c.ewm(span=15, adjust=False).mean()
e2 = e1.ewm(span=15, adjust=False).mean()
e3 = e2.ewm(span=15, adjust=False).mean()
trix = e3.pct_change().fillna(0.0)
sig = trix.ewm(span=9, adjust=False).mean()
signal = (trix > sig).fillna(False)
res = backtest_signal(df, signal, cost_per_leg=0.0005,
funding_per_bar=0.0001 / 8.0)
print(metrics(res, 8760))Reproduce it
cd blog-drafts/scripts
python backtest_base.py --strategy trix --symbol BTCUSDT --interval 1h \
--start 2023-01-01 --end 2023-12-31 --fee 0.0005 --funding 0.0000125Data: Binance public API, hourly OHLCV, 8,735 bars. The tables above reproduce exactly from this command.
This is a backtest on historical data, not investment advice. Past performance does not predict future results.