The Ehlers Stochastic Cyber Cycle Strategy is a quantitative trading strategy that generates trading signals using Ehlers’ stochastic cycle indicator. This strategy combines the advantages of stochastic indicators and cycle indicators, aiming to capture cyclical opportunities in the market.
This strategy first constructs a smoothed cycle indicator, then builds a stochastic indicator value based on that indicator. The generation of trading signals is determined by the crossover of the moving average line of this stochastic indicator value.
Specifically, the smoothed cycle indicator is calculated as:
smooth = (src + 2 * src[1] + 2 * src[2] + src[3]) / 6
Where src is the input price data, such as closing price. This indicator combines the current price and the prices of the previous 3 time periods to construct a smoothed cycle signal.
Based on this smoothed indicator, the stochastic cycle cycle can then be calculated:
cycle := (1 - .5 * alpha) * (1 - .5 * alpha) *
(smooth - 2 * smooth[1] + smooth[2]) +
2 * (1 - alpha) * cycle[1] -
(1 - alpha) * (1 - alpha) * cycle[2]
This calculation formula contains the second order difference of the smoothed periodic signal, and the values of the previous two cycles. α is a smoothing factor that adjusts the weight of new and old cycle values.
Finally, a 0-100 random value value1 is calculated based on this cycle indicator. And the signal value signal is constructed based on the 10-day moving average of value1. Trading signals are issued when the moving average line of signal crosses up or down.
This strategy combines stochastic indicators and cycle indicators to integrate the advantages of both. Compared to simple trend strategies such as moving averages, this strategy can better capture cyclical opportunities and thus achieve better results.
The main advantages are:
The main risks of this strategy are:
Risks can be controlled by optimizing parameter settings, setting stop loss points, combining other filtering indicators, etc.
This strategy can also be optimized in the following aspects:
The Ehlers Stochastic Cyber Cycle Strategy integrates the advantages of stochastic and cycle indicators through dual signal design to effectively control risks, and can achieve good returns in markets with strong cyclicality. With further optimization, this strategy can become a worthwhile quantitative trading strategy to recommend.
/*backtest start: 2024-01-09 00:00:00 end: 2024-01-16 00:00:00 period: 3m basePeriod: 1m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=3 strategy("Ehlers Stochastic Cyber Cycle Strategy",overlay=false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100.0, pyramiding = 1, commission_type = strategy.commission.percent, commission_value = 0.1) src = input(hl2, title = "Source") alpha = input(.07, title = "Alpha") lag = input(9, title = "Lag") smooth = (src + 2 * src[1] + 2 * src[2] + src[3]) / 6 len = input(8, title = "Stochastic len") cycle = na if na(cycle[7]) cycle := (src - 2 * src[1] + src[2]) / 4 else cycle := (1 - .5 * alpha) * (1 - .5 * alpha) * (smooth - 2 * smooth[1] + smooth[2]) + 2 * (1 - alpha) * cycle[1] - (1 - alpha) * (1 - alpha) * cycle[2] value1 = stoch(cycle, cycle, cycle, len) / 100 value2 = 2 * ((4 * value1 + 3 * value1[1] + 2 * value1[2] + value1[3]) / 10 - 0.5) signal = value2 oppositeTrade = input(true) barsSinceEntry = 0 barsSinceEntry := nz(barsSinceEntry[1]) + 1 if strategy.position_size == 0 barsSinceEntry := 0 if (crossover(signal, signal[1]) and not oppositeTrade) or (oppositeTrade and crossunder(signal, signal[1])) strategy.entry("Long", strategy.long) barsSinceEntry := 0 if (crossunder(signal, signal[1]) and not oppositeTrade) or (oppositeTrade and crossover(signal, signal[1])) strategy.entry("Short", strategy.short) barsSinceEntry := 0 if strategy.openprofit < 0 and barsSinceEntry > 8 strategy.close_all() barsSinceEntry := 0 plot(0, title="ZeroLine", color=gray) plotSrc = signal cyclePlot = plot(plotSrc, title = "CyberCycle", color = blue) triggerPlot = plot(plotSrc[1], title = "Trigger", color = green) fill(cyclePlot, triggerPlot, color = plotSrc < plotSrc[1] ? red : lime, transp = 50)