Archived: QQE (Quantitative Qualitative Estimation) for ThinkorSwim

Status
Not open for further replies.

BenTen

Administrative
Staff member
Staff
VIP
Lifetime

These are the archived posts for the QQE. The current thread can be found:

https://usethinkscript.com/threads/qqe-quantitative-qualitative-estimation-for-thinkorswim.938/



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:
 
Last edited by a moderator:
sorry but I'm new to reading tos code, i have a question for these two lines
i assume the first line is storing one absolute value in the variable atr_rsi correct?
but if so then how are you finding the EMA with that one value in the second line?
is atr_rsi an array?
thanks!


def atr_rsi = AbsValue(rsi_ma[1] - rsi_ma);
def atr_rsi_ma = MovingAverage(AverageType.EXPONENTIAL, atr_rsi, Wilder_Period);
 
@bandzbond Remember, each of those lines gets executed with every trade so the second line paints the ema of the result stored in atr_rsi... This is a common concept that you will find in many indicators, especially lower indicators... Many study indicators plot both the original value as well as an overlaid moving average based on the original values...

As for the question about arrays, no, TOS does not support arrays... What may appear to be an array is simply a series of basic calculations done one after the other as trade data comes in, not an aggregate grouping of values as a whole... I hope that makes sense...
 
ah that's interesting, to confirm my understand, I want to use an example, so lets say we had RSIs of these values: 40 50 60 70 80
basically the second line will be doing the EMA of these following absolute values (40-50),(50-60),(60-70), (70-80) right?
 
ah that's interesting, to confirm my understand, I want to use an example, so lets say we had RSIs of these values: 40 50 60 70 80
basically the second line will be doing the EMA of these following absolute values (40-50),(50-60),(60-70), (70-80) right?
What the numbers are is irrelevant... Just remember the concept that every time the price changes, so does the moving average... The current price paints and so does the current average, on a price change by price change basis... And there is no array of data... When a chart starts painting, regardless of how far back it goes, TOS parses the servers database for each candle/bar - without building a data array...

For this very reason you should keep the length of your charts only as long as immediately needed... If you only need a few days of visual lookback then go with 3 or 5 days... For example, if you have a study that paints a 50 day moving average on a 3D 3M chart the study will only parse the database for the price values it needs, not the entire candle/bar worth of data... This reduces bandwidth overhead and reduces latency... It's all about making the platform efficient so that your charts stay as real-time as possible... After all, in reality, real-time data actually isn't real-time - it's the closest to real-time as the internet will allow at a given point in time...

All that being said, TOS most likely uses a streaming buffer of some sort but not what programmers would consider and array...
 
Hello all. I like this QQE indicator thus far. Have anyone able to write a scanner thinkscript to scan when the 2 lines crossed (daily timeframe)?
You can't scan for that sadly, because of how the Short/Long band are coded. You can however search for when the Prsima crosses anything (Besides the other line) . So a 50 cross, oversold cross, overbought, etc etc

You can also do Watchlist Custom Columns and use them in your scan results if you want.
 
I'm not certain why there seems to be problems scanning, this worked fine

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.

QQE.png
Could you do it again and show the results from the scan ? There are no issues in showing the results on the actual chart itself of a crossover, it's the actual SCAN that there are issues with.

I tripled checked my own scan and then took the exact code you posted and attempted a scan. Zero results.

Been trying on/off for the past few months to get a scan working, so if you actually have a working one, I'd be excited asf ,lol.
 
@Xiuying I absolutely have no idea why it generates results for me yet doesn't work for you. Given that I'm scanning in the "All Listed Stocks" category, it takes about 30-45 seconds to load results - it would be faster if the scan is run against far fewer stocks. Maybe reset the scan page to default and then try it? I'm out of ideas.
Been trying on/off for the past few months to get a scan working, so if you actually have a working one, I'd be excited asf ,lol.
The good news is you can be excited . . . I do have a working scan! 😁
 
@Xiuying I absolutely have no idea why it generates results for me yet doesn't work for you. Given that I'm scanning in the "All Listed Stocks" category, it takes about 30-45 seconds to load results - it would be faster if the scan is run against far fewer stocks. Maybe reset the scan page to default and then try it? I'm out of ideas.

The good news is you can be excited . . . I do have a working scan! 😁
I've tried doing it exactly as I see you have and have also tried setting it up for scanning less and even just my watchlist which I know has had crosses.

Could you by chance share the scan via the top right button ? If for some reason the actual scan link ends up giving me zero results as well, then I'm going to start wondering if it's a software or account issue on my end.

I am excited but also angry and confused, all at the same time, lol.
 
I tried looking over some other MTF indicators to get an idea of how to add a MTF function. I added these but it didn't really work out:
Code:
input agg = AggregationPeriod.fifteen_min;
plot c = close(period = agg);

Can someone help me out?
 
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:
what is the reason qqe is 4.236
 
I tried looking over some other MTF indicators to get an idea of how to add a MTF function. I added these but it didn't really work out:
Code:
input agg = AggregationPeriod.fifteen_min;
plot c = close(period = agg);

Can someone help me out?
It's working, When you use an aggregation period that is lower than the one you're currently using, it wont work properly. So 15m will work on anything below that, but wont work on anything above that.

what is the reason qqe is 4.236
Fibs, You'll notice using Fib Retracement you'll get the usual 161.8, 261.8 , 423.6 levels after the 100%. The QQE coincides with those fib extension levels.(Correct me if I'm wrong though, since I'm going off my own experience with it)
 
I saw this indicator somewhere else, it looks great with K bars and Histogram could show you very clear entry and exit points.

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
im assuming this script isnt for TOS?? Does anyone know where to find the QQE histogram version. ive searched the forums up and down and only found one person with it but no code or links when asked...just given the two line version.
 
Status
Not open for further replies.

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Thread starter Similar threads Forum Replies Date
M QQE Threshold Questions 2
G Follow up with Original Code - QQE painting strat Help Questions 4

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
307 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top