ZigZag Based Trend Following Strategy

Author: ChaoZhang, Date: 2023-10-30 14:51:08
Tags:

img

Overview

This strategy uses the ZigZag indicator to determine trend direction and follows the trend once confirmed. It belongs to the trend following strategy.

Strategy Logic

The strategy mainly uses the ZigZag indicator to determine the price trend direction. ZigZag can filter market noise and identify major price fluctuation directions. It generates trading signals when prices reach new highs or lows.

Specifically, the strategy first calculates the ZigZag values. When prices reach a higher high, the ZigZag value becomes the high price. When prices reach a lower low, the ZigZag value becomes the low price. Thus, ZigZag can clearly reflect the main price fluctuation direction.

The strategy determines the trend direction based on ZigZag values. When ZigZag rises, it indicates an upward trend. When ZigZag falls, it indicates a downward trend. The strategy opens positions when ZigZag turns around to follow the trend direction.

In particular, the strategy goes long when ZigZag turns to a new high, and goes short when ZigZag turns to a new low. The exit condition is when ZigZag turns around again. This achieves auto trading based on ZigZag for trend identification.

Advantage Analysis

  • ZigZag can effectively filter market noise and accurately determine the major trend direction.
  • ZigZag turn timing is precise, allowing optimal entry opportunities.
  • It implements a pure trend following strategy without other complex indicators or models.
  • The logic is simple and clear, easy to understand and modify.
  • The trading frequency can be freely controlled via parameter tuning.

Risk Analysis

  • ZigZag is insensitive to medium-term trend reversals, potentially missing faster reversals.
  • Trend following strategies cannot handle losses from trend reversals.
  • It does not limit the loss size of single trades, posing large single loss risks.
  • The strategy relies solely on one indicator, risks overfitting.

Risks can be reduced by:

  • Combining other indicators to detect trend reversal risks.
  • Shortening holding period, timely stop loss.
  • Adding risk management to limit single loss size.
  • Adding machine learning models to improve robustness.

Optimization Directions

The strategy can be optimized in the following aspects:

  1. Add stop loss to control single loss risk, e.g. trailing stop or stop limit orders.

  2. Add trend reversal detection mechanisms, e.g. MACD, moving averages. Close positions when reversal is detected.

  3. Add re-entry module. Pyramid positions when trend continues.

  4. Add machine learning models like LSTM to assist trend detection.

  5. Optimize capital management based on drawdown or correlation theories.

  6. Comprehensively optimize parameters like ZigZag period by backtesting and referencing expertise.

Summary

The strategy identifies trend direction by ZigZag and trades the trend. The logic is simple and easy to implement. But risks like single indicator reliance and trend reversal exist. We can optimize via stop loss, auxiliary indicators, re-entry, machine learning models etc. to make it more robust and rational. With proper parameters and risk controls, it can effectively track medium-long term trends.


/*backtest
start: 2022-10-23 00:00:00
end: 2023-04-14 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//Noro
//2018

//@version=2
strategy(title = "Noro's ZZ Strategy v1.0", shorttitle = "ZZ str 1.0", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, pyramiding = 0)

//Settings
needlong = input(true, defval = true, title = "Long")
needshort = input(false, defval = false, title = "Short")
capital = input(100, defval = 100, minval = 1, maxval = 10000, title = "Capital, %")
tf = input('W', title='Timeframe for ZigZag')
showzz = input(false, defval = false, title = "Show ZigZag")
showbg = input(false, defval = false, title = "Show Background")
fromyear = input(1900, defval = 1900, minval = 1900, maxval = 2100, title = "From Year")
toyear = input(2100, defval = 2100, minval = 1900, maxval = 2100, title = "To Year")
frommonth = input(01, defval = 01, minval = 01, maxval = 12, title = "From Month")
tomonth = input(12, defval = 12, minval = 01, maxval = 12, title = "To Month")
fromday = input(01, defval = 01, minval = 01, maxval = 31, title = "From day")
today = input(31, defval = 31, minval = 01, maxval = 31, title = "To day")

//ZigZag
zigzag() =>
    _isUp = close >= open
    _isDown = close <= open
    _direction = _isUp[1] and _isDown ? -1 : _isDown[1] and _isUp ? 1 : nz(_direction[1])
    _zigzag = _isUp[1] and _isDown and _direction[1] != -1 ? highest(2) : _isDown[1] and _isUp and _direction[1] != 1 ? lowest(2) : na
useAltTF = true
zz = useAltTF ? (change(time(tf)) != 0 ? request.security(syminfo.tickerid, tf, zigzag()) : na) : zigzag()
zzcolor = showzz ? black : na
plot(zz, title = 'ZigZag', color = zzcolor, linewidth = 2)

//Levels
dot = zz > 0 ? zz : dot[1]
uplevel = dot > dot[1] ? dot : uplevel[1]
dnlevel = dot < dot[1] ? dot : dnlevel[1]
colorup = close[1] < uplevel[1] and uplevel == uplevel[1] ? lime : na
colordn = close[1] > dnlevel[1] and dnlevel == dnlevel[1] ? red : na
plot(uplevel, color = colorup, linewidth = 3)
plot(dnlevel, color = colordn, linewidth = 3)

//Background
size = strategy.position_size
bgcol = showbg == false ? na : size != size[1] ? blue : na
bgcolor(bgcol, transp = 50)

//Trading
lot = strategy.position_size != strategy.position_size[1] ? strategy.equity / close * capital / 100 : lot[1]

if uplevel > 0 and dnlevel > 0
    strategy.entry("Long", strategy.long, needlong == false ? 0 : lot, stop = uplevel + syminfo.mintick)
    strategy.entry("Short", strategy.short, needshort == false ? 0 : lot, stop = dnlevel - syminfo.mintick)

if time > timestamp(toyear, tomonth, today, 23, 59)
    strategy.close_all()

More