Strategy vault / Trend following
Triple Moving Average Trend Following Strategy
This strategy combines the concept of turtle trading with Niko Bakkers' phase analysis, using three moving averages of different cycles to determine the trend direction for trend following. It goes long when the fast…

Overview
This strategy combines the concept of turtle trading with Niko Bakkers' phase analysis, using three moving averages of different cycles to determine the trend direction for trend following. It goes long when the fast moving average crosses over the medium moving average and all three moving averages are in the same upward or downward trend; It goes short when the fast moving average crosses below the medium moving average and all three moving averages are in the same upward or downward trend.
Strategy Logic
Calculate three moving averages of different cycles: the fast moving average period is 8 days, the medium moving average period is 21 days, and the slow moving average period is 55 days.
Determine entry conditions: when the fast moving average crosses above the medium moving average, and all three moving averages are in an upward trend, go long; when the fast moving average crosses below the medium moving average, and all three moving averages are in a downward trend, go short.
Determine exit conditions: close positions when the fast moving average crosses the medium moving average in the opposite direction.
Position sizing: use fixed position sizing, open 1 contract each time. ATR can also be used to dynamically adjust position sizing.
Advantage Analysis
Using three moving averages helps determine the trend direction and avoid false breakouts.
Trend following for profit potential.
Using moving averages results in stable profits and relatively small drawdowns.
Controllable stop loss strategy reduces probability of huge losses.
Risk Analysis
Prone to multiple small losses, lowering profit efficiency.
Moving averages lag and may miss trend reversal points.
Fixed position sizing cannot effectively control risks, may cause margin call during significant market fluctuation.
Improper parameter optimization leads to over-trading, increasing trading costs and slippage.
Optimization
Optimize moving average periods to suit the characteristics of the trading instrument.
Use ATR to dynamically adjust position sizing.
Add stop loss strategy.
Incorporate trading volume indicators to determine reliability of trends.
Summary
This strategy integrates traditional technical indicators and the philosophy of turtle trading, using three moving averages to track trends. With proper parameter optimization, it can achieve good profitability. But it also has some risks. Stop loss, position sizing and other measures need to be utilized to control risks and obtain long-term steady profits from this quantitative trading strategy.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_1 | 8 | Fast MA Length |
| v_input_2 | 21 | Medium MA Length |
| v_input_3 | 55 | Slow MA Length |
| v_input_4 | 12 | From Month |
| v_input_5 | true | From Day |
| v_input_6 | 2016 | From Year |
| v_input_7 | true | To Month |
| v_input_8 | true | To Day |
| v_input_9 | 9999 | To Year |
| v_input_10 | true | Use Position Sizing? |
| v_input_11 | 0.5 | Risk % |
Source Pine Script
/*backtest
start: 2024-01-01 00:00:00
end: 2024-01-31 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// LOVE JOY PEACE PATIENCE KINDNESS GOODNESS FAITHFULNESS GENTLENESS SELF-CONTROL
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © JoshuaMcGowan
//@version=4
// 1. Define strategy settings
strategy(title="Triple Moving Average", overlay=true,
pyramiding=0, initial_capital=1000,
commission_type=strategy.commission.cash_per_order,
commission_value=4, slippage=2)
fastMALen = input(title="Fast MA Length", type=input.integer, defval=8)
medMALen = input(title="Medium MA Length", type=input.integer, defval=21)
slowMALen = input(title="Slow MA Length", type=input.integer, defval=55)
//endMonth = input(title="End Month Backtest", type=input.integer, defval=11)
//endYear = input(title="End Year Backtest", type=input.integer, defval=2019)
// === INPUT BACKTEST RANGE ===
FromMonth = input(defval = 12, title = "From Month", minval = 1, maxval = 12)
FromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear = input(defval = 2016, title = "From Year", minval = 2017)
ToMonth = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
ToDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear = input(defval = 9999, title = "To Year", minval = 2017)
// === FUNCTION EXAMPLE ===
start = timestamp(FromYear, FromMonth, FromDay, 00, 00) // backtest start window
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59) // backtest finish window
window() => true
usePosSize = input(title="Use Position Sizing?", type=input.bool, defval=true)
riskPerc = input(title="Risk %", type=input.float, defval=0.5, step=0.25)
// 2. Calculate strategy values
fastMA = sma(close, fastMALen)
medMA = sma(close, medMALen)
slowMA = sma(close, slowMALen)
//Position Sizing
riskEquity = (riskPerc / 100) * strategy.equity
atrCurrency = (atr(20) * syminfo.pointvalue)
posSize = usePosSize ? floor(riskEquity / atrCurrency) : 1
//Backtest Window
//tradeWindow = (time <= timestamp(endYear, endMonth, 1, 0, 0))
// 3. Determine long trading conditions
enterLong = crossover(fastMA, medMA) and
(fastMA > slowMA) and (medMA > slowMA) and
window()
exitLong = crossunder(fastMA, medMA)
// 4. Code short trading conditions
enterShort = crossunder(fastMA, medMA) and
(fastMA < slowMA) and (medMA < slowMA) and
window()
exitShort = crossover(fastMA, medMA)
// 5. Output strategy data
plot(series=fastMA, color=color.green, title="Fast MA")
plot(series=medMA, color=color.purple, title="Medium MA")
plot(series=slowMA, color=color.red, title="Slow MA",
linewidth=2)
bgColour =
enterLong and (strategy.position_size < 1) ? color.green :
enterShort and (strategy.position_size > -1) ? color.red :
exitLong and (strategy.position_size > 0) ? color.lime :
exitShort and (strategy.position_size < 0) ? color.orange :
na
bgcolor(color=bgColour, transp=85)
// 6. Submit entry orders
if (enterLong)
strategy.entry(id="EL", long=true, qty=1)
if (enterShort)
strategy.entry(id="ES", long=false, qty=1)
// 7. Submit exit orders
strategy.close_all(when=exitLong and
(strategy.position_size > 0))
strategy.close_all(when=exitShort and
(strategy.position_size < 0))
strategy.close_all(when=not window())
//ENDPublished by ChaoZhang on the FMZ strategy square · last modified 2024-02-01. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Triple-Moving-Average-Trend-Following-Strategy.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- ATR and Moving Average Crossover Hybrid StrategyPine Script · Trend following · 1h
- Adaptive Risk Management Strategy Based on Dynamic ATR and Moving Average CrossoverPine Script · Trend following · 2h
- Adaptive Volatility Based Trend Following Short Strategy with Time Delay and Stop Loss ProtectionPine Script · Trend following · 2m
- BB Percentage Index Trend Fading StrategyPine Script · Trend following · 1h
- Bollinger Bands and RSI Trend Following StrategyPine Script · Trend following · 1h
- Dual ATR Channel Trend Following StrategyPine Script · Trend following · 15m