Thanks to @BrooklynMintCapital for his lower study which is more comprehensive.
As a person who doesn't like a lot on my chart I converted his Dynamic Net Flow Lower Study into an upper chart label that shows DynamicPriceFlow only and thank him for the framework!
mod note:
Here is the code as an Upper Label only showing if the trend is Bullish or Bearish.
lower study:
As a person who doesn't like a lot on my chart I converted his Dynamic Net Flow Lower Study into an upper chart label that shows DynamicPriceFlow only and thank him for the framework!

mod note:
code for lower study can be found further below
any questions? https://usethinkscript.com/threads/goldensniper-options-dashboard-for-thinkorswim.20997/
Here is the code as an Upper Label only showing if the trend is Bullish or Bearish.
Code:
# Dynamic Net Flow UPPER LABEL ONLY
# @brooklyngfellaz 3/21/2025
#Revamped on_volume 7/29/25 to show only a Dynamic Price Label on_volume then upper chart. Thanks to @brooklyingfellaz for the original.
declare upper;
declare once_per_bar;
# Inputs
input smoothingPeriod = 10;
input lookbackPeriod = 75;
input separationFactor = 2.0;
input lineLabelOffset = 1;
input selectedOffset = "Offset 1";
input offset_1 = -1;
input offset_2 = 0;
input offset_3 = 4;
input offset_4 = 1;
# Stock price (close)
def stockPriceRaw = close;
# Regular market hours check (08:00 to 17:00 EST)
def isRegularHours = secondsFromTime(0435) >= 0 and secondsTillTime(1945) > 0;
# Smooth stock price using EMA
def stockPriceSmoothed = ExpAverage(stockPriceRaw, smoothingPeriod);
# Stock price range over lookback period
def stockPriceMax = Highest(stockPriceSmoothed, lookbackPeriod);
def stockPriceMin = Lowest(stockPriceSmoothed, lookbackPeriod);
def priceRange = stockPriceMax - stockPriceMin;
# Price change for direction
def priceChange = stockPriceSmoothed - stockPriceSmoothed[1];
# Raw Net Calls and Puts based on price movement
def rawNetCalls = if priceRange != 0 then priceChange / priceRange else 0;
def rawNetPuts = -rawNetCalls;
# Smooth Net Calls and Puts using EMA
def smoothedNetCalls = ExpAverage(rawNetCalls, smoothingPeriod);
def smoothedNetPuts = ExpAverage(rawNetPuts, smoothingPeriod);
# Range of smoothed Net Calls and Puts
def callsMax = Highest(smoothedNetCalls, lookbackPeriod);
def callsMin = Lowest(smoothedNetCalls, lookbackPeriod);
def putsMax = Highest(smoothedNetPuts, lookbackPeriod);
def putsMin = Lowest(smoothedNetPuts, lookbackPeriod);
# Scale to stock price range with separation
def scaledPriceRange = stockPriceMax - stockPriceMin;
def midPoint = (stockPriceMax + stockPriceMin) / 2;
# Use the full range of the vertical lines for scaling
def verticalRangeMin = stockPriceMin * 0.9;
def verticalRangeMax = stockPriceMax * 1.1;
def verticalRange = verticalRangeMax - verticalRangeMin;
# Scale stockPriceSmoothed, netCalls, and netPuts
def scaledStockPrice = if stockPriceMax != stockPriceMin then midPoint + (stockPriceSmoothed - stockPriceMin) * verticalRange * separationFactor / (stockPriceMax - stockPriceMin) else stockPriceSmoothed;
def scaledNetCalls = if callsMax != callsMin then midPoint + (smoothedNetCalls - callsMin) * verticalRange * separationFactor / (callsMax - callsMin) else stockPriceSmoothed;
def scaledNetPuts = if putsMax != putsMin then midPoint + (smoothedNetPuts - putsMin) * verticalRange * separationFactor / (putsMax - putsMin) else stockPriceSmoothed;
# Plot lines (only during regular hours)
def plotStockPrice = if isRegularHours then scaledStockPrice else Double.NaN;
def plotNetCalls = if isRegularHours then scaledNetCalls else Double.NaN;
def plotNetPuts = if isRegularHours then scaledNetPuts else Double.NaN;
# Zero line (midpoint reference)
def zeroLine = (stockPriceMin + stockPriceMax) / 2;
# Detect crossovers
def callsCrossAbovePuts = smoothedNetCalls crosses above smoothedNetPuts;
def callsCrossBelowPuts = smoothedNetCalls crosses below smoothedNetPuts;
# Track sentiment state (1 = bullish, -1 = bearish, 0 = neutral)
def sentimentState;
if callsCrossAbovePuts {
sentimentState = 1;
} else if callsCrossBelowPuts {
sentimentState = -1;
} else if IsNaN(sentimentState[1]) {
sentimentState = 0;
} else {
sentimentState = sentimentState[1];
}
# Calculate percentage distance from stock price
def callsPercentDiff = if plotStockPrice != 0 then ((scaledNetCalls - plotStockPrice) / stockPriceSmoothed) * 100 else 0;
def putsPercentDiff = if plotStockPrice != 0 then ((scaledNetPuts - plotStockPrice) / stockPriceSmoothed) * 100 else 0;
# Calculate percentage distance from stock price to zero line
def pricePercentDiff = if zeroLine != 0 then ((plotStockPrice - zeroLine) / zeroLine) * 100 else 0;
# Determine Net Flow sentiment (Bullish or Bearish)
def isBullish = scaledNetCalls > scaledNetPuts;
def isBearish = scaledNetPuts > scaledNetCalls;
# Check if calls or puts line is touching the zero line (within a small threshold)
def threshold = 0.01;
def callsAtZero = AbsValue(scaledNetCalls - zeroLine) <= threshold;
def putsAtZero = AbsValue(scaledNetPuts - zeroLine) <= threshold;
DefineGlobalColor("LabelGreen", CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed", color.downtick) ;
# Status indicators (using AddLabel instead of table)
AddLabel(yes, "Dynamic Price Flow: ", if isBullish then GlobalColor("LabelGreen") else if isBearish then GlobalColor("LabelRed") else Color.WHITE);
AddLabel(yes, if isBullish then "Bullish" else if isBearish then "Bearish" else "Neutral", if isBullish then GlobalColor("LabelGreen") else if isBearish then GlobalColor("LabelRed") else Color.WHITE);
lower study:
Ruby:
# Dynamic Net Flow Lower Study
# @brooklyngfellaz 3/21/2025
# https://usethinkscript.com/threads/goldensniper-options-dashboard-for-thinkorswim.20997/
declare lower;
declare once_per_bar;
# Inputs
input smoothingPeriod = 10;
input lookbackPeriod = 75;
input separationFactor = 2.0;
input lineLabelOffset = 1;
# Vertical line inputs
input plot_line_1 = yes;
input plot_line_2 = yes;
input plot_line_3 = yes;
input plot_line_4 = yes;
input plot_line_5 = yes;
input plot_line_6 = yes;
input Line_1_Hour = 9;
input inputMinute_1 = 30;
input Line_2_Hour = 10;
input inputMinute_2 = 0;
input Line_3_Hour = 11;
input inputMinute_3 = 0;
input Line_4_Hour = 13;
input inputMinute_4 = 0;
input Line_5_Hour = 15;
input inputMinute_5 = 0;
input Line_6_Hour = 16;
input inputMinute_6 = 0;
input Line_1_Width = 3;
input Line_2_Width = 3;
input Line_3_Width = 3;
input Line_4_Width = 2;
input Line_5_Width = 3;
input Line_6_Width = 2;
input Line_1_Style = "Dashed"; # ThinkScript doesn't support line styles for AddVerticalLine, but we'll keep for reference
input Line_2_Style = "Dashed";
input Line_3_Style = "Dashed";
input Line_4_Style = "Dashed";
input Line_5_Style = "Dashed";
input Line_6_Style = "Dashed";
input color_1 = "green";
input color_2 = "red";
input color_3 = "black";
input color_4 = "teal";
input color_5 = "black";
input color_6 = "teal";
input selectedOffset = "Offset 1";
input offset_1 = -1;
input offset_2 = 0;
input offset_3 = 4;
input offset_4 = 1;
# Stock price (close)
def stockPriceRaw = close;
# Regular market hours check (08:00 to 17:00 EST)
def isRegularHours = secondsFromTime(0435) >= 0 and secondsTillTime(1945) > 0;
# Smooth stock price using EMA
def stockPriceSmoothed = ExpAverage(stockPriceRaw, smoothingPeriod);
# Stock price range over lookback period
def stockPriceMax = Highest(stockPriceSmoothed, lookbackPeriod);
def stockPriceMin = Lowest(stockPriceSmoothed, lookbackPeriod);
def priceRange = stockPriceMax - stockPriceMin;
# Price change for direction
def priceChange = stockPriceSmoothed - stockPriceSmoothed[1];
# Raw Net Calls and Puts based on price movement
def rawNetCalls = if priceRange != 0 then priceChange / priceRange else 0;
def rawNetPuts = -rawNetCalls;
# Smooth Net Calls and Puts using EMA
def smoothedNetCalls = ExpAverage(rawNetCalls, smoothingPeriod);
def smoothedNetPuts = ExpAverage(rawNetPuts, smoothingPeriod);
# Range of smoothed Net Calls and Puts
def callsMax = Highest(smoothedNetCalls, lookbackPeriod);
def callsMin = Lowest(smoothedNetCalls, lookbackPeriod);
def putsMax = Highest(smoothedNetPuts, lookbackPeriod);
def putsMin = Lowest(smoothedNetPuts, lookbackPeriod);
# Scale to stock price range with separation
def scaledPriceRange = stockPriceMax - stockPriceMin;
def midPoint = (stockPriceMax + stockPriceMin) / 2;
# Use the full range of the vertical lines for scaling
def verticalRangeMin = stockPriceMin * 0.9;
def verticalRangeMax = stockPriceMax * 1.1;
def verticalRange = verticalRangeMax - verticalRangeMin;
# Scale stockPriceSmoothed, netCalls, and netPuts
def scaledStockPrice = if stockPriceMax != stockPriceMin then midPoint + (stockPriceSmoothed - stockPriceMin) * verticalRange * separationFactor / (stockPriceMax - stockPriceMin) else stockPriceSmoothed;
def scaledNetCalls = if callsMax != callsMin then midPoint + (smoothedNetCalls - callsMin) * verticalRange * separationFactor / (callsMax - callsMin) else stockPriceSmoothed;
def scaledNetPuts = if putsMax != putsMin then midPoint + (smoothedNetPuts - putsMin) * verticalRange * separationFactor / (putsMax - putsMin) else stockPriceSmoothed;
# Plot lines (only during regular hours)
plot plotStockPrice = if isRegularHours then scaledStockPrice else Double.NaN;
plot plotNetCalls = if isRegularHours then scaledNetCalls else Double.NaN;
plot plotNetPuts = if isRegularHours then scaledNetPuts else Double.NaN;
# Styling for plots
plotStockPrice.SetDefaultColor(Color.YELLOW);
plotStockPrice.SetLineWeight(2);
plotNetCalls.SetDefaultColor(Color.uptick);
plotNetCalls.SetLineWeight(2);
plotNetPuts.SetDefaultColor(Color.downtick);
plotNetPuts.SetLineWeight(2);
# Zero line (midpoint reference)
def zeroLine = (stockPriceMin + stockPriceMax) / 2;
plot plotZeroLine = if isRegularHours then zeroLine else Double.NaN;
plotZeroLine.SetDefaultColor(Color.GRAY);
plotZeroLine.SetLineWeight(1);
# Detect crossovers
def callsCrossAbovePuts = smoothedNetCalls crosses above smoothedNetPuts;
def callsCrossBelowPuts = smoothedNetCalls crosses below smoothedNetPuts;
# Track sentiment state (1 = bullish, -1 = bearish, 0 = neutral)
def sentimentState;
if callsCrossAbovePuts {
sentimentState = 1;
} else if callsCrossBelowPuts {
sentimentState = -1;
} else if IsNaN(sentimentState[1]) {
sentimentState = 0;
} else {
sentimentState = sentimentState[1];
}
# Calculate percentage distance from stock price
def callsPercentDiff = if plotStockPrice != 0 then ((scaledNetCalls - plotStockPrice) / stockPriceSmoothed) * 100 else 0;
def putsPercentDiff = if plotStockPrice != 0 then ((scaledNetPuts - plotStockPrice) / stockPriceSmoothed) * 100 else 0;
# Calculate percentage distance from stock price to zero line
def pricePercentDiff = if zeroLine != 0 then ((plotStockPrice - zeroLine) / zeroLine) * 100 else 0;
# Determine Net Flow sentiment (Bullish or Bearish)
def isBullish = scaledNetCalls > scaledNetPuts;
def isBearish = scaledNetPuts > scaledNetCalls;
# Check if calls or puts line is touching the zero line (within a small threshold)
def threshold = 0.01;
def callsAtZero = AbsValue(scaledNetCalls - zeroLine) <= threshold;
def putsAtZero = AbsValue(scaledNetPuts - zeroLine) <= threshold;
# Status indicators (using AddLabel instead of table)
AddLabel(yes, "Dynamic Price Flow: ", if isBullish then Color.uptick else if isBearish then Color.downtick else Color.WHITE);
AddLabel(yes, if isBullish then "Bullish" else if isBearish then "Bearish" else "Neutral", if isBullish then Color.uptick else if isBearish then Color.downtick else Color.WHITE);
AddLabel(yes, "Zero Line Status: ", if callsAtZero then Color.uptick else if putsAtZero then Color.downtick else Color.dark_gray);
AddLabel(yes, if callsAtZero then "Calls @ Zero" else if putsAtZero then "Puts @ Zero" else "Clear", if callsAtZero then Color.uptick else if putsAtZero then Color.downtick else Color.dark_gray);
# Labels for end of lines
def stockPriceLabel = if !IsNaN(plotStockPrice) then plotStockPrice else stockPriceLabel[1];
def netCallsLabel = if !IsNaN(plotNetCalls) then plotNetCalls else netCallsLabel[1];
def netPutsLabel = if !IsNaN(plotNetPuts) then plotNetPuts else netPutsLabel[1];
# Chart Bubbles with percentage distance
AddChartBubble(IsNaN(close[-1]) and !IsNaN(close), scaledNetCalls, "Calls/" + (if callsPercentDiff >= 0 then "+" else "") + AsText(callsPercentDiff, NumberFormat.TWO_DECIMAL_PLACES) + "%", Color.UPTICK);
AddChartBubble(IsNaN(close[-1]) and !IsNaN(close), scaledNetPuts, "Puts/" + (if putsPercentDiff >= 0 then "+" else "") + AsText(putsPercentDiff, NumberFormat.TWO_DECIMAL_PLACES) + "%", Color.DOWNTICK);
AddChartBubble(IsNaN(close[-1]) and !IsNaN(close),plotStockPrice, "Price/" + (if pricePercentDiff >= 0 then "+" else "") + AsText(pricePercentDiff, NumberFormat.TWO_DECIMAL_PLACES) + "%", Color.YELLOW);
Declare Hide_On_Daily;
input ShowTodayOnly = yes;
input Time1 = 0435;
input Time2 = 950;
input Time3 = 1020;
input Time4 = 1615;
input Time5 = 0930; # Added Market Open
input Time6 = 1945; # Added End
input Time7 = 1350;
input Time8 = 1425;
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time1) == 0
then SecondsFromTime(Time1) == 0 and SecondsTillTime(Time1) == 0
else if SecondsFromTime(Time1) != 0
then (SecondsFromTime(Time1)[1] < 0 and SecondsFromTime(Time1) > 0) or
(SecondsfromTime(Time1) > 0 and SecondsfromTime(Time1)[1] > secondsfromTime(Time1))
else Double.NaN,
"Start", Color.dark_green, Curve.short_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time2) == 0
then SecondsFromTime(Time2) == 0 and SecondsTillTime(Time2) == 0
else if SecondsFromTime(Time2) != 0
then (SecondsFromTime(Time2)[1] < 0 and SecondsFromTime(Time2) > 0) or
(SecondsfromTime(Time2) > 0 and SecondsfromTime(Time2)[1] > secondsfromTime(Time2))
else Double.NaN,
"Pivot Window", Color.dark_red, Curve.shorT_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time3) == 0
then SecondsFromTime(Time3) == 0 and SecondsTillTime(Time3) == 0
else if SecondsFromTime(Time3) != 0
then (SecondsFromTime(Time3)[1] < 0 and SecondsFromTime(Time3) > 0) or
(SecondsfromTime(Time3) > 0 and SecondsfromTime(Time3)[1] > secondsfromTime(Time3))
else Double.NaN,
"Pivot Window", Color.dark_red, Curve.shorT_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time4) == 0
then SecondsFromTime(Time4) == 0 and SecondsTillTime(Time4) == 0
else if SecondsFromTime(Time4) != 0
then (SecondsFromTime(Time4)[1] < 0 and SecondsFromTime(Time4) > 0) or
(SecondsfromTime(Time4) > 0 and SecondsfromTime(Time4)[1] > secondsfromTime(Time4))
else Double.NaN,
"Market Close", Color.dark_red, Curve.shorT_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time5) == 0
then SecondsFromTime(Time5) == 0 and SecondsTillTime(Time5) == 0
else if SecondsFromTime(Time5) != 0
then (SecondsFromTime(Time5)[1] < 0 and SecondsFromTime(Time5) > 0) or
(SecondsfromTime(Time5) > 0 and SecondsfromTime(Time5)[1] > secondsfromTime(Time5))
else Double.NaN,
"Market Open", Color.dark_green, Curve.short_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time6) == 0
then SecondsFromTime(Time6) == 0 and SecondsTillTime(Time6) == 0
else if SecondsFromTime(Time6) != 0
then (SecondsFromTime(Time6)[1] < 0 and SecondsFromTime(Time6) > 0) or
(SecondsfromTime(Time6) > 0 and SecondsfromTime(Time6)[1] > secondsfromTime(Time6))
else Double.NaN,
"End", Color.dark_red, Curve.shorT_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time7) == 0
then SecondsFromTime(Time7) == 0 and SecondsTillTime(Time7) == 0
else if SecondsFromTime(Time7) != 0
then (SecondsFromTime(Time7)[1] < 0 and SecondsFromTime(Time7) > 0) or
(SecondsfromTime(Time7) > 0 and SecondsfromTime(Time7)[1] > secondsfromTime(Time7))
else Double.NaN,
"Pivot Window", Color.dark_red, Curve.shorT_DASH);
AddVerticalLine(
if ShowTodayOnly and GetDay() != GetLastDay()
then Double.NaN
else if SecondsFromTime(Time8) == 0
then SecondsFromTime(Time8) == 0 and SecondsTillTime(Time8) == 0
else if SecondsFromTime(Time8) != 0
then (SecondsFromTime(Time8)[1] < 0 and SecondsFromTime(Time8) > 0) or
(SecondsfromTime(Time8) > 0 and SecondsfromTime(Time8)[1] > secondsfromTime(Time8))
else Double.NaN,
"Pivot Window", Color.dark_red, Curve.shorT_DASH);
Last edited by a moderator: