
This isn’t your average multi-indicator strategy. The WaveTrend + Connors RSI + Linear Regression Deviation combo hinges on window synchronization: all buy signals must appear within a 2-bar range, isolated signals get ignored. This design directly filters out 90% of false signals.
Traditional strategies either let indicators work independently (creating noise) or require simultaneous triggers (missing opportunities). This strategy finds the sweet spot: a 2-bar tolerance window ensures signal correlation while avoiding overly strict synchronization requirements.
WT length set to 10 periods, oversold at -48, overbought at 48. This parameter combo is more aggressive than traditional RSI’s 30⁄70, catching price reversal signals earlier. WT’s advantage lies in combining price position with volatility, making it more reliable than pure RSI in choppy markets.
The key is WT’s calculation: (Typical Price - EMA) / (0.015 * Deviation EMA). This formula naturally incorporates volatility adjustment. When market volatility spikes, the denominator increases, keeping WT values relatively stable and avoiding the distortion common RSI suffers during high-volatility periods.
CRSI isn’t ordinary RSI - it fuses price RSI, streak RSI, and price change percentile ranking. The 20 oversold threshold is more aggressive than traditional 30, but CRSI’s triple verification mechanism reduces false signal probability.
The 6-period RSI length is deliberately short to enhance signal sensitivity. On 15-minute timeframes, 6 periods equals 1.5 hours of price memory - enough to catch short-term oversold conditions without excessive lag. This parameter works particularly well for 24⁄7 traded assets like BTC.
LSDD = Current Price - Linear Regression Value. When LSDD crosses above 0, it signals price starting to deviate from the downtrend line. The 20-period setting covers 5 hours on 15-minute charts, effectively identifying medium-term trend changes.
This indicator’s brilliance lies in measuring trend deviation rather than simple trend following. When price consistently falls then starts deviating upward from the regression line, it often signals rebound initiation. Combined with WT and CRSI oversold signals, it creates “oversold + trend reversal” dual confirmation.
Strategy designed as pure long-only, 30% capital per entry, allowing 1 additional position. This setup suits cryptocurrency’s long-term uptrend while managing risk through position control. 30% single position size provides adequate returns while avoiding excessive single-trade risk.
Exit conditions are equally strict: WT overbought (>48) AND CRSI overbought (>80) AND LSDD negative - all three must align. This design ensures trend trading completeness, preventing premature exits.
Strategy performs well in BTC 15-minute backtests, but this doesn’t guarantee effectiveness across all market environments. In sideways choppy markets, even triple confirmation may generate false signals. Strategy works best in markets with clear trending characteristics.
Risk Warning: Historical backtests don’t guarantee future returns. Cryptocurrency markets are extremely volatile with potential for capital loss. Recommend thorough paper trading validation before live implementation and strict overall position control.
/*backtest
start: 2024-10-09 00:00:00
end: 2025-10-07 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT","balance":500000}]
*/
//@version=5
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © alescha13
// WT + CRSI + Linear Regression Long-only Strategy
// Description:
// This long-only trading strategy combines WaveTrend (WT),
// Connors RSI (CRSI), and a Linear Regression Slope (LSDD) trend filter.
// Signals are generated only when all three indicators align within a defined window.
// Exits occur when all indicators turn bearish.
// Backtested on BTC with 15-minute timeframe.
strategy("WT + CRSI + Linear Regression Long-only © alescha13",
overlay=true,
initial_capital=10000,
default_qty_type=strategy.percent_of_equity,
default_qty_value=30,
pyramiding=1,
calc_on_every_tick=false,
process_orders_on_close=true)
// =====================
// Inputs
// =====================
wtLength = input.int(10, "WT Length")
wtOversold = input.int(-48, "WT Oversold Level")
wtOverbought = input.int(48, "WT Overbought Level")
crsiRSILength = input.int(6, "CRSI RSI Length")
crsiOversold = input.int(20, "CRSI Oversold Level")
crsiOverbought = input.int(80, "CRSI Overbought Level")
lsddLen = input.int(20, "Linear Regression Length")
windowSize = input.int(2, "Window size (bars) for all signals", minval=1)
// =====================
// Helper: CRSI Function
// =====================
updown(s) =>
isEqual = s == s[1]
isGrowing = s > s[1]
ud = 0.0
ud := isEqual ? 0 : isGrowing ? (nz(ud[1]) <= 0 ? 1 : nz(ud[1]) + 1) : (nz(ud[1]) >= 0 ? -1 : nz(ud[1]) - 1)
ud
crsiFunc(src, lenrsi) =>
lenupdown = 2
lenroc = 100
rsi = ta.rsi(src, lenrsi)
updownrsi = ta.rsi(updown(src), lenupdown)
percentrank = ta.percentrank(ta.roc(src, 1), lenroc)
math.avg(rsi, updownrsi, percentrank)
// =====================
// WaveTrend (WT) Calculation
// =====================
ap = (high + low + close) / 3.0
esa = ta.ema(ap, wtLength)
d = ta.ema(math.abs(ap - esa), wtLength)
ci = (ap - esa) / (0.015 * d)
wt = ta.ema(ci, 3)
wtBull = ta.crossover(wt, wtOversold)
wtBear = wt > wtOverbought
// =====================
// CRSI Calculation
// =====================
crsiValue = crsiFunc(close, crsiRSILength)
crsiBull = crsiValue < crsiOversold
crsiBear = crsiValue > crsiOverbought
// =====================
// Linear Regression LSDD Calculation
// =====================
slope = ta.linreg(close, lsddLen, 0)
lsdd = close - slope
lsddBull = ta.crossover(lsdd, 0)
lsddBear = lsdd < 0
// =====================
// Window Logic (Synchronize Signals)
// =====================
var int wtBarIndex = na
var int crsiBarIndex = na
var int lsddBarIndex = na
if wtBull
wtBarIndex := bar_index
if crsiBull
crsiBarIndex := bar_index
if lsddBull
lsddBarIndex := bar_index
buySignal = false
if not na(wtBarIndex) and not na(crsiBarIndex) and not na(lsddBarIndex)
maxBar = math.max(wtBarIndex, crsiBarIndex, lsddBarIndex)
minBar = math.min(wtBarIndex, crsiBarIndex, lsddBarIndex)
if (maxBar - minBar) <= windowSize
buySignal := true
wtBarIndex := na
crsiBarIndex := na
lsddBarIndex := na
finalLong = buySignal
// =====================
// Exit Logic
// =====================
sellSignal = wtBear and crsiBear and lsddBear
// =====================
// Entries / Exits
// =====================
if finalLong
strategy.entry("Long", strategy.long, comment="Long Entry")
if sellSignal
strategy.close("Long", comment="Long Exit")
// =====================
// Background Color for Signals
// =====================
bgcolor(finalLong ? color.new(color.green, 85) : na)
bgcolor(sellSignal ? color.new(color.red, 85) : na)
// =====================
// Plots
// =====================
plot(wt, color=color.new(color.blue, 0), title="WT")
plot(crsiValue, color=color.new(color.purple, 0), title="CRSI")
plot(lsdd, color=color.new(color.orange, 0), title="LSDD")
plotshape(finalLong, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(sellSignal, title="Sell Signal", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
// =====================
// Alerts
// =====================
alertcondition(finalLong, title="Long Alert", message="WT + CRSI + LSDD Long Signal")
alertcondition(sellSignal, title="Exit Alert", message="WT + CRSI + LSDD Exit Signal")