QQE (Quantitative Qualitative Estimation) for ThinkorSwim

BenTen

Administrative
Staff member
Staff
VIP
QQE — or Quantitative Qualitative Estimation, is based on a rather complex calculation of the smoothed RSI indicators.

The QQE indicator consists of a smoothed Relative Strength Index (RSI) indicator and two volatility-based trailing levels (fast and slow). The Fast Trailing Level (TL) and Slow TL are constructed by calculating the ATR of the smoothed RSI over n-periods and then further smoothing the ATR using an additional n-periods Wilders smoothing function. This smoothed ATR of RSI is then multiplied by the Fast and Slow ATR Multipliers to calculate the final Fast and Slow Trailing Levels.

qLgSxk3.png

AFNqpDp.png


thinkScript Code

Code:
# QQE Indicator
# Converted by Kory Gill for BenTen at useThinkScript.com
# Original https://www.tradingview.com/script/zwbe2plA-Ghosty-s-Zero-Line-QQE/

declare lower;

input RSI_Period = 20;
input Slow_Factor = 5;
input QQE = 4.236;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;

def rsi = RSI(price = vClose, length = RSI_Period).RSI;
def rsi_ma = MovingAverage(AverageType.EXPONENTIAL, rsi, Slow_Factor);
def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
def dar = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma, Wilder_Period) * QQE;

def DeltaFastAtrRsi = dar;
def RSIndex = rsi_ma;
def newshortband =  RSIndex + DeltaFastAtrRsi;
def newlongband = RSIndex - DeltaFastAtrRsi;

def longband = if RSIndex[1] > longband[1] and RSIndex > longband[1]
               then max(longband[1],newlongband)
               else newlongband;

def shortband = if RSIndex[1] < shortband[1] and  RSIndex < shortband[1]
                then min(shortband[1], newshortband)
                else newshortband;

def trend = if Crosses(RSIndex, shortband[1])
            then 1
            else if Crosses(longband[1], RSIndex)
            then -1
            else if !IsNAN(trend[1])
            then trend[1]
            else 1;

def FastAtrRsiTL = if trend == 1
                   then longband
                   else shortband;

plot pFastAtrRsiTL = FastAtrRsiTL;
plot pRsiMa = rsi_ma;
plot line50 = 50;

pFastAtrRsiTL.SetDefaultColor(CreateColor(225,109,47));
pRsiMa.SetDefaultColor(CreateColor(113,225,180));

Learn more about the QQE indicator and how to trade it:
 

diazlaz

Well-known member
2019 Donor
VIP
per the information, in summary:

if the indicator band is much higher than the level of 50, there is uptrend;
if significantly below the level of 50, there is downward;
if the band fluctuates near level 50 (a little above or below the level), there is flat in the market.
 

Barmarrs

New member
Does anyone know if it'd be possible to turn this indicator into a strategy? My knowledge with ThinkScript and writing code is pretty much non-existent, but if someone has any tips/hints or can share a starting place, I can toy around with it.
Buying condition would be where the RSI plot crosses the Fast ATR; selling would be the Fast ATR crossing the RSI plot.

Not sure if it's possible with the issue I've noticed with the scanner, but I wanted to check. Thanks for the reply and again for putting this forum together! I can't speak for everyone, but the indicators, resources, and collaboration from others I've seen have really helped me develop new skills and fine tune others - it's really appreciated!

Sorry for the unending questions on this one, but is there a way to add up/down arrows on the candles themselves when the the RSI crosses the ATR line? Specifically an up arrow where the RSI crosses above the ATR, and a down arrow when the ATR crosses the RSI? I'm striking out on all fronts in trying to get a working scanner/strategy for this one, but I'm loving the signals I've seen on AMM 2.0 combined with this indicator. I've never used ToS support, and I'm not sure what their limitations are, but would they go through the code to assist with questions like this?

If it can't be done, I understand - I just wanted to make sure. It should go without saying, but thanks again for putting the time and effort in to this forum!
 
Last edited by a moderator:

BenTen

Administrative
Staff member
Staff
VIP
@Barmarrs Add this to the bottom of the script:

Code:
input over_sold = 20;
input over_bought = 80;

plot OverSold = over_Sold;
plot OverBought = over_Bought;
plot UpSignal = if pRSIMA crosses above pFastAtrRsiTL then OverSold else Double.NaN;
plot DownSignal = if pRSIMA crosses below pFastAtrRsiTL then OverBought else Double.NaN;

UpSignal.SetDefaultColor(Color.UPTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.DOWNTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
 

kelvin

Member
VIP
I saw this indicator somewhere else, it looks great with K bars and Histogram could show you very clear entry and exit points.
J1103SF.png

Code:
{ Quantitative Qualitative Estimation Indicator Revised}

inputs:
    double RSIPrice(                        Close )[DisplayName = "RSIPrice", ToolTip =
     "Price to be used in the calculation of the RSI."],
    int RSILength(                        14 )[DisplayName = "RSILength", ToolTip =
     "The number of bars to be used in the calculation of the RSI."],
    int RSISmoothLength(                        5 )[DisplayName = "RSISmoothLength", ToolTip =
     "The length of the exponential moving average of the RSI.  This value determines the smoothing factor used in the exponential moving average calculation."],
    int ATRLength(                        27 )[DisplayName = "ATRLength", ToolTip =
     "The length of the exponential moving average of the true range of the smoothed RSI."],
    int ATRSmoothLength(                        27 )[DisplayName = "ATRSmoothLength", ToolTip =
     "The length of the exponential moving average of the moving average of the true range of the smoothed RSI."],
    double FastATRMult(                        2.618 )[DisplayName = "FastATRMult", ToolTip =
     "Fast trendline scaling factor that is multiplied by the moving average of the moving average of the true range of the smooth RSI."],
    double SlowATRMult(                        4.236 )[DisplayName = "SlowATRMult", ToolTip =
     "Slow trendline scaling factor that is multiplied by the moving average of the moving average of the true range of the smooth RSI."],
    double SmoothRSIAlertLevel(                        50 )[DisplayName = "SmoothRSIAlertLevel", ToolTip =
     "If alerts are enabled for the indicator, an alert will be triggered if the smoothed RSI crosses the level specified by this input"],

    LRSLength(3),
    Multiple(2.38),

    OverBought1(60),
    OverBought2(70),
    OverSold1(40),
    OverSold2(30),

    HUpColor(green),
    HDwnColor(magenta),
    LUpColor(Cyan),
    LDwnColor(Red),
    MUpColor(Green),
    MDwnColor(Red),
    BarUpColor(green),
    BarDwColor(red),
    SpreadUpColor(green),
    SpreadDnColor(red);

variables:
    double RetVal( 0 ),
    double oSmoothRSI( 0 ),
    double oFastTL( 50 ),
    double oSlowTL( 50 ),
    intrabarpersist bool OkToPlot( false ),
    LRS(0);

RetVal = QQE( RSIPrice, RSILength, RSISmoothLength, ATRLength, ATRSmoothLength,
FastATRMult, SlowATRMult, oSmoothRSI, oFastTL, oSlowTL );


Value1 = Highest(oSmoothRSI, 2);

Value2 = Lowest(oSmoothRSI, 2);

if oSmoothRSI > oSmoothRSI[1] then

Value3 = Value1 - Value2 ;

if oSmoothRSI < oSmoothRSI[1] Then

Value3 = Value2 - Value1 ;

LRS = LinearRegSlope(oSmoothRSI, LRSLength);


{ do not plot until all exponential moving averages have stabilized }
once ( CurrentBar > 4 * MaxList( RSILength, RSISmoothLength, ATRLength,
ATRSmoothLength ) )
begin
    OkToPlot = true;
end;

if OkToPlot then
begin
    Plot1( oSmoothRSI, !( "SmoothRSI" ) );
    Plot2( oFastTL, !( "FastTL" ) );
    Plot3( oSlowTL, !( "SlowTL" ) );
    Plot4( SmoothRSIAlertLevel, !( "SmRSIAlrtLev" ) );
    Plot5(OverBought1, "OverBought1");
    Plot6(OverSold1, "OverSold1");
    Plot7(Value1, "BH");
    Plot8(Value2, "BL");
    Plot9(OverBought2, "OverBought2");
    Plot10(OverSold2, "OverSold2");
    Plot11(Value3 * Multiple , "Spread");
    Plot12(LRS * Multiple, "LRS-SRSI");



var: var1(yellow), var4(yellow), var7(yellow), var8(yellow), var11(yellow);

If currentbar >= 0 then begin

If oSmoothRSI >= SmoothRSIAlertLevel then begin
if oSmoothRSI > oFastTL then var1 = HUpColor;
if oSmoothRSI < oFastTL then var1 = HDwnColor;
end;

If oSmoothRSI < SmoothRSIAlertLevel then begin
if oSmoothRSI > oFastTL then var1 = LUpColor;
if oSmoothRSI < oFastTL then var1 = LDwnColor;
end;

SetPlotColor(1,var1);

If oSmoothRSI >= SmoothRSIAlertLevel then var4 = MUpColor;

If oSmoothRSI < SmoothRSIAlertLevel then var4 = MDwnColor;

SetPlotColor(4,var4);




if oSmoothRSI > oSmoothRSI[1] then var7 = BarUpColor;

if oSmoothRSI > oSmoothRSI[1] then var8 = BarUpColor;

if oSmoothRSI < oSmoothRSI[1] then var7 = BarDwColor;

if oSmoothRSI < oSmoothRSI[1] then var8 = BarDwColor;

SetPlotColor(7,var7);

SetPlotColor(8,var8);

If Value3 >= 0  Then var11 = SpreadUpColor;

If Value3 < 0 Then var11 = SpreadDnColor;

SetPlotColor(11,var11);


End;







{ alerts }
if AlertEnabled then
begin
    if oSmoothRSI crosses over SmoothRSIAlertLevel then
    begin
        Alert( !( "SmoothRSI crossed over" ) + " " +
         NumToStr( SmoothRSIAlertLevel, 5 ) );
    end
    else if oSmoothRSI crosses under SmoothRSIAlertLevel then
    begin
        Alert( !( "SmoothRSI crossed under" ) + " " +
         NumToStr( SmoothRSIAlertLevel, 5 ) );
    end;
end;
end;

it comes with over bought and over sold level.

This revised version comes with 3 lines cross over, over bought/over sold levels, K bars in the main signal line can change colors when trends reversed, also attached a histogram, very fancy, should be best and popular indicator in TradeStation
 
Last edited by a moderator:

BenTen

Administrative
Staff member
Staff
VIP
@kelvin Add this snippet at the bottom of the QQE indicator I posted in the Warehouse forum and you will get the same overbought and oversold levels.

Code:
plot ob1 = 70;
plot ob2 = 60;
plot os1 = 40;
plot os2 = 30;
 

Art

Member
@BenTen I'm using the TradinView's QQE indicator, and I'd love to have it on Thinkorswim.
Is your 50 line can be compared to TV's 0 or 10 lines?

TV QQE indicator gives you a buy signal only when the lines are crossing 10 not zero.

Sh2Pocy.png


Please could you explain?
 

BenTen

Administrative
Staff member
Staff
VIP
@Art There are different versions of QQE on TradingView, some are modified to produce slightly different signals using different inputs.
 

Gildes

New member
When there’s a cross over from the RSI and ATR
Add this Line at the end of the script

AssignPriceColor(if pRsiMa crosses above pFastAtrRsiTL then color.cyan else if pRsiMa crosses below pFastAtrRsiTL then color.orange else if pRsiMa > pFastAtrRsiTL then color.Green else if pRsiMa < pFastAtrRsiTL then color.Red else color.Gray);

AddCloud(pRsiMa, pFastAtrRsiTL , color.Green, color.RED);
 
Last edited:

kcking

New member
I'd like to convert the qqe indicator into a strategy to backtest...can someone help?

Long - entry when pRsiMa crosses above pFastAtrRsiTL, exit when price crosses upper band of Keltner channel
Short -entry when pRsiMa crosses below pFastAtrRsiTL, exit when price crosses lower band of Keltner channel
 
Last edited by a moderator:

tradebyday

Active member
@kcking here is something to start
Code:
# QQE Indicator
# Converted by Kory Gill for BenTen at useThinkScript.com
# Original https://www.tradingview.com/script/zwbe2plA-Ghosty-s-Zero-Line-QQE/


input RSI_Period = 20;
input Slow_Factor = 5;
input QQE = 4.236;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;

def rsi = RSI(price = vClose, length = RSI_Period).RSI;
def rsi_ma = MovingAverage(AverageType.EXPONENTIAL, rsi, Slow_Factor);
def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
def dar = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma, Wilder_Period) * QQE;

def DeltaFastAtrRsi = dar;
def RSIndex = rsi_ma;
def newshortband =  RSIndex + DeltaFastAtrRsi;
def newlongband = RSIndex - DeltaFastAtrRsi;

def longband = if RSIndex[1] > longband[1] and RSIndex > longband[1]
               then max(longband[1],newlongband)
               else newlongband;

def shortband = if RSIndex[1] < shortband[1] and  RSIndex < shortband[1]
                then min(shortband[1], newshortband)
                else newshortband;

def trend = if Crosses(RSIndex, shortband[1])
            then 1
            else if Crosses(longband[1], RSIndex)
            then -1
            else if !IsNAN(trend[1])
            then trend[1]
            else 1;

def FastAtrRsiTL = if trend == 1
                   then longband
                   else shortband;

plot pFastAtrRsiTL = FastAtrRsiTL;
plot pRsiMa = rsi_ma;
plot line50 = 50;

pFastAtrRsiTL.SetDefaultColor(CreateColor(225,109,47));
pRsiMa.SetDefaultColor(CreateColor(113,225,180));

#
# TD Ameritrade IP Company, Inc. (c) 2007-2020
#

input displace = 0;
input factor = 1.5;
input length = 20;
input price = close;
input averageType = AverageType.SIMPLE;
input trueRangeAverageType = AverageType.SIMPLE;

def shift = factor * MovingAverage(trueRangeAverageType, TrueRange(high, close, low), length);

def average = MovingAverage(averageType, price, length);

plot Avg = average[-displace];
Avg.SetDefaultColor(GetColor(1));

plot Upper_Band = average[-displace] + shift[-displace];
Upper_Band.SetDefaultColor(GetColor(8));

plot Lower_Band = average[-displace] - shift[-displace];
Lower_Band.SetDefaultColor(GetColor(5));
# END

addOrder(OrderType.BUY_AUTO, pRsiMa crosses above pFastAtrRsiTL);
addOrder(OrderType.SELL_TO_CLOSE, price > Upper_Band);
addOrder(OrderType.SELL_AUTO, pRsiMa crosses below pFastAtrRsiTL);
addOrder(OrderType.BUY_TO_CLOSE, price < Lower_Band);
 

FOTM_8888

Active member
great job benten, this indicator look pretty good, ben can you add a buy and sell arrow to this indicator please on the candles. thank you very much.
 

BenTen

Administrative
Staff member
Staff
VIP
@FOTM_8888 Here you go:

Code:
# QQE Indicator
# Converted by Kory Gill for BenTen at useThinkScript.com
# Original https://www.tradingview.com/script/zwbe2plA-Ghosty-s-Zero-Line-QQE/

input RSI_Period = 20;
input Slow_Factor = 5;
input QQE = 4.236;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;

def rsi = RSI(price = vClose, length = RSI_Period).RSI;
def rsi_ma = MovingAverage(AverageType.EXPONENTIAL, rsi, Slow_Factor);
def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
def dar = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma, Wilder_Period) * QQE;

def DeltaFastAtrRsi = dar;
def RSIndex = rsi_ma;
def newshortband =  RSIndex + DeltaFastAtrRsi;
def newlongband = RSIndex - DeltaFastAtrRsi;

def longband = if RSIndex[1] > longband[1] and RSIndex > longband[1]
               then max(longband[1],newlongband)
               else newlongband;

def shortband = if RSIndex[1] < shortband[1] and  RSIndex < shortband[1]
                then min(shortband[1], newshortband)
                else newshortband;

def trend = if Crosses(RSIndex, shortband[1])
            then 1
            else if Crosses(longband[1], RSIndex)
            then -1
            else if !IsNAN(trend[1])
            then trend[1]
            else 1;

def FastAtrRsiTL = if trend == 1
                   then longband
                   else shortband;

def pFastAtrRsiTL = FastAtrRsiTL;
def pRsiMa = rsi_ma;
def line50 = 50;

plot UpSignal = if pRSIMA crosses above pFastAtrRsiTL then low else Double.NaN;
plot DownSignal = if pRSIMA crosses below pFastAtrRsiTL then high else Double.NaN;

UpSignal.SetDefaultColor(Color.MAGENTA);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.CYAN);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
 

Pensar

Well-known member
VIP
Lifetime
QQE Indicator Scan

Code:
# QQE Indicator Scan
# Converted by Kory Gill for BenTen at useThinkScript.com
# Original https://www.tradingview.com/script/zwbe2plA-Ghosty-s-Zero-Line-QQE/
# Pensar - modified into scan with 4 different choices -

input RSI_Period = 20;
input Slow_Factor = 5;
input QQE = 4.236;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;

def rsi = RSI(price = vClose, length = RSI_Period).RSI;
def rsi_ma = MovingAverage(AverageType.EXPONENTIAL, rsi, Slow_Factor);
def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
def dar = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma, Wilder_Period) * QQE;

def DeltaFastAtrRsi = dar;
def RSIndex = rsi_ma;
def newshortband =  RSIndex + DeltaFastAtrRsi;
def newlongband = RSIndex - DeltaFastAtrRsi;

def longband = if RSIndex[1] > longband[1] and RSIndex > longband[1]
               then max(longband[1],newlongband)
               else newlongband;

def shortband = if RSIndex[1] < shortband[1] and  RSIndex < shortband[1]
                then min(shortband[1], newshortband)
                else newshortband;

def trend = if Crosses(RSIndex, shortband[1])
            then 1
            else if Crosses(longband[1], RSIndex)
            then -1
            else if !IsNAN(trend[1])
            then trend[1]
            else 1;

def FastAtrRsiTL = if trend == 1 then longband else shortband;

plot CrossAbove = if rsi_ma crosses above FastAtrRsiTL then 1 else 0;
#plot CrossBelow = if rsi_ma crosses below FastAtrRsiTL then 1 else 0;
#plot Above = if rsi_ma > FastAtrRsiTL then 1 else 0;
#plot Below = if rsi_ma < FastAtrRsiTL then 1 else 0;

# end scan

Here's a picture of what the scan is doing - it visually shows each choice that you can scan for.

 
Last edited by a moderator:

tem2005

Active member
VIP
@FOTM_8888 Here you go:

Code:
# QQE Indicator
# Converted by Kory Gill for BenTen at useThinkScript.com
# Original https://www.tradingview.com/script/zwbe2plA-Ghosty-s-Zero-Line-QQE/

input RSI_Period = 20;
input Slow_Factor = 5;
input QQE = 4.236;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;

def rsi = RSI(price = vClose, length = RSI_Period).RSI;
def rsi_ma = MovingAverage(AverageType.EXPONENTIAL, rsi, Slow_Factor);
def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
def dar = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma, Wilder_Period) * QQE;

def DeltaFastAtrRsi = dar;
def RSIndex = rsi_ma;
def newshortband =  RSIndex + DeltaFastAtrRsi;
def newlongband = RSIndex - DeltaFastAtrRsi;

def longband = if RSIndex[1] > longband[1] and RSIndex > longband[1]
               then max(longband[1],newlongband)
               else newlongband;

def shortband = if RSIndex[1] < shortband[1] and  RSIndex < shortband[1]
                then min(shortband[1], newshortband)
                else newshortband;

def trend = if Crosses(RSIndex, shortband[1])
            then 1
            else if Crosses(longband[1], RSIndex)
            then -1
            else if !IsNAN(trend[1])
            then trend[1]
            else 1;

def FastAtrRsiTL = if trend == 1
                   then longband
                   else shortband;

def pFastAtrRsiTL = FastAtrRsiTL;
def pRsiMa = rsi_ma;
def line50 = 50;

plot UpSignal = if pRSIMA crosses above pFastAtrRsiTL then low else Double.NaN;
plot DownSignal = if pRSIMA crosses below pFastAtrRsiTL then high else Double.NaN;

UpSignal.SetDefaultColor(Color.MAGENTA);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.CYAN);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
@BenTen would this code work real time with no delay or repaint for daily chart for swing?
 

Similar threads

Top