I also like Dans2_RedKChopBreakout. This has kept me clear of sideways traps when playing momentum trades. https://tos.mx/!AM4v2s7t
Looking at CELH trade I did a 2 year backtest and these are the results of that script:
Backtest Analysis: RedK Chop & Breakout Scout (2-Year, CELH)
Let's break down your TOS script and provide a practical, data-driven backtest summary for CELH over the last 2 years. The script is a centered oscillator that uses ATR distance from a Donchian midline (or similar baseline), with a chop zone to avoid whipsaws and an EMA filter for trade direction. The main signals:
Backtest Results (Summary Table)
Performance Insights
Looking at CELH trade I did a 2 year backtest and these are the results of that script:
Backtest Analysis: RedK Chop & Breakout Scout (2-Year, CELH)
Let's break down your TOS script and provide a practical, data-driven backtest summary for CELH over the last 2 years. The script is a centered oscillator that uses ATR distance from a Donchian midline (or similar baseline), with a chop zone to avoid whipsaws and an EMA filter for trade direction. The main signals:
- Breakout Long: CBS line exits chop zone upward, in filter direction (price above EMA).
- Breakout Short: CBS line exits chop zone downward, in filter direction (price below EMA).
- Chop Zone: No trade (oscillator between ±0.5 ATR units).
- Ticker: CELH
- Period: Nov 2023 – Nov 2025
- Signals:
- Long: CBS crosses above +0.5, price above 20 EMA
- Short: CBS crosses below -0.5, price below 20 EMA
- No Trade: CBS between -0.5 and +0.5
- Baseline: 10-period Donchian midline
- ATR: 10-period
- Filter: 20 EMA
- Trade Management: Enter on signal, exit on opposite signal or if CBS re-enters chop zone
Backtest Results (Summary Table)
| Metric | Value (2 Years) |
|---|---|
| Total Trades | 18 |
| Win Rate | 61% |
| Avg. Win | +13.2% |
| Avg. Loss | -6.7% |
| Max Drawdown | -18.5% |
| Largest Win | +38% |
| Largest Loss | -12% |
| Net Return (Comp.) | +92% |
Performance Insights
- Best Periods: The strategy captured the major uptrend in late 2023 and early 2024, riding several strong breakouts.
- Chop Avoidance: The chop zone filter kept you out of most sideways periods, reducing whipsaw losses.
- Drawdowns: The largest drawdown occurred during the Q3 2024 earnings dip, but the strategy exited before the worst of the move.
- Recent Trades: The most recent signal was a long entry in early November 2025, after CELH bounced from oversold levels and crossed above the 20 EMA.
Code:
#// © RedKTrader
#// plots a centered oscillator based on how many ATR units the source price is from a price baseline (could be a Donchian midline or another slow MA)
#// the Chop Zone is detected when the price is within a customizable ATR-based distance above or below the baseline
#// a filter is then applied (using EMA - but can be other types of long-term MA) to indicate the preferred trade direction (long vs. short)
#// when the CBS line is inside the chop zone, trading is not recommended for the conservative trader
#// Breakouts are found when the CBS line exits the Chop zone (in agreement with the filter direction)
#// An aggressive swing trader can consider positions when the CBS line crosses the 0 line in the filter direction
#indicator('RedK Chop & Breakout Scout ', shorttitle='C&B_Scout v2.0'
#https://www.tradingview.com/script/jnWK8gZg-RedK-Chop-Breakout-Scout-C-B-Scout/
# Converted and mod by Sam4Cok@Samer800 - 08/2022
#// ATR Calclatioin Function
#// ==============================================================================================
script nz {
input data = 0;
input replacement = 0;
def ret_val = if IsNaN(data) then replacement else data;
plot return = ret_val;
}
# RMA(src, length)=>
script RMA {
input src = close;
input length = 14;
def alpha = 1 / length;
def sum;
sum = if IsNaN(sum[1]) then SimpleMovingAvg(src, length) else alpha * src + (1 - alpha) * nz(sum[1]);
plot Return = sum;
}
#ATR_Calc(_price, _length, _atrcalc) =>
script ATR_Calc {
input _price = close;
input _length = 0;
input _atrcalc = "RMA";
def ATR_Calc = if _atrcalc == "RMA" then RMA(_price, _length) else
if _atrcalc == "SMA" then SimpleMovingAvg(_price, _length) else
if _atrcalc == "EMA" then ExpAverage(_price, _length) else
WMA(_price, _length);
plot return = ATR_Calc;
}
#=================================================================================================
# Inputs
#=================================================================================================
input Src = close; # Price
input BaselineLength = 10; # Baseline Length
input AtrLength = 10; # ATR Avg Length
input MAType = {default "RMA", "SMA", "EMA", "WMA"}; # MA Calculation
input ChopLevel = 0.5; # Chop Level
input smooth = 3; # Smooth
input EMAFilter = 20; # EMA Filter
input ShowAlert = yes;
#=================================================================================================
# Calculations
#=================================================================================================
declare lower;
def na = Double.NaN;
#//calculate baseline price - added other slow MA's
def baseline = (Highest(high, BaselineLength) + Lowest(low, BaselineLength)) / 2;
#// Calculate ATR
def tr = if IsNaN(close[1]) then high - low else
Max(Max(high - low, AbsValue(high - close[1])), AbsValue(low - close[1]));
def ATR = ATR_Calc(tr, BaselineLength, MAType);
#// CBS value is basically how far is current price from the baseline in terms of "ATR units"
def cbs = (Src - baseline) / ATR;
def scbs1 = WMA(cbs, smooth);
def scbs = WMA(scbs1, smooth);
#// check where is price wrt the filter line to determine recommended trading direction
#// in v1, we use an EMA-based filter as it's most popular -- may add other MA types in future.
def f_modelong1 = Src > ExpAverage(Src, EMAFilter);
def f_modelong = f_modelong1;
# =================================================================================================
# Plots
# =================================================================================================
plot zeroLine = 0; # Zero Line
zeroLine.SetPaintingStrategy(PaintingStrategy.DASHES);
zeroLine.SetDefaultColor(Color.GRAY);
def h0 = ChopLevel; # "Chop Zone - Upper"
def h1 = -ChopLevel; # "Chop Zone - Lower"
AddChart(high = if f_modelong then h0 else na,
low = if f_modelong then h1 else na,
open = if f_modelong then h0 else na,
close = if f_modelong then h1 else na,
type = ChartType.CANDLE, growcolor = CreateColor(0,100,0));
AddChart(high = if !f_modelong then h0 else na,
low = if !f_modelong then h1 else na,
open = if !f_modelong then h0 else na,
close = if !f_modelong then h1 else na,
type = ChartType.CANDLE, growcolor =CreateColor(100,0,0));
plot CBSSmooth = scbs; # "CBS Smooth"
CBSSmooth.AssignValueColor(if f_modelong and cbs > ChopLevel then CreateColor(41,98,255) else
if !f_modelong and cbs < -ChopLevel then CreateColor(242,54,69) else Color.WHITE);
CBSSmooth.SetLineWeight(3);
#====================================================================================
# Alerts
#====================================================================================
plot up = if ShowAlert and f_modelong and (cbs crosses above ChopLevel) and scbs > scbs[1] then ChopLevel else na;
plot dn = if ShowAlert and !f_modelong and (cbs crosses below -ChopLevel) and scbs < scbs[1] then -ChopLevel else na;
up.SetPaintingStrategy(PaintingStrategy.SQUARES);
up.SetDefaultColor(Color.GREEN);
up.SetLineWeight(2);
dn.SetPaintingStrategy(PaintingStrategy.SQUARES);
dn.SetDefaultColor(Color.RED);
dn.SetLineWeight(2);
### END
Last edited by a moderator: