#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © millerrh
#// Version 1.3
#// The SPX Intraday Mood Indicator tries to gauge the intraday market direction of the S&P 500 (SPX) by focusing on internal market data.
#// Overall strength/weakness is converted into a directional Mood percentage.
#// Based on the 0DTE Mood Indicator concept.
#// Use at your own risk and discretion. Potential trade ideas offer no guarantees. Intraday Charts Only. Turn off extended hours data. Only works on SPX.
#// 1.1 Update: Swap out Sector Pull for "Highly Weighted Stocks" pull in an attempt to better capture the pull of the highest weighted stocks on the S&P. Some additional code cleanup.
#// 1.2 Update: Convert to Pine v5 and update highly weighted stocks weightings.
#// 1.3 Update: Added ability for user to configure/update highlyl weighted stocks as Inputs.
#indicator('SPX Intraday Mood', overlay=false)
# Converted by Sam4Cok@Samer800 - 03/2024
declare lower;
input showLabels = yes;
input smoothingLength = 3; #, minval=1, maxval=10, title='Smoothing Length',
input avgLength = 5; #, minval=1, maxval=10, title='Average Length'
input moodRecommendationPercent = 40; #, minval=0, maxval=100, title='Mood Recommendation Percent'
input showMoodRanges = yes; #, title='Show Mood Ranges?'
input stock1 = "AAPL"; #, group='heavy weighted stocks', inline='1')
input weight1 = 7.0; #, group='heavy weighted stocks', inline='1') //AAPL
input stock2 = "MSFT"; #, group='heavy weighted stocks', inline='2')
input weight2 = 5.6; #, group='heavy weighted stocks', inline='2') //MSFT
input stock3 = "AMZN"; #, group='heavy weighted stocks', inline='3')
input weight3 = 3.3; #, group='heavy weighted stocks', inline='3') //AMZN
input stock4 = "TSLA"; #', group='heavy weighted stocks', inline='4')
input weight4 = 2.0; #, group='heavy weighted stocks', inline='4') //TSLA
input stock5 = "GOOGL"; #', group='heavy weighted stocks', inline='5')
input weight5 = 1.9; #, group='heavy weighted stocks', inline='5') //GOOGL
input stock6 = "GOOG"; #', group='heavy weighted stocks', inline='6')
input weight6 = 1.7; #, group='heavy weighted stocks', inline='6') //GOOG
input stock7 = "BRK/B"; #', group='heavy weighted stocks', inline='7')
input weight7 = 1.6; #, group='heavy weighted stocks', inline='7') //BRK.B
input stock8 = "UNH"; #', group='heavy weighted stocks', inline='8')
input weight8 = 1.5; #, group='heavy weighted stocks', inline='8') //UNH
input stock9 = "JNJ"; #', group='heavy weighted stocks', inline='9')
input weight9 = 1.4; #, group='heavy weighted stocks', inline='9') //JNJ
input stock10 = "XOM"; #', group='heavy weighted stocks', inline='10')
input weight10 = 1.4; #, group='heavy weighted stocks', inline='10') //XOM
def na = Double.NaN;
def last = IsNaN(close);
DefineGlobalColor("pos", CreateColor(38, 166, 154));
DefineGlobalColor("neg", CreateColor(240, 83, 80));
#vwma(source, length)
script VWMA {
input src = close;
input len = 14;
input vol = volume;
def nom = Average(src * vol, len);
def den = Average(vol, len);
def VWMA = nom / den;
plot result = VWMA;
}
#// === SPX & VIX PERCENT CHANGE ===
def currentSPX = if !last then close(Symbol = "SPX") else currentSPX[1]; # // SPX Current Value
def closeSPX = if !last then close(Symbol = "SPX", Period = "DAY")[1] else closeSPX[1]; # // SPX Daily Close
def SPXchg = (currentSPX - closeSPX) / closeSPX * 100;
def SPXchgRnd = Round(SPXchg, 2); # // ~ variable for populating into table
def closeVIX = if !last then close(Symbol = "VIX", Period = "DAY")[1] else closeVIX[1]; # // VIX Daily Close
def currentVIX = if !last then close(Symbol = "VIX") else currentVIX[1]; # // VIX Current Value
def VIXchg = (currentVIX - closeVIX) / closeVIX * 100;
def VIXchgRnd = Round(VIXchg, 2); # // ~ variable for populating into table
#// plot(SPXchg)
def SPXRange = 0.25;
def SPXPctChangePoints = if SPXchg > SPXRange * 6 then 2 else
if SPXchg > SPXRange * 4 then 1.5 else
if SPXchg > SPXRange then 1 else
if SPXchg < SPXRange * -6 then -2 else
if SPXchg < SPXRange * -4 then -1.5 else
if SPXchg < SPXRange * -1 then -1 else 0;
def weightSum = weight1 + weight2 + weight3 + weight4 + weight5 + weight6 + weight7 + weight8 + weight9 + weight10;
def curr1 = if !last then close(Symbol = stock1) else curr1[1];
def clos1 = if !last then close(Symbol = stock1, Period = "DAY")[1] else clos1[1];
def curr2 = if !last then close(Symbol = stock2) else curr2[1];
def clos2 = if !last then close(Symbol = stock2, Period = "DAY")[1] else clos2[1];
def curr3 = if !last then close(Symbol = stock3) else curr3[1];
def clos3 = if !last then close(Symbol = stock3, Period = "DAY")[1] else clos3[1];
def curr4 = if !last then close(Symbol = stock4) else curr4[1];
def clos4 = if !last then close(Symbol = stock4, Period = "DAY")[1] else clos4[1];
def curr5 = if !last then close(Symbol = stock5) else curr5[1];
def clos5 = if !last then close(Symbol = stock5, Period = "DAY")[1] else clos5[1];
def curr6 = if !last then close(Symbol = stock6) else curr6[1];
def clos6 = if !last then close(Symbol = stock6, Period = "DAY")[1] else clos6[1];
def curr7 = if !last then close(Symbol = stock7) else curr7[1];
def clos7 = if !last then close(Symbol = stock7, Period = "DAY")[1] else clos7[1];
def curr8 = if !last then close(Symbol = stock8) else curr8[1];
def clos8 = if !last then close(Symbol = stock8, Period = "DAY")[1] else clos8[1];
def curr9 = if !last then close(Symbol = stock9) else curr9[1];
def clos9 = if !last then close(Symbol = stock9, Period = "DAY")[1] else clos9[1];
def curr10 = if !last then close(Symbol = stock10) else curr10[1];
def clos10 = if !last then close(Symbol = stock10, Period = "DAY")[1] else clos10[1];
def HW1 = (curr1 - clos1) / clos1 * 100 * weight1;
def HW2 = (curr2 - clos2) / clos2 * 100 * weight2;
def HW3 = (curr3 - clos3) / clos3 * 100 * weight3;
def HW4 = (curr4 - clos4) / clos4 * 100 * weight4;
def HW5 = (curr5 - clos5) / clos5 * 100 * weight5;
def HW6 = (curr6 - clos6) / clos6 * 100 * weight6;
def HW7 = (curr7 - clos7) / clos7 * 100 * weight7;
def HW8 = (curr8 - clos8) / clos8 * 100 * weight8;
def HW9 = (curr9 - clos9) / clos9 * 100 * weight9;
def HW10 = (curr10 - clos10) / clos10 * 100 * weight10;
def HW = (HW1 + HW2 + HW3 + HW4 + HW5 + HW6 + HW7 + HW8 + HW9 + HW10) / weightSum;
def HWdif = HW - SPXchg;
def HWdifRnd = Round(HWdif, 2); # // ~ variable for heavy weight pull in table
def HWPctChangePoints = if HWdif > 1.5 then 2 else
if HWdif > .75 then 1 else
if HWdif > .35 then 0.5 else
if HWdif < -1.5 then -2 else
if HWdif < -.75 then -1 else
if HWdif < -.35 then -0.5 else 0;
def emaHW = ExpAverage(HWdif, avgLength);
def HWTrendPoints = if HWdif > emaHW then 1 else if HWdif < emaHW then -1 else 0;
#// === MARKET INTERNALS ===
#// S&P Tick (uses NYSE tick data instead of S&P)
def tickTrend = 300;
def instantTick = close(Symbol = "$TICK"); # // ~ varaible for tick information for table
def smoothedTick = hlc3(Symbol = "$TICK");
def tickspPoints = if smoothedTick > tickTrend then 1 else
if smoothedTick < tickTrend * -1 then -1 else 0;
def emaTick = ExpAverage(smoothedTick, avgLength);
def tickspTrendPoints = if smoothedTick > emaTick then 1 else
if smoothedTick < emaTick then -1 else 0;
#// S&P UVOL-DVOL (uses NYSE UVOL/DVOL intead of S&P)
def volTrend = 1.2;
def UVOL = close(Symbol = "$UVOL");
def DVOL = close(Symbol = "$DVOL");
def UvolDvolRatio = if UVOL >= DVOL then UVOL / DVOL else -DVOL / UVOL;
def UvolDvolRatioRnd = Round(UvolDvolRatio, 2); # // ~ varaible for Uvol/dvol for table
def UDRatioPoints = if UvolDvolRatio > volTrend * 3 then 3 else
if UvolDvolRatio > volTrend * 2 then 2 else
if UvolDvolRatio > volTrend then 1 else
if UvolDvolRatio < volTrend * -3 then -3 else
if UvolDvolRatio < volTrend * -2 then -2 else
if UvolDvolRatio < volTrend then -1 else 0;
def emaUD = ExpAverage(UvolDvolRatio, avgLength);
def UDRatioTrendPoints = if UvolDvolRatio > emaUD then 1 else
if UvolDvolRatio < emaUD then -1 else 0;
#// S&P Advance/Decline - using NYSE ADVDEC
def adspd = close(Symbol = "$ADD"); #// ~ varaible for S&P advance delcline for table
def ADPoints = if adspd > 1800 then 3 else
if adspd > 1200 then 2 else
if adspd > 300 then 1 else
if adspd < -1800 then -3 else
if adspd < -1200 then -2 else
if adspd < -300 then -1 else 0;
def emaAD = ExpAverage(ADPoints, avgLength);
def ADAvgPoints = if ADPoints > emaAD then 1 else
if ADPoints < emaAD then -1 else 0;
#// === MARKET STAGE ===
def price = close(Symbol = "SPY");
def volSpy = volume(Symbol = "SPY");
def vwma8 = vwma(price, 8, volSpy);
def vwma21 = vwma(price, 21, volSpy);
def vwma34 = vwma(price, 34, volSpy);
def bullish = vwma8 > vwma21 and vwma21 > vwma34; # ? true : false;
def bearish = vwma8 < vwma21 and vwma21 < vwma34; # ? true : false;
def consolidation = !bullish and !bearish; # ? true : false;
def marketStagePoints = if bullish then 2 else
if bearish then -2 else
if consolidation and price > vwma8 then 1 else
if consolidation and price < vwma8 then -1 else 0;
script nz {
input src = close;
def nz = if IsNaN(src) then 0 else src;
plot out = nz;
}
#// === MARKET MOOD ===
#// Component weighting
def comp1 = nz(SPXPctChangePoints) * .75;
def comp2 = nz(HWPctChangePoints) * 1;
def comp3 = nz(HWTrendPoints) * 1.5;
def comp4 = nz(tickspPoints) * 1;
def comp5 = nz(tickspTrendPoints) * 1.5;
def comp6 = nz(UDRatioPoints) * 1;
def comp7 = nz(UDRatioTrendPoints) * 1.5;
def comp8 = nz(ADPoints) * 1;
def comp9 = nz(ADAvgPoints) * 1.5;
def comp10 = nz(marketStagePoints) * 1;
def moodNormalCalc = (comp1 + comp2 + comp3 + comp4 + comp5 + comp6 + comp7 + comp8 + comp9 + comp10) * 10;
def moodBase = if moodNormalCalc < 0 then Max(moodNormalCalc, -100) else Min(moodNormalCalc, 100);
def currentMood = ExpAverage(moodBase, smoothingLength);
def condition = if currentMood > moodRecommendationPercent then 1 else
if currentMood < moodRecommendationPercent * -1 then -1 else 0;
#// === RECOMMENDATIONS ===
def zonestep = (100 - moodRecommendationPercent) / 2;
def recommendation = if currentMood > moodRecommendationPercent and currentMood <= moodRecommendationPercent + zonestep then 1 else
if currentMood > moodRecommendationPercent + zonestep then 2 else
if currentMood < moodRecommendationPercent * -1 + -zonestep then -2 else
if currentMood < moodRecommendationPercent * -1 and currentMood >= moodRecommendationPercent * -1 - zonestep
then -1 else 0; # // Iron Co
#// === PLOTTING AND TABLES ===
#// Plotting
def bullline = if showMoodRanges and !last then moodRecommendationPercent else na;
def bearline = if showMoodRanges and !last then -moodRecommendationPercent else na;
def zeroline = if last then na else 0;
def topline = if last then na else 100;
def bottomline = if last then na else -100;
def moodColor = if currentMood >= moodRecommendationPercent then 1 else
if currentMood <= moodRecommendationPercent * -1 then -1 else 0;
plot moodLine = if last then na else currentMood; #, color=moodColor, linewidth=2)
plot bull = bullline; #, color=color.new(posColor, 60), linewidth=1)
plot bear = bearline; #, color=color.new(negColor, 60), linewidth=1)
plot zero = zeroline; #, color=color.new(neuColor, 60), linewidth=1)
plot top = topline; #, color=color.new(color.gray, 60), linewidth=1)
plot bot = bottomline; #, color=color.new(color.gray, 60), linewidth=1)
moodLine.SetLineWeight(2);
moodLine.AssignValueColor(if moodColor>0 then GlobalColor("pos") else
if moodColor<0 then GlobalColor("neg") else Color.GRAY);
bull.SetDefaultColor(Color.DARK_GREEN);
bear.SetDefaultColor(Color.DARK_RED);
zero.SetDefaultColor(Color.DARK_GRAY);
top.SetDefaultColor(Color.DARK_GRAY);
bot.SetDefaultColor(Color.DARK_GRAY);
AddLabel(showLabels,"SPX Change: " + SPXchgRnd + "%", if SPXchgRnd > 0 then GlobalColor("pos") else GlobalColor("neg"));
AddLabel(showLabels,"VIX: " + currentVIX + "(" + VIXchgRnd + "%)",if VIXchgRnd > 0 then GlobalColor("pos") else GlobalColor("neg"));
AddLabel(showLabels,"HW Pull: " + HWdifRnd + "%", if HWPctChangePoints >= 0.5 then GlobalColor("pos") else
if HWPctChangePoints <= -0.5 then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, "TICK: " + instantTick,if instantTick > tickTrend then GlobalColor("pos") else
if instantTick < tickTrend * -1 then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, "VOL: " + UvolDvolRatioRnd + ":1",if UvolDvolRatioRnd > volTrend then GlobalColor("pos") else
if UvolDvolRatioRnd < volTrend then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, "A/D: " + adspd,if ADPoints >= 1 then GlobalColor("pos") else
if ADPoints <= 1 then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, if marketStagePoints == 2 then "Trend: Acceleration" else
if marketStagePoints ==-2 then "Trend: Deceleration" else
if marketStagePoints == 1 then "Trend: Bullish Consolidation" else
if marketStagePoints ==-1 then "Trend: Bearish Consolidation" else "Trend: No Trend",
if marketStagePoints > 0 then GlobalColor("pos") else
if marketStagePoints < 0 then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, if condition > 0 then "Mood: Bullish " + Round(currentMood, 2) + "%" else
if condition < 0 then "Mood: Bearish " + Round(currentMood, 2) + "%" else
"Mood: Neutral " + Round(currentMood, 1) + "%",
if condition > 0 then GlobalColor("pos") else
if condition < 0 then GlobalColor("neg") else Color.GRAY);
AddLabel(showLabels, if recommendation == 1 then "Trade: Skewed Bullish Iron Condor" else
if recommendation == 2 then "Trade: Put Credit Spread" else
if recommendation == -2 then "Trade: Call Credit Spread" else
if recommendation == -1 then "Trade: Skewed Bearish Iron Condor" else "Trade: Iron Condor" ,
if recommendation > 0 then GlobalColor("pos") else
if recommendation < 0 then GlobalColor("pos") else Color.GRAY);
#-- END of CODE