QQE MTF (Multi Timeframe) for ThinkorSwim

Xiuying

Member
Had this on the backburner for quite awhile and finally got off my lazy *** to clean it up a bit.(Searched and didn't see anyone post one yet, so hopefully I didn't miss it)

QQE indicator with a MTF spin on it. It has two variations with "1" being the faster one(6/3 2.621 settings) and "2" being the slower one(20/5/ 4.236 settings).

Time frames go in order of Bottom to top with bottom being the current timeframe you're on and working it's way upward. Default secondary timeframes are 15m and 30m.

Colors:
Green = Fast > Slower
Red = Fast < Slower
White = Fast < Slower and in Oversold Territory(Below 30)
Blue = Fast > Slower and in Overbought Territory(Above 70)

The last two colors only apply to the bottom row(current time frame) considering that I mainly use this for day trading on the 5m and those OS & OB areas help me a lot. I am currently back testing to see how often the same areas will work on higher time frames. Currently 15m is the top contender for being great for the colors, so I'll be more than likely adding in code to detect that aggregation period to allow it on the 15m.

I would also like to thank @BenTen for posting the QQE thread months ago which got me to start using QQE in the first place and testing to see what could be done with it in general to improve it.

Code:
#QQEV2 7/18/2020
#MTF QQE based off of the first version I made, Ended up sticking with only MTF and getting rid of the extra "Fib variations" for this version.
#Timeframes will go from Bottom to Top with the bottom being the current time frame
#Green = Fast > Slow and Blue indicates that Fast > Slow AND it's in overbought territory while white will indicate fast < slow and in oversold Territory.
#This feature will only appear for the current time ONLY, as I mainly use it to daytrade on the 5m where it helps me avoid sudden drops
#Author - Xiuying

#Update 10/05/2020 - Replaced the inputs to change the Slow/Fast/QQE with a simple Variation input. Input "1" shall be the usual fast 6/3 and anything not "1" will be the generic 20/5
#Update 11/07/2020 - Ended up changing the original lines that I had and switched to something simple like the MMARB that I imported, however the lines would be too "Trippy" so changed to singular bubbles

#Future - I plan on adding anothing feature based off of the trend that is usually associated with QQE, Going to do some more backtesting before I do so.

# The Original Base that this all started from was the one that Kory Gill converted for Benten at useThinkScript.com



declare lower;

input Variation =  1;
Input Agg2 = {"1 min", "3 min", "5 min", "10 min", default  "15 min", "30 min", "60 min", "120 min", "Daily", "Weekly", "Monthly"};
Input Agg3 = { "3 min", "5 min", "10 min", "15 min", default  "30 min", "60 min", "120 min", "Daily","Weekly", "Monthly"};


###Agg Code
def middleAggregation;

switch (Agg2) {
case "1 min":
    middleAggregation = AggregationPeriod.MIN;
case "3 min":
    middleAggregation = AggregationPeriod.THREE_MIN;
case "5 min":
    middleAggregation = AggregationPeriod.FIVE_MIN;
case "10 min":
    middleAggregation = AggregationPeriod.TEN_MIN;
case "15 min":
    middleAggregation = AggregationPeriod.FIFTEEN_MIN;
case "30 min":
    middleAggregation = AggregationPeriod.THIRTY_MIN;
case "60 min":
    middleAggregation = AggregationPeriod.HOUR;
case "120 min":
    middleAggregation = AggregationPeriod.TWO_HOURS;
case "Daily":
    middleAggregation = AggregationPeriod.DAY;
case "Weekly":
    middleAggregation = AggregationPeriod.WEEK;
case "Monthly":
    middleAggregation = AggregationPeriod.MONTH;
}

def highestAggregation;
switch (Agg3) {
case "3 min":
    highestAggregation = AggregationPeriod.THREE_MIN;
case "5 min":
    highestAggregation = AggregationPeriod.FIVE_MIN;
case "10 min":
    highestAggregation = AggregationPeriod.TEN_MIN;
case "15 min":
    highestAggregation = AggregationPeriod.FIFTEEN_MIN;
case "30 min":
    highestAggregation = AggregationPeriod.THIRTY_MIN;
case "60 min":
    highestAggregation = AggregationPeriod.HOUR;
case "120 min":
    highestAggregation = AggregationPeriod.TWO_HOURS;
case "Daily":
    highestAggregation = AggregationPeriod.DAY;
case "Weekly":
    highestAggregation = AggregationPeriod.WEEK;
case "Monthly":
    highestAggregation = AggregationPeriod.MONTH;
}

####

def RSI_Period = if Variation != 1 then 20 else 6;
def Slow_Factor = if Variation != 1 then 5 else 3;
def QQE = if Variation != 1 then 4.236 else 2.621;

def Wilder_Period = RSI_Period * 2 - 1;
def vClose = close;
def vClose15 = close(period = middleAggregation);
def vClose30 = close(period = highestAggregation);

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;

##################
def rsi15 = RSI(price = vClose15, length = RSI_Period).RSI;
def rsi_ma15 = MovingAverage(AverageType.EXPONENTIAL, rsi15, Slow_Factor);
def atr_rsi15 = AbsValue(rsi_ma15[1] - rsi_ma15);
def atr_rsi_ma15 = MovingAverage(AverageType.EXPONENTIAL, atr_rsi15, Wilder_Period);
def dar15 = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma15, Wilder_Period) * QQE;

def DeltaFastAtrRsi15 = dar15;
def RSIndex15 = rsi_ma15;
def newshortband15 =  RSIndex15 + DeltaFastAtrRsi15;
def newlongband15 = RSIndex15 - DeltaFastAtrRsi15;

def longband15 = if RSIndex15[1] > longband15[1] and RSIndex15 > longband15[1]
               then Max(longband15[1], newlongband15)
               else newlongband15;

def shortband15 = if RSIndex15[1] < shortband15[1] and  RSIndex15 < shortband15[1]
                then Min(shortband15[1], newshortband15)
                else newshortband15;

def trend15 = if Crosses(RSIndex15, shortband15[1])
            then 1
            else if Crosses(longband15[1], RSIndex15)
            then -1
            else if !IsNaN(trend15[1])
            then trend15[1]
            else 1;

def FastAtrRsiTL15 = if trend15 == 1
                   then longband15
                   else shortband15;

def pFastAtrRsiTL15 = FastAtrRsiTL15;
def pRsiMa15 = rsi_ma15;
def OS = 30;
def OB = 70;




##################

def rsi30 = RSI(price = vClose30, length = RSI_Period).RSI;
def rsi_ma30 = MovingAverage(AverageType.EXPONENTIAL, rsi30, Slow_Factor);
def atr_rsi30 = AbsValue(rsi_ma30[1] - rsi_ma30);
def atr_rsi_ma30 = MovingAverage(AverageType.EXPONENTIAL, atr_rsi30, Wilder_Period);
def dar30 = MovingAverage(AverageType.EXPONENTIAL, atr_rsi_ma30, Wilder_Period) * QQE;

def DeltaFastAtrRsi30 = dar30;
def RSIndex30 = rsi_ma30;
def newshortband30 =  RSIndex30 + DeltaFastAtrRsi30;
def newlongband30 = RSIndex30 - DeltaFastAtrRsi30;

def longband30 = if RSIndex30[1] > longband30[1] and RSIndex30 > longband30[1]
               then Max(longband30[1], newlongband30)
               else newlongband30;

def shortband30 = if RSIndex30[1] < shortband30[1] and  RSIndex30 < shortband30[1]
                then Min(shortband30[1], newshortband30)
                else newshortband30;

def trend30 = if Crosses(RSIndex30, shortband30[1])
            then 1
            else if Crosses(longband30[1], RSIndex30)
            then -1
            else if !IsNaN(trend30[1])
            then trend30[1]
            else 1;

def FastAtrRsiTL30 = if trend30 == 1
                   then longband30
                   else shortband30;

def pFastAtrRsiTL30 = FastAtrRsiTL30;
def pRsiMa30 = rsi_ma30;


##################
plot Five = 0;
plot Fifteen = 1;
plot Thirty = 2;


### Color Coding
Five.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
Five.AssignValueColor(if pfastAtrRsiTL < prsiMa and prsima > OB then color.blue else if pfastAtrRsiTL < prsiMa then color.green else if  prsima < OS then color.white else color.red);
Fifteen.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
Fifteen.AssignValueColor(if pfastAtrRsiTL15 < prsiMa15 then color.green else color.red);
Thirty.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
Thirty.AssignValueColor(if pfastAtrRsiTL30 < prsiMa30 then color.green else color.red);

Five.SetLineWeight(5);
Fifteen.SetLineWeight(5);
Thirty.SetLineWeight(5);

http://tos.mx/b0AAp9f

An Example from NVDA, We can see the higher Aggregation period is staying Green overall with a few dips on the lower 5m time frame I've been using.
I do plan on adding a "Flat" trend that QQE has to point out when a crossover could be occurring, but still figuring out a few more variables to that equation(I.E, Above or Below 50, How often they matter above 70 or below 30, etc etc)

QQEVExample.jpg
 
thanks looks great. the coloring of bubbles get changed during live trading?

can we have a label that indicates the result of the three bubbles?

sorry been too long!
 
@tem2005 There is a chance of the bubbles getting changed live(only the current one, not past) , more often than not it's when there is a cross that is being attempted or from sudden Spikes/Drops. Like what happened with BYND today on the drop down of News.

I could look into adding a label to make it easier to understand.
 
appreciated that so much

so the 5 min bubble itself represents the current candle forming?
It's default set for working on the 5m chart, since that's what I mostly use, but you can set it up for any timeframe you want. You can even change the agg periods to 10m and 15m, if that's what you prefer.

Just remember the bottom row will always be the current timeframe for the chart.
 
@Xiuying is there a chance for the 15 or 30min bubbles to change the last representative bubbles after closing of the candle?
For example, if 15 min cureent bubbles red and candled closed green somewhat big, so last 3 bubbles get changed to green?

I hope I explained it well!
 
@Xiuying is there a chance for the 15 or 30min bubbles to change the last representative bubbles after closing of the candle?
For example, if 15 min cureent bubbles red and candled closed green somewhat big, so last 3 bubbles get changed to green?

I hope I explained it well!
You explained it well, don't worry.

My assumption would be that they do if they're apart of that 15m/30m interval. Going over the past data as well, for the 15m and 30m, you can always see that the start or end of their respected time frames.

Actually, I might just add in some form of grouping for the aggregated periods to make it easier to see when certain bars are starting/ending.

Hm, Another idea as well I could try.
 
yes, i asked because i saw the majority get changed right at the start of forming the candle which may indicate that after the candle closing it paints its meant bubbles..But then i saw some changed within the forming process. i think we need to test it using Demand.
 
yes, i asked because i saw the majority get changed right at the start of forming the candle which may indicate that after the candle closing it paints its meant bubbles..But then i saw some changed within the forming process. i think we need to test it using Demand.
OnDemand has been buggy for me as of late, but I'll be sure to keep an eye on it as I trade throughout the day.
 
OnDemand has been buggy for me as of late, but I'll be sure to keep an eye on it as I trade throughout the day.
I have tried it a couple times again in the past week and it's essentially worthless...!!! :mad: Locks up, lags, sporadic trade entries and exits...

During the day you're better off using Paper Trading...
 
I have tried it a couple times again in the past week and it's essentially worthless...!!! :mad: Locks up, lags, sporadic trade entries and exits...

During the day you're better off using Paper Trading...
I'm glad It's not just me who is having issues with OnDemand. I messaged support about it, but they gave the generic "Not our fault" statement.
 
Worked for me, only on the 15-minute time frame though. Would love to see a larger time frame for larger moves but still great work. Really helps enrty
 
Is there any way that the time periods can be made to reflect smaller time periods like 1min, 2min, and 5 min?
Yea, you would just need to go into Studies and click the Cogwheel next to the indicator and change it to those periods. However, if you're current chart is on a higher time period, then the lower ones won't work.

However, I only have 1/3/5 as the smallest ones, don't have Two since I saw it as Redundant.
 
Is there a way to turn this into a scan? I've given the condition wizard a go, but didn't know what to choose in the middle panel or the right panel. I'd like to scan for when it is all green(&blue) dots or red(&white) dots. For the daily chart, the other two periods would be weekly and monthly.
 
Last edited:
Are alerts possible for secondary aggregations? For when it is all green/blue or red/white?

That depends on the type of alert... Alerts should be possible anywhere that secondary aggregations are allowed...
 

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

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
343 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