• Get $30 off VIP with code SUMMER30. Ends July 27. Happy trading!

RSI Scanner for ThinkorSwim (Oversold/Overbought Scan)


Hello, Is there a way to scan a watchlist with the current price has just touched RSI 70% or 30% or within the last 5 bars? I am trying to find which stock on my watchlist is at oversold or overbought area within the last 5 bars. Thanks!!

# RSI Scan
# Nick Name NAG®
# 3.15.2016

# If you'd like to scan for stocks that have crossed the an input level (e.g. 30 level)
# on the RSI for the first time in 3 years.
# The scanner limitation is 750 daily bars. It doesn't go any further
# back than that. TOS limits historical scan data to 730 days for daily
# and up aggregation, so I'm not sure there's enough to do that accurately.
# This should get what's available within TOS limits.

rec rsi_cross = CompoundValue(1, if RSI() crosses above 30 then rsi_cross[1] + 1 else rsi_cross[1], 0);
plot scan = rsi_cross[1] == 0 and rsi_cross == 1;

# End Study
Last edited by a moderator:


It's effortless. Here is an example of how to set up a scanner for RSI crossing above the oversold line (30).


Once you have this setup, you can also select the specific watchlist that you wish to scan in. This could be your own personal watchlist or any of the pre-built watchlists by ThinkorSwim.


By default, the scanner will run on the Daily (D) chart; you can change this to any other timeframe of your choice.

The Grim One

New member
Hello All,

Brand new here, so I'll jump right in. Found this forum looking for some info on how to create a custom scan.

My trading idea is simple. There are stocks that have fairly set patterns of "oversold" RSI that, after a generally consistent period of time wander into "overbought".

The time frame I'm talking about is measured roughly in weeks.

FB, and MU are a couple of examples.

I'd be interested in finding as many stocks as I can that fit this pattern. Because well... it doesn't work 100% of the time so eggs in many baskets, and stocks that fit this pattern are not going to do it forever. Thus a scan.

Does anyone have anything like this?

My coding experience is limited to having written a simple function calculator (+, -, /, *) in C# back in 2006.


The RSI Fractal indicator is really solid when you have an up or down arrow. I've tried to create a scan to show me stocks that have a up or down arrow within the last bar but have failed. I'm trying to scan for stocks at the end of the day primarily for swing trade candidates. Any help would be greatly appreciated.

# RSIwithFractalPivots_Amalia

# reposted to chatroom 04.18.2018

########START  Code

declare lower;

input length = 14;

input over_Bought = 70;

input over_Sold = 30;

input price = close;

input averageType = AverageType.WILDERS;

input New_HI_LO = 30;

def NetChgAvg = MovingAverage(averageType, price - price[1], length);

def TotChgAvg = MovingAverage(averageType, AbsValue(price - price[1]), length);

def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;

plot RSI = 50 * (ChgRatio + 1);

plot OverSold = over_Sold;

plot OverBought = over_Bought;

RSI.DefineColor("OverBought", GetColor(5));

RSI.DefineColor("Normal", GetColor(7));

RSI.DefineColor("OverSold", GetColor(1));

RSI.AssignValueColor(if RSI > over_Bought then RSI.color("OverBought") else if RSI < over_Sold then RSI.color("OverSold") else RSI.color("Normal"));



plot NEWHIGH = if RSI == highest(RSI, new_HI_LO) then RSI else Double.NAN; 




plot NEWLOW = if RSI == lowest(RSI, new_HI_LO) then RSI else Double.NAN; 




# Fractals

# 1/5/17 Amalia added Aggregation periods?

def H = RSI; 

def L = RSI; 

input sequenceCount = 10;

def maxSideLength = sequenceCount + 10;

def upRightSide = fold i1 = 1 to maxSideLength + 1 

                  with count1 

                  while count1 != sequenceCount and 

                        count1 != -1 

                  do if GetValue(H, -i1) > H or 

                       (GetValue(H, -i1) == H and

                        count1 == 0) 

                     then -1

                     else if GetValue(H, -i1) < H 

                          then count1 + 1 

                          else count1;

def upLeftSide = fold i2 = 1 to maxSideLength + 1 

                 with count2 

                 while count2 != sequenceCount and 

                       count2 != -1 

                 do if GetValue(H, i2) > H or 

                      (GetValue(H, i2) == H and 

                       count2 >= 1) 

                    then -1

                    else if GetValue(H, i2) < H 

                         then count2 + 1 

                         else count2;

def downRightSide = fold i3 = 1 to maxSideLength + 1 

                    with count3 

                    while count3 != sequenceCount and 

                          count3 != -1 

                    do if GetValue(L, -i3) < L or 

                         (GetValue(L, -i3) == L and 

                          count3 == 0) 

                          then -1

                        else if GetValue(H, -i3) > L 

                             then count3 + 1 

                             else count3;

def downLeftSide = fold i4 = 1 to maxSideLength + 1 

                   with count4 

                   while count4 != sequenceCount and 

                         count4 != -1

                   do if GetValue(L, i4) < L or 

                        (GetValue(L, i4) == L and 

                         count4 >= 1) 

                      then -1

                      else if GetValue(L, i4) > L 

                      then count4 + 1 

                      else count4;

plot UpFractal = if upRightSide == sequenceCount and 

                    upLeftSide == sequenceCount 

                 then RSI 

                 else Double.NaN;

plot DownFractal = if downRightSide == sequenceCount and 

                      downLeftSide == sequenceCount 

                   then RSI

                   else Double.NaN;







def Pre_hi = if !isnan(upfractal) then upfractal else pre_hi[1];

plot high_line = pre_hi;



def Pre_lo = if !isnan(downFractal) then downFractal else pre_lo[1];

plot lo_line = pre_lo;




if RSI >= OverBought && RSI >= RSI[1]

    then "RSI OB & Rising: " +round(RSI, 2)

else if RSI >= OverBought && RSI < RSI[1]

    then "RSI OB & Falling: " +round(RSI, 2)

else if RSI <= OverSold && RSI < RSI[1]

    then "RSI OS & Falling: " +round(RSI, 2)

else if RSI <= OverSold && RSI >= RSI[1]

    then "RSI OS & Rising: " +round(RSI, 2)

else if RSI < OverBought && RSI > OverSold && RSI >= RSI[1]

    then "RSI Rising: " +round(RSI, 2)

else if RSI < OverBought && RSI > OverSold && RSI < RSI[1]

    then "RSI Falling: " +round(RSI, 2)

else "",

if RSI >= OverBought && RSI >= RSI[1]

    then color.dark_orange

else if RSI >= OverBought && RSI < RSI[1]

    then color.yellow

else if RSI <= OverSold && RSI < RSI[1]

    then createcolor(000, 100, 100)

else if RSI <= OverSold && RSI >= RSI[1]

    then color.cyan

else if RSI < OverBought && RSI > OverSold && RSI >= RSI[1]

    then color.green

else if RSI < OverBought && RSI > OverSold && RSI < RSI[1]

    then color.red

else color.gray);

plot Buffer = if RSI <= OverSold then RSI - 10 else if RSI >= OverBought then RSI + 10 else double.nan;




####END Code
The following chart shows strength in symbols with RSI above 60 and daily RSI > weekly RSI. This is done by me with Tradestation.

Can we develop explore the idea with TOS? I would appreciate a scan for thinkorswim.


Last edited by a moderator:


Could someone please help me find RSi scanner for TOS that will scan for RSI cross under Oversold and overbought values both set to lets say 90, cross less than both values combined? Instead of having the typical 2 separate values of 30 and 70, require both combined at lets say "30" or "70" and want the cross greater or less than scanner for my want and needs over 7,8,9 min aggregation instead of pre set 5, 10 ones if possible?
I have searched the forum and could not find something like this.


You can easily set that up using the scanner. Something like this would work.


close crosses above SimpleMovingAvg("length" = 49)."SMA" and RSI()."RSI" is greater than 69
So say I want to scan for stocks with 2 conditions, and I want to add a third. Example being I want a stock where the RSI has not gone below 50 in the last 14 days(bars). Anyone know the proper way to say this without having to use condition wizard?


New member
Hi -

This is my first time posting but have been reading through the forum for awhile now. Great information here.
I'm trying to create a RSI scan, where the RSI line turns red before it reaches the 70 line (OverBought). For example the RSI turns red but the value is at 61, or any value below the 70 line. I would like to use the 5-10 min time frame. Can there be an alert exactly when the RSI turns red even before the close of the candle?
See image below.

Thank you for any insight anyone might have.


Well-known member
I don't have a scan for it yet - still trying to figure that out. Not sure how to scan for the RSI turning red?

@rhmillion You can't scan for a "color" in Thinkorswim using Thinkscript, you can only scan for the "condition" that triggers the color to be painted a color... What causes the color to be red on "your" chart...??? That's what you scan for... But remember, everyone's chart doesn't paint the same colors... That's why we use "conditions", or "criteria"... And the default color is "orange", not "red"... But I digress...

What makes the color turn color is being overbought... And the default "condition" is rsi crosses 70 or rsi crosses overBought... There should be a plot for the breakout that you can scan for... In your Conditon Wizard it would end up being close crosses above RSI()."OverBought" if you are using the default RSI...

That should be enough breadcrumbs for you to figure things out...


Active member
@mdtn @rhmillion take a look at my post and script below. Since you have a watchlist already, then you can just add a column into the watchlist that will tell you oversold or overbought in the last bars. I posted the script and screenshot below. The script is set for 80/20, you can just modify that to 70/30 on a 1-minute aggregation. I've tried and tested to add an alert inside the script in watchlist, it will not fire and not allowed (asked support already).

Good luck! @cabe1332

Last edited:

Similar threads