0bps

Strategy vault / Trend following

Hull Moving Average Trend Following Strategy

The Hull moving average trend following strategy utilizes the Hull moving average to determine market trend direction and generate buy and sell signals. It captures mid-to-long term trends, establishes positions…

Author
ChaoZhang
Complexity
Intermediate · 77 lines
Parameters
10
Backtest bar
1h · intraday
Tested on
BTC/USDT · futures

Overview

The Hull moving average trend following strategy utilizes the Hull moving average to determine market trend direction and generate buy and sell signals. It captures mid-to-long term trends, establishes positions early in trend starts, and closes positions before trend reversals.

Principles

The strategy uses both the Hull moving average and simple moving average to determine trend direction. When the shorter period Hull MA crosses above the longer period Hull MA, it generates a buy signal. When the shorter Hull MA crosses below the longer one, it generates a sell signal.

The simple moving average determines real-time trend direction. When the shorter EMA crosses above the longer EMA, it indicates an uptrend. When the shorter EMA crosses below the longer EMA, it indicates a downtrend. Trades are taken only when the Hull MA and EMA signals agree on the bullish or bearish bias.

In addition, the strategy utilizes K-line body channels to gauge market fluctuation and avoid trading in consolidation. Trades are considered only when prices break out of the channel range.

Advantages

  • The Hull MA is more sensitive in detecting price changes and early trend shifts.

  • Using both Hull MA and EMA eliminates false signals.

  • K-line channels avoid excessive trading in sideways markets.

  • Trend following allows sustained profit capture as the trend extends.

Risks

  • Moving averages have lags and may miss optimal trend reversal entry points.

  • Inaccurate consolidation detection may cause bad trades.

  • Low trade frequency leads to large impact from single losing trades.

  • Unable to capitalize on short-term oscillations.

Risk Management

  • Optimize MA periods for timely trend signal generation.

  • Use other indicators like RSI and BBANDS to determine consolidation.

  • Exercise aggressive capital management to limit loss percentage per trade.

  • Complement with other strategies to harness short-term profits.

Summary

The Hull moving average trend following strategy effectively tracks mid-to-long term trends through the combined use of Hull MA and EMA. It accumulates profits throughout profit trends and exits early before reversals. This is a simple and practical quant trading strategy worth recommending.

Parameters

NameDefaultWhat it controls
v_input_1_close0Candle body resistance Channel: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4
v_input_2falseBar Channel On/Off
v_input_315Support / Resistance length:
v_input_413EMA 1
v_input_521EMA 2
v_input_6falseDisplay Hull MA Set:
v_input_7_close0Hull MA's Source:: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4
v_input_816Hull MA's Base Length:
v_input_910Hull MA's Length Scalar:
v_input_10720Piriod

Source Pine Script

/*backtest
start: 2023-08-16 00:00:00
end: 2023-09-15 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=2

// strategy(title='HULLMiguel 2019/ Strategy v3', shorttitle='HULLMiguel_2019_Strategy', overlay=true, pyramiding=0, default_qty_value=1000, initial_capital=1000, currency=currency.USD)

//Candle body resistance Channel-----------------------------//
len = 34
src = input(close, title="Candle body resistance Channel")
out = sma(src, len)
last8h = highest(close, 13)
lastl8 = lowest(close, 13)
bearish = cross(close,out) == 1 and falling(close, 1)
bullish = cross(close,out) == 1 and rising(close, 1)
channel2=input(false, title="Bar Channel On/Off")
ul2=plot(channel2?last8h:last8h==nz(last8h[1])?last8h:na, color=black, linewidth=1, style=linebr, title="Candle body resistance level top", offset=0)
ll2=plot(channel2?lastl8:lastl8==nz(lastl8[1])?lastl8:na, color=blue, linewidth=1, style=linebr, title="Candle body resistance level bottom", offset=0)
//fill(ul2, ll2, color=black, transp=95, title="Candle body resistance Channel")

//-----------------Support and Resistance 
RST = input(title='Support / Resistance length:',  defval=15) 
RSTT = valuewhen(high >= highest(high, RST), high, 0)
RSTB = valuewhen(low <= lowest(low, RST), low, 0)
RT2 = plot(RSTT, color=RSTT != RSTT[1] ? na : red, linewidth=1, offset=+0)
RB2 = plot(RSTB, color=RSTB != RSTB[1] ? na : green, linewidth=1, offset=0)

//--------------------Trend colour ema------------------------------------------------// 
src0 = close, len0 = input(13, minval=1, title="EMA 1")
ema0 = ema(src0, len0)
direction = rising(ema0, 2) ? +1 : falling(ema0, 2) ? -1 : 0
plot_color = direction > 0  ? lime: direction < 0 ? red : na
plot(ema0, title="EMA", style=line, linewidth=3, color = plot_color)

//-------------------- ema 2------------------------------------------------//
src02 = close, len02 = input(21, minval=1, title="EMA 2")
ema02 = ema(src02, len02)
direction2 = rising(ema02, 2) ? +1 : falling(ema02, 2) ? -1 : 0
plot_color2 = direction2 > 0  ? green: direction2 < 0 ? red : na
plot(ema02, title="EMA Signal 2", style=line, linewidth=2, color = plot_color2)

//=============Hull MA//
show_hma = input(false, title="Display Hull MA Set:")
hma_src = input(close, title="Hull MA's Source:")
hma_base_length = input(16, minval=1, title="Hull MA's Base Length:")
hma_length_scalar = input(10, minval=0, title="Hull MA's Length Scalar:")
hullma(src, length)=>wma(2*wma(src, length/2)-wma(src, length), round(sqrt(length)))
plot(not show_hma ? na : hullma(hma_src, hma_base_length+hma_length_scalar*6), color=black, linewidth=5, title="Hull MA")
dif_close_hull= (close-hullma(hma_src, hma_base_length+hma_length_scalar*6))/close
Percent_dif = (dif_close_hull/(hullma(hma_src, hma_base_length+hma_length_scalar*6)))
//direction3 = Percent_dif>0 ? +1 : Percent_dif<0 ? -1 : 0
//plot_color3 = direction3 > 0  ? lime: direction3 < 0 ? red : na
//plot(dif_close_hull, title="dif close hull", style=line, linewidth=6, color = plot_color3)

//============ signal Generator ==================================//
Piriod=input('720')
ch1 = security(syminfo.tickerid, Piriod, open)
ch2 = security(syminfo.tickerid, Piriod, close)
plot(ch1, title="EMA Signal 2", style=line, linewidth=1, color = blue)
//longCondition = crossover(security(tickerid, Piriod, close),security(tickerid, Piriod, open))
//plot((close-ema02)/ema02+close)
longCondition = direction > 0 and direction2> 0

if (longCondition)
    strategy.entry("BUY", strategy.long)
//shortCondition = crossunder(security(tickerid, Piriod, close),security(tickerid, Piriod, open))
shortCondition = direction < 0 and direction2 < 0

if (shortCondition)
    strategy.entry("SELL", strategy.short)

///////////////////////////////////////////////////////////////////////////////////////////

Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-16. 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/Hull-Moving-Average-Trend-Following-Strategy.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