0bps

Strategy vault / Trend following

Trend Following Strategy Based on Multi Timeframe TEMA Crossover

This strategy identifies market trend direction based on the crossover of TEMA indicator across multiple timeframes, and uses TEMA crossover in lower timeframe to find specific entry and exit points. The strategy can…

Author
ChaoZhang
Complexity
Intermediate · 95 lines
Parameters
12
Backtest bar
1d · swing
Tested on
BTC/USDT · futures

IMG

Overview

This strategy identifies market trend direction based on the crossover of TEMA indicator across multiple timeframes, and uses TEMA crossover in lower timeframe to find specific entry and exit points. The strategy can be configured for long only, short only or both directions.

Strategy Logic

The strategy employs two TEMA indicators, one with fast and slow line based on 5 and 15 periods, the other based on user-defined higher timeframe such as daily or weekly. The crossover of higher timeframe TEMA determines overall trend bias, with fast line crossing above slow line indicating bullish view, and below indicating bearish view. The lower timeframe TEMA crossover is used to find concrete entry and exit timing.

When higher timeframe TEMA fast line crosses above slow line, a long entry can be triggered when lower timeframe TEMA fast line crosses above slow line; An exit signal is given when fast line crosses below slow line. Similarly, when higher timeframe fast line drops below slow line, a short entry is triggered on lower timeframe TEMA bearish crossover and exit when a bullish crossover happens.

Advantages

  1. Based on TEMA crossover, avoids noise interference
  2. Multi timeframe design combines high and lower cycles, improving accuracy
  3. Flexible configuration for long only, short only or both directions
  4. Simple rules, easy to understand and implement

Risk Analysis

  1. TEMA has lagging effect, may miss initial price change
  2. Short term corrections on higher TF may cause unnecessary reverse trades
  3. Improper higher TF setting fails to reflect real trend
  4. Improper lower TF setting increases stop loss risk

Risk Solutions:

  1. Fine tune TEMA parameters for balance
  2. Relax stop loss margin moderately
  3. Optimize high low cycle settings
  4. Test parameter robustness across products

Enhancement Opportunities

  1. Dynamically adjust TEMA parameters for sensitivity optimization
  2. Add momentum filter to avoid missing trends
  3. Add volatility index for dynamic stop loss sizing
  4. Machine learning for parameter optimization

Summary

The strategy overall is simple and clear in logic, identifying trend bias via TEMA crossover on multiple timeframes, and relying on additional crossover on lower TF to time entries. It has certain merits while also has some space for improvements. On the whole, it provides valuable reference for quant trading practices.

Parameters

NameDefaultWhat it controls
v_input_10What type of Orders: Longs+Shorts | LongsOnly | ShortsOnly
v_input_2trueFrom Month
v_input_3trueFrom Day
v_input_42020From Year
v_input_5trueTo Month
v_input_6trueTo Day
v_input_79999To Year
v_input_820Fast Length
v_input_960Slow Length
v_input_10DHTF Resolution
v_input_115HTF Fast Length
v_input_1215HTF Slow Length

Source Pine Script

/*backtest
start: 2023-01-01 00:00:00
end: 2023-12-24 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Seltzer_

//@version=4
strategy(title="TEMA Cross +HTF Backtest", shorttitle="TEMA_X_+HTF_BT", overlay=true)

orderType = input("Longs+Shorts",title="What type of Orders", options=["Longs+Shorts","LongsOnly","ShortsOnly"])
isLong   = (orderType != "ShortsOnly")
isShort  = (orderType != "LongsOnly")

// Backtest Section {

// Backtest inputs
FromMonth = input(defval=1, title="From Month", minval=1, maxval=12)
FromDay = input(defval=1, title="From Day", minval=1, maxval=31)
FromYear = input(defval=2020, title="From Year", minval=2010)
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)

// Define backtest timewindow
start = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)  // backtest finish window
window() => true

// }

//TEMA Section {

//LTF Section
xLength = input(20, minval=1, title="Fast Length")
xPrice = close
xEMA1 = ema(xPrice, xLength)
xEMA2 = ema(xEMA1, xLength)
xEMA3 = ema(xEMA2, xLength)
xnRes = (3 * xEMA1) - (3 * xEMA2) + xEMA3
xnResP = plot(xnRes, color=color.green, linewidth=2, title="TEMA1")

yLength = input(60, minval=1, title="Slow Length")
yPrice = close
yEMA1 = ema(yPrice, yLength)
yEMA2 = ema(yEMA1, yLength)
yEMA3 = ema(yEMA2, yLength)
ynRes = (3 * yEMA1) - (3 * yEMA2) + yEMA3
ynResP = plot(ynRes, color=color.red, linewidth=2, title="TEMA2")

fill(xnResP, ynResP, color=xnRes > ynRes ? color.green : color.red, transp=65, editable=true)

//HTF Section
HTFres = input(defval="D", type=input.resolution, title="HTF Resolution")

HTFxLength = input(5, minval=1, title="HTF Fast Length")
HTFxPrice = close
HTFxEMA1 = security(syminfo.tickerid, HTFres, ema(HTFxPrice, HTFxLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFxEMA2 = security(syminfo.tickerid, HTFres, ema(HTFxEMA1, HTFxLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFxEMA3 = security(syminfo.tickerid, HTFres, ema(HTFxEMA2, HTFxLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFxnRes = (3 * HTFxEMA1) - (3 * HTFxEMA2) + HTFxEMA3
HTFxnResP = plot(HTFxnRes, color=color.yellow, linewidth=1,transp=30, title="TEMA1")

HTFyLength = input(15, minval=1, title="HTF Slow Length")
HTFyPrice = close
HTFyEMA1 = security(syminfo.tickerid, HTFres, ema(HTFyPrice, HTFyLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFyEMA2 = security(syminfo.tickerid, HTFres, ema(HTFyEMA1, HTFyLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFyEMA3 = security(syminfo.tickerid, HTFres, ema(HTFyEMA2, HTFyLength), barmerge.gaps_off, barmerge.lookahead_on)
HTFynRes = (3 * HTFyEMA1) - (3 * HTFyEMA2) + HTFyEMA3
HTFynResP = plot(HTFynRes, color=color.purple, linewidth=1, transp=30, title="TEMA2")

fill(HTFxnResP, HTFynResP, color=HTFxnRes > HTFynRes ? color.yellow : color.purple, transp=90, editable=true)
bgcolor(HTFxnRes > HTFynRes ? color.yellow : na, transp=90, editable=true)
bgcolor(HTFxnRes < HTFynRes ? color.purple : na, transp=90, editable=true)

// }

// Buy and Sell Triggers
LongEntryAlert = xnRes > ynRes and HTFxnRes > HTFynRes and window()
LongCloseAlert = xnRes < ynRes and window()
ShortEntryAlert = xnRes < ynRes and HTFxnRes < HTFynRes and window()
ShortCloseAlert = xnRes > ynRes

// Entry & Exit signals
if isLong
    strategy.entry("Long", strategy.long, when = LongEntryAlert)
    strategy.close("Long", when = LongCloseAlert)

if isShort
    strategy.entry("Short", strategy.short, when = ShortEntryAlert)
    strategy.close("Short", when = ShortCloseAlert)

Published by ChaoZhang on the FMZ strategy square · last modified 2023-12-25. 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.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Trend-Following-Strategy-Based-on-Multi-Timeframe-TEMA-Crossover.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. 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

esc

Try , , or .

↑↓ move↵ open