Trend Following Strategy Based on Nadaraya-Watson Regression and ATR Channel

Author: ChaoZhang, Date: 2024-02-22 15:15:03



This strategy is a trend following strategy that combines Nadaraya-Watson regression and ATR channel to identify trend direction and entry points. It goes long when price breaks through the lower rail and closes position when price breaks through the upper rail. A stop loss mechanism is also set.

Strategy Logic

Firstly, this strategy uses Nadaraya-Watson kernel regression to calculate two regression curves with different lags, and compares the crossover of the two curves to determine the trend direction. Specifically, it calculates the regression curves of h-period and h-lag-period respectively. When the h-lag-period curve crosses over the h-period curve, it indicates a long signal. When the h-lag-period curve crosses below the h-period curve, it indicates a short signal.

Secondly, this strategy uses ATR channel to determine entry points. The upper rail is the regression curve plus n-period ATR multiplier and the lower rail is the regression curve minus the n-period ATR multiplier. It goes long when price breaks through the lower rail and goes short when price breaks through the upper rail.

Finally, a stop loss mechanism is set. If the price stays below the entry price for stopLossBars consecutive bars, the position will be closed by stop loss.

Advantage Analysis

This strategy combines regression analysis and channel breakthrough, which can capture the trend direction and momentum relatively accurately. Compared with using single indicators like moving average to identify trends, this method reduces false signals and thus improves the stability of the strategy.

In addition, the ATR channel sets reasonable entry points, avoiding wrong entries around trend reversal points. The stop loss mechanism also effectively controls the single loss.

Therefore, this strategy has advantages like strong ability to identify trends, relatively accurate entries and exits, controllable single stop loss risk, etc.

Risk Analysis

The biggest risk of this strategy is that when price breaks through the ATR channel, it may just be making a reversal or consolidation, which leads to improper entry or quick stop loss after entry.

In addition, both the regression curves and ATR channels need some parameter optimization. Improper parameter settings may lead to poor regression analysis results or over-wide or over-narrow ATR ranges, which will affect the performance of the strategy.

Optimization Directions

We can consider combining other indicators to judge trend and reversal signals, such as VOLUME, MACD etc. to improve the stability and accuracy of the strategy.

The kernel function in the regression analysis can also be adjusted, such as trying Epanechnikov kernel, to see if better fitting effects can be obtained.

The ATR period and multiplier of the ATR channel also need repeated testing and optimization to find the best parameter combination.


This strategy combines the use of regression analysis and channel breakthrough to identify trend direction and strength, enters at reasonable points, and sets stop loss, thus realizing a stable trend following strategy. There is still a large room for further testing and improvement of this strategy.

start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]

strategy("Custom Strategy with Stop Loss and EMA", overlay=true)

src = input(close, title='Source')
h = input(10, title='Lookback Window', tooltip='The number of bars used for the estimation.')
r = input(10, title='Relative Weighting', tooltip='Relative weighting of time frames.')
x_0 = input(50, title='Start Regression at Bar',  tooltip='Bar index on which to start regression.')
lag = input(2, title='Lag', tooltip='Lag for crossover detection.')
stopLossBars = input(3, title='Stop Loss Bars', tooltip='Number of bars to check for stop loss condition.')
emaPeriod = input(46, title='EMA Period',  tooltip='Period for Exponential Moving Averages.')

lenjeje = input(32, title='ATR Period', tooltip='Period to calculate upper and lower band')
coef = input(2.7, title='Multiplier', tooltip='Multiplier to calculate upper and lower band')

// Function for Nadaraya-Watson Kernel Regression
kernel_regression1(_src, _size, _h) =>
    _currentWeight = 0.0
    _cumulativeWeight = 0.0
    for i = 0 to _size + x_0
        y = _src[i] 
        w = math.pow(1 + (math.pow(i, 2) / ((math.pow(_h, 2) * 2 * r))), -r)
        _currentWeight += y * w
        _cumulativeWeight += w
    [_currentWeight, _cumulativeWeight]

// Calculate Nadaraya-Watson Regression
[currentWeight1, cumulativeWeight1] = kernel_regression1(src, h, h)
yhat1 = currentWeight1 / cumulativeWeight1
[currentWeight2, cumulativeWeight2] = kernel_regression1(src, h-lag, h-lag)
yhat2 = currentWeight2 / cumulativeWeight2

// Calculate Upper and Lower Bands
upperjeje = yhat1 + coef * ta.atr(lenjeje)
lowerjeje = yhat1 - coef * ta.atr(lenjeje)

// Plot Upper and Lower Bands
plot(upperjeje, color=color.rgb(0, 247, 8), title="Upper Band", linewidth=2)
plot(lowerjeje, color=color.rgb(255, 0, 0), title="Lower Band", linewidth=2)

// Calculate EMAs
emaLow = ta.ema(low, emaPeriod)
emaHigh = ta.ema(high, emaPeriod)

// Plot EMAs
plot(emaLow, color=color.rgb(33, 149, 243, 47), title="EMA (Low)", linewidth=2)
plot(emaHigh, color=color.rgb(255, 153, 0, 45), title="EMA (High)", linewidth=2)

// Long Entry Condition
longCondition = low < lowerjeje
strategy.entry("Long", strategy.long, when=longCondition)

// Stop Loss Condition
stopLossCondition = close[1] < strategy.position_avg_price and close[2] < strategy.position_avg_price and close[3] < strategy.position_avg_price
strategy.close("Long", when=stopLossCondition)

// Close and Reverse (Short) Condition
shortCondition = high > upperjeje
strategy.close("Long", when=shortCondition)
strategy.entry("Short", strategy.short, when=shortCondition)