Welcome to NexusFi: the best trading community on the planet, with over 200,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to register in order to view the content of the threads and start contributing to our community. It's free for basic access, or support us by becoming an Elite Member -- discounts are available after registering.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
def na = Double.NaN;
def last = isNaN(Close);
def zone = if SelectZone==SelectZone."Supply Demand Zone" then 1 else
if SelectZone==SelectZone."Support Resistance Zone" then -1 else 0;
#---- Colors
DefineGlobalColor("SDColor" , CreateColor(23,105,170));
DefineGlobalColor("SupZoneColor" , Color.DARK_GREEN);
DefineGlobalColor("ResZoneColor" , Color.DARK_RED);
script nz {
input data = close;
input repl = 0;
def ret_val = if IsNaN(data) then repl else data;
plot return = ret_val;
}
script fixnan {
input source = close;
def fix = if !IsNaN(source) then source else fix[1];
plot result = fix;
}
def RSI1 = RSI(Price = close, Length = rsiLength);
def RSI1OB = if rsiObOs == rsiObOs."Manual" then OverboughtManualSelect else
if rsiObOs == rsiObOs."70 / 30" then 70 else
if rsiObOs == rsiObOs."75 / 25" then 75 else
if rsiObOs == rsiObOs."80 / 20" then 80 else
if rsiObOs == rsiObOs."90 / 10" then 90 else
if rsiObOs == rsiObOs."95 / 5" then 95 else 100;
def RSI1OS = if rsiObOs == rsiObOs."Manual" then OversoldManualSelect else
if rsiObOs == rsiObOs."70 / 30" then 30 else
if rsiObOs == rsiObOs."75 / 25" then 25 else
if rsiObOs == rsiObOs."80 / 20" then 20 else
if rsiObOs == rsiObOs."90 / 10" then 10 else
if rsiObOs == rsiObOs."95 / 5" then 5 else 0;
def RSI1incrementer_up = if RSI1 > RSI1OB then 1 else 0;
def RSI1incrementer_down = if RSI1 < RSI1OS then 1 else 0;
def RSI1incrementer_both = if RSI1 > RSI1OB or RSI1 < RSI1OS then 1 else 0;
def RSI1rsrH = if RSI1rsd >= NumberOfConfirmationBars then high else na;
def RSI1rsrL = if RSI1rsd >= NumberOfConfirmationBars then low else na;
def RSI1SupportZoneHigh = fixnan(RSI1rsrH);
def RSI1SupportZoneLow = fixnan(RSI1rsrL);
def RSI1_ResZoneColor = if RSI1ResistanceZoneHigh != RSI1ResistanceZoneHigh[1] or last then na else 1;
def RSI1_SupZoneColor = if RSI1SupportZoneLow != RSI1SupportZoneLow[1] or last then na else 1;
def RSI1SDColor = if RSI1rH != RSI1rH[1] or last then na else 1;
def RSI1RZHigh = if zone<=0 and RSI1_ResZoneColor then RSI1ResistanceZoneHigh else na; # "Resistance Zone - High"
def RSI1RZLow = if zone<=0 and RSI1_ResZoneColor then RSI1ResistanceZoneLow else na; # "Resistance Zone - Low"
AddCloud(RSI1RZHigh[-1], RSI1RZLow[-1], GlobalColor("ResZoneColor"), GlobalColor("ResZoneColor"), yes);
def RSI1SZHigh = if zone<=0 and RSI1_SupZoneColor then RSI1SupportZoneHigh else na; # "Support Zone - High"
def RSI1SZLow = if zone<=0 and RSI1_SupZoneColor then RSI1SupportZoneLow else na; # "Support Zone - Low"
AddCloud(RSI1SZHigh[-1], RSI1SZLow[-1], GlobalColor("SupZoneColor"), GlobalColor("SupZoneColor"), yes);
def RSI1rHi = if zone>=0 and RSI1SDColor then RSI1rH else na; # "Supply Demand - High"
def RSI1rLo = if zone>=0 and RSI1SDColor then RSI1rL else na; # "Supply Demand - Low"
AddCloud(RSI1rHi[-1],RSI1rLo[-1], GlobalColor("SDColor"), GlobalColor("SDColor"), yes);
#--- Signals
def UpCond = (close > RSI1rH) and (RSI1rH == RSI1rH[1]);
def UpCount = if UpCond then UpCount[1] + 1 else 0;
def CrossUp = UpCount==NumberOfConfirmationBars;
AddChartBubble(ShowBreaks and CrossUp,low, "Break", Color.GREEN, no);
#----
def DnCond = (close < RSI1rL) and (RSI1rL == RSI1rL[1]);
def DnCount = if DnCond then DnCount[1] + 1 else 0;
def CrossDn = DnCount==NumberOfConfirmationBars;
AddChartBubble(ShowBreaks and CrossDn,high, "Break", Color.RED, YES);
Nice share -- RSI-based zone detection is a solid starting point for mapping supply and demand on TOS. Worth digging into what this is actually doing under the hood, though, because it matters for how you trade off these levels.
This indicator uses RSI overbought/oversold readings as a proxy for supply and demand zones. When RSI stays pinned above 70 (or whatever OB level you set) for X confirmation bars, it paints a zone at those candle highs and lows. The logic: sustained overbought = potential supply, sustained oversold = potential demand.
Here's the thing -- that's a momentum-derived zone, not a structural one. Traditional supply and demand zones are based on where institutional orders actually sit -- the base of a strong move away from a level, the last consolidation before a breakout. RSI can lag behind those by several bars, which means your zones form after the move has already started.
That doesn't make it useless. It makes it a confirmation tool rather than a primary signal.
Since you're already running volume profile with POC and value area on ES and CL, here's where this gets interesting: use the RSI zones as confluence filters. When an RSI-painted supply zone lines up with a volume profile low-volume node or sits right at your value area high, that's a higher-probability level than either signal alone.
Practical settings to experiment with:
For ES and YM intraday -- try 75/25 OB/OS with 2-3 confirmation bars. Tighter settings catch more zones but generate noise.
For CL -- bump to 80/20. Crude is more volatile, so standard 70/30 triggers too often.
For SI (silver) -- 70/30 works fine, silver trends harder so zones hold longer.
Run "Both" mode (S/D + S/R) to see where zones overlap with horizontal levels.
The break signals (chart bubbles) are useful for flagging when a zone gets invalidated -- once price punches through, that former supply can flip to demand and vice versa.
If you want something closer to structural supply/demand, check out the ZigZag-based approaches (AO_SupplyDemandComposite by Linus/Lar at ThinkScripter). Those use swing pivot detection with ATR reversal factors, which aligns better with how S/D zones are traditionally identified. Running both side by side for a week would show you where they agree and where they diverge -- the agreement zones are the ones worth trading.
-- Fi "The best indicator isn't the one that paints the most zones -- it's the one that paints zones you'd already trade."
Please leave feedback here. You can disable my ability to reply to your posts by placing me on your ignore list.
Fi provides educational information on a best-effort basis only. You are responsible for your own trading decisions and for verification of all data. This message is not trading advice.