Market Structure & Scatter Dashboard [LuxAlgo]The Market Structure & Scatter Dashboard indicator provides a comprehensive view of price action by combining automated market structure mapping with a dynamic scatter plot analysis. It aims to quantify the relationship between impulse moves and subsequent pullbacks to help traders understand the current volatility and trend strength.
🔶 USAGE
The script identifies key structural points and visualizes the relationship between the magnitude of price expansions and their retracements through a dashboard and candle heatmap.
🔹 Market Structure (SMC)
The indicator automatically detects swing highs and lows to plot significant market structure levels. It identifies:
BOS (Break of Structure): Occurs when price continues in the direction of the prevailing trend by breaking a previous swing level.
CHoCH (Change of Character): Occurs when price breaks a swing level in the opposite direction of the current trend, signaling a potential reversal.
🔹 Scatter Dashboard
The dashboard, located to the right of the current price action, plots historical price swings as a scatter chart. It breaks down the market into two measurements:
X-Axis (Impulse): How far the market moved aggressively in the direction of the trend.
Y-Axis (Pullback): How deep the market retraced after that initial impulse.
Quadrant Interpretation: The top-right quadrant represents bullish sequences (upward move followed by a downward pullback), while the bottom-left represents bearish sequences (downward move followed by an upward pullback).
🔹 Candle Heatmap
Users can color the chart candles based on the live data from the scatter plot. This allows for a direct visual correlation between the price action and the statistical intensity of current swings.
🔶 DETAILS
The scatter plot calculates the percentage change of every historical swing. By mapping these onto a quadrant system, traders can see if recent pullbacks are deep relative to their impulses.
The tool uses a simplified two-tone color scheme (Bullish vs. Bearish). These colors define the extremes of the gradient used for both the dashboard dots and the candle heatmap. Points closer to the Bullish color represent strong upward volatility, while points closer to the Bearish color represent heavy downward volatility.
🔶 SETTINGS
🔹 Core Settings
Pivot Length: Determines the sensitivity for identifying swing highs and lows.
Color Candles via Scatter Heatmap: Toggles the candle coloring on or off.
Heatmap Mode: Selects the logic for the candle gradient. "Pullback" (default) focuses on retracement depth, "Impulse" focuses on the strength of the trend extension, and "Combined" uses a score derived from both.
🔹 Style
Bullish Color: Sets the color for bullish structure and the positive extreme of the heatmap gradient.
Bearish Color: Sets the color for bearish structure and the negative extreme of the heatmap gradient.
🔹 Dashboard
Dashboard Vertical Position: Anchors the dashboard to the Top, Middle, or Bottom of the recent price action.
Dashboard Time Offset: Controls how many bars into the future the dashboard is projected.
Dashboard Size Scale: Adjusts the visual size of the dashboard and its grid elements.
Indicator

Volume Scatter Plot [UAlgo]Volume Scatter Plot is a visual analytics tool that transforms recent candles into a two dimensional distribution of price and volume. Instead of plotting volume in the traditional way at the bottom of the chart, the script projects each recent bar as a point inside a custom scatter plot area drawn directly on the chart. This allows the user to study the relationship between traded volume and price location in a much more spatial and intuitive format.
Each point represents one candle from the selected lookback period. The vertical location of the point is taken from price, while the horizontal location is determined by that candle’s volume relative to all other bars inside the lookback window. As a result, the plot makes it possible to quickly see whether higher volume tends to cluster near higher prices, lower prices, or specific sections of the recent range.
The script also colors every point according to candle direction, which adds a simple but useful order flow style layer. Bullish candles are shown with one color and bearish candles with another, so the scatter plot can reveal not only the price and volume relationship, but also whether those clusters were formed more often by bullish or bearish candles.
To add structure, the indicator draws a framed plotting area with guide lines, then overlays a linear regression line across the cloud of points. This regression line gives the user a fast view of the overall relationship between volume and price. If enabled, deviation bands are also plotted above and below the regression line, which can help identify points that stand out from the average relationship.
In practical use, this script is useful for studying whether strong participation is appearing at premium or discount prices, whether extreme volume is clustering around certain regions, and whether recent bars are tightly aligned with the broader price volume relationship or scattered away from it.
🔹 Features
🔸 Price and Volume Scatter Mapping
The script converts each candle in the lookback period into a scatter point. Price controls vertical placement and volume controls horizontal placement. This creates a true two dimensional view of recent market behavior rather than a separate price chart and volume pane.
🔸 Bullish and Bearish Point Coloring
Each point is colored according to candle direction. Bullish candles use the bullish point color, while bearish candles use the bearish point color. This makes it easier to visually separate positive and negative participation inside the same distribution.
🔸 Custom Plot Area Overlay
The scatter plot is drawn in a dedicated chart area offset to the right of current price. The width of this area and the horizontal offset are both configurable, giving the user control over how large and how far away the visualization appears.
🔸 Flexible Scatter Symbols
The plotted points can use different characters such as circles, stars, squares, crosses, or other symbols. This helps users adapt the style of the plot to their preferred chart appearance.
🔸 Automatic Bounds Calculation
The indicator automatically calculates the highest price, lowest price, highest volume, and lowest volume across the current point set. These values are then used to scale the scatter plot so the entire distribution fits inside the frame cleanly.
🔸 Framed Axes and Mid Guides
The script draws the outer borders of the plot area as well as horizontal and vertical midpoint guides. This creates a clearer analytical space and makes it easier to judge where points sit relative to the full distribution.
🔸 Tooltip Enabled Data Points
Every scatter point includes a tooltip that shows the underlying price and volume values. This allows the user to inspect specific points directly on the chart without losing the visual overview.
🔸 Linear Regression Overlay
A regression line is calculated from the relationship between volume and price across the current dataset. This gives the user an immediate view of whether the cloud of points implies a positive, negative, or flat volume price relationship.
🔸 Optional Deviation Bands
When enabled, the script also draws lines one standard deviation above and below the regression line. These bands help visualize how tightly or loosely the scatter cloud is distributed around the fitted relationship.
🔸 Live Refresh on the Latest Bar
The plot refreshes on the latest bar and in realtime conditions, ensuring that the scatter map always reflects the most recent market state.
🔹 Calculations
1) Defining the Scatter Point and Plot Structures
type ScatterPoint
float price
float volume
color pt_color
int bar_time
type ScatterPlot
array points
int lookback
int width
int x_offset
float min_price
float max_price
float min_vol
float max_vol
array drawn_labels
array drawn_lines
This is the data model behind the whole indicator.
Each ScatterPoint stores one candle’s contribution to the plot. It contains:
the target price,
the candle volume,
the point color,
and the candle time.
The ScatterPlot structure stores the full plotting state:
the rolling point array,
the configuration values,
the current plot bounds,
and the labels and lines used for drawing.
So before any calculations begin, the script already has a full container for both the raw data and the visual objects used to display it.
2) Adding New Points Into the Rolling Dataset
method add_point(ScatterPlot this, float p, float v, color c, int t) =>
this.points.unshift(ScatterPoint.new(p, v, c, t))
if this.points.size() > this.lookback
this.points.pop()
This method manages the rolling dataset.
Every new bar creates a new ScatterPoint and inserts it at the front of the array with unshift() . That means the newest point is always stored first. If the array grows larger than the selected lookback size, the oldest point is removed from the end with pop() .
This gives the script a continuously updating point cloud that always contains only the most recent bars.
In practical terms, the scatter plot is always a moving window of recent market behavior rather than an ever growing history.
3) Choosing the Price and Color for Each Point
color bar_color = close >= open ? c_bull : c_bear
float target_price = hl2
data_plot.add_point(target_price, volume, bar_color, time)
This block explains how each bar is converted into a scatter point.
First, the script determines the point color from candle direction. If the close is above or equal to the open, the point uses the bullish color. Otherwise it uses the bearish color.
Second, the script chooses hl2 as the target price. That means the vertical position of each point is the midpoint of the bar’s high and low, not the close or the open. This is a useful choice because it represents the candle’s central traded location rather than only its final close.
Finally, the script sends that price, the candle volume, the directional color, and the time into the rolling plot dataset.
So each plotted point reflects:
where the candle sat in price,
how much volume it traded,
and whether it closed bullish or bearish.
4) Calculating the Plot Bounds
method calculate_bounds(ScatterPlot this) =>
float max_p = na
float min_p = na
float max_v = na
float min_v = na
if this.points.size() > 0
max_p := this.points.get(0).price
min_p := this.points.get(0).price
max_v := this.points.get(0).volume
min_v := this.points.get(0).volume
for p in this.points
if p.price > max_p
max_p := p.price
if p.price < min_p
min_p := p.price
if p.volume > max_v
max_v := p.volume
if p.volume < min_v
min_v := p.volume
This method scans all stored points and finds the extreme values needed for scaling.
It identifies:
the maximum price,
the minimum price,
the maximum volume,
and the minimum volume.
These values form the raw boundaries of the point cloud. Without them, the script would not know how to map prices and volumes into the framed plotting area.
So this is the normalization step that prepares the scatter plot for accurate positioning.
5) Adding a Small Price Margin Around the Point Cloud
float p_range = math.max(max_p - min_p, 0.0001)
this.max_price := max_p + (p_range * 0.05)
this.min_price := min_p - (p_range * 0.05)
this.max_vol := max_v
this.min_vol := min_v
After the raw bounds are found, the script adds a small vertical margin to the price range.
It computes the price span and then extends the upper and lower bounds by five percent of that range. This prevents the highest and lowest points from sitting directly on the frame border.
Volume bounds are stored without an added margin because they are used mainly for horizontal scaling.
In practical terms, this makes the plot easier to read and visually less cramped.
6) Mapping Volume Into Horizontal Position
method get_x_pos(ScatterPlot this, float vol, int current_bar) =>
float max_range = math.max((this.max_vol - this.min_vol), 0.0001)
float ratio = (vol - this.min_vol) / max_range
float active_width = this.width * 0.95
int pos = current_bar + this.x_offset + int(ratio * active_width)
pos
This function is what turns volume into horizontal placement.
First, it measures the full volume range across the current dataset. Then it converts the current point’s volume into a ratio between zero and one:
ratio = (vol - this.min_vol) / max_range
That ratio tells the script where the volume sits between the smallest and largest volume values in the lookback.
The ratio is then multiplied by the active plot width and shifted to the right of current price using x_offset .
So low volume points appear closer to the left side of the scatter area, and high volume points appear closer to the right side.
This is the key transformation that makes the chart behave like a true scatter plot rather than a simple time series.
7) Drawing the Plot Frame and Guides
method draw_axes(ScatterPlot this, int current_bar) =>
int x_start = current_bar + this.x_offset
int x_end = x_start + this.width
this.push_line(line.new(x_start, this.min_price, x_start, this.max_price, color = c_axis, style = line.style_dotted, width = 1))
this.push_line(line.new(x_end, this.min_price, x_end, this.max_price, color = c_axis, style = line.style_dotted, width = 1))
this.push_line(line.new(x_start, this.min_price, x_end, this.min_price, color = c_axis, style = line.style_dotted, width = 1))
this.push_line(line.new(x_start, this.max_price, x_end, this.max_price, color = c_axis, style = line.style_dotted, width = 1))
int mid_x = x_start + math.round(this.width / 2)
float mid_y = (this.max_price + this.min_price) / 2
this.push_line(line.new(mid_x, this.min_price, mid_x, this.max_price, color = color.new(c_axis, 70), style = line.style_dashed, width = 1))
this.push_line(line.new(x_start, mid_y, x_end, mid_y, color = color.new(c_axis, 70), style = line.style_dashed, width = 1))
This method draws the visual frame of the scatter plot.
It defines the left and right horizontal edges of the plotting area, then draws four dotted boundary lines:
left border,
right border,
bottom border,
and top border.
After that, it draws a vertical midpoint guide and a horizontal midpoint guide.
These guides help the user interpret where the point cloud sits relative to the full price and volume range. For example, it becomes much easier to see whether most points cluster in the upper half of price or the right half of volume.
8) Drawing Axis Labels
this.push_label(label.new(x_start, this.max_price, "Price Max", textcolor = c_axis, color = transparent, style = label.style_label_down, size = size.small))
this.push_label(label.new(x_start, this.min_price, "Price Min", textcolor = c_axis, color = transparent, style = label.style_label_up, size = size.small))
this.push_label(label.new(x_end, this.min_price, "Vol Max", textcolor = c_axis, color = transparent, style = label.style_label_left, size = size.small))
These labels give the plot basic orientation.
The script marks:
the highest price boundary,
the lowest price boundary,
and the far right side of the plot as the maximum volume direction.
This is a simple but useful usability feature because it immediately tells the user how to read the scatter space:
vertical movement corresponds to price,
and movement toward the right corresponds to increasing volume.
9) Drawing the Scatter Points Themselves
method draw_points(ScatterPlot this, int current_bar, string char_symbol) =>
color transparent = color.new(color.white, 100)
for p in this.points
int x_pos = this.get_x_pos(p.volume, current_bar)
string tooltip_txt = "P: " + str.tostring(p.price, format.mintick) + " V: " + str.tostring(p.volume, format.volume)
this.push_label(label.new(x_pos, p.price, text = char_symbol, textcolor = p.pt_color, color = transparent, style = label.style_none, size = size.small, tooltip = tooltip_txt))
This method plots every stored point inside the scatter area.
For each point, the script first converts volume into an x position using get_x_pos() . The y position is simply the stored point price. Then it draws a label using the selected point symbol and the stored bullish or bearish color.
Each point also gets a tooltip showing:
the exact price,
and the exact volume.
So visually, the user sees a clean scatter cloud, but each point still preserves its detailed numeric information.
10) Computing the Regression Line
method draw_regression(ScatterPlot this, int current_bar, bool show_dev) =>
int n = this.points.size()
if n > 1
float sum_x = 0.0
float sum_y = 0.0
float sum_xy = 0.0
float sum_xx = 0.0
for p in this.points
sum_x += p.volume
sum_y += p.price
sum_xy += p.volume * p.price
sum_xx += p.volume * p.volume
float denom = (n * sum_xx - sum_x * sum_x)
float slope = denom == 0 ? 0 : (n * sum_xy - sum_x * sum_y) / denom
float intercept = (sum_y - slope * sum_x) / n
This is the statistical core of the indicator.
The script performs a standard linear regression where:
x is volume,
and y is price.
It first accumulates the sums needed for the regression formula:
sum of x,
sum of y,
sum of xy,
and sum of xx.
From those totals, it calculates:
the slope,
and the intercept.
So the regression line answers a simple analytical question:
as volume changes across the recent dataset, what is the average linear relationship with price?
A positive slope suggests higher volume tends to align with higher prices.
A negative slope suggests higher volume tends to align with lower prices.
A flat slope suggests little directional relationship between the two.
11) Measuring Dispersion Around the Regression
float variance = 0.0
for p in this.points
float expected_y = slope * p.volume + intercept
variance += math.pow(p.price - expected_y, 2)
float std_dev = math.sqrt(variance / n)
After the regression line is found, the script measures how far the actual points deviate from that fitted relationship.
For each point, it calculates the expected price on the regression line for that point’s volume. It then measures the squared difference between the actual price and the expected price. The average of those squared differences becomes the variance, and the square root of that value becomes the standard deviation.
This tells the user how tightly or loosely the point cloud clusters around the regression line. A small deviation means the relationship is relatively consistent. A large deviation means the cloud is more dispersed.
12) Converting the Regression Into Drawable Chart Coordinates
float y_min_vol = slope * this.min_vol + intercept
float y_max_vol = slope * this.max_vol + intercept
int x_start_clamped = this.get_x_pos(this.min_vol, current_bar)
int x_end_clamped = this.get_x_pos(this.max_vol, current_bar)
this.push_line(line.new(x_start_clamped, y_min_vol, x_end_clamped, y_max_vol, color = c_reg, width = 2, style = line.style_solid))
This block translates the regression model into something the chart can display.
The script evaluates the regression line at the minimum and maximum volume values of the dataset. Those two calculated prices define the start and end of the regression segment in price space.
Then it converts the minimum and maximum volumes into actual chart x positions using get_x_pos() .
Finally, it draws a straight line between those two points.
So even though the regression is calculated in price and volume coordinates, it becomes a visible line inside the custom scatter plot area.
13) Drawing the Deviation Bands
if show_dev
color dev_color = color.new(c_reg, 60)
this.push_line(line.new(x_start_clamped, y_min_vol + std_dev, x_end_clamped, y_max_vol + std_dev, color = dev_color, width = 1, style = line.style_dashed))
this.push_line(line.new(x_start_clamped, y_min_vol - std_dev, x_end_clamped, y_max_vol - std_dev, color = dev_color, width = 1, style = line.style_dashed))
If deviation display is enabled, the script draws two additional dashed lines:
one standard deviation above the regression,
and one standard deviation below it.
These bands help the user judge whether points are staying close to the average relationship or whether some bars are standing far away from the expected line.
In practical terms, points well outside these bands can be interpreted as unusually strong or unusually weak price locations relative to their traded volume.
14) Clearing and Redrawing the Plot
method clear_drawings(ScatterPlot this) =>
if this.drawn_labels.size() > 0
for l in this.drawn_labels
l.delete()
this.drawn_labels.clear()
if this.drawn_lines.size() > 0
for b in this.drawn_lines
b.delete()
this.drawn_lines.clear()
Before each refresh, the script deletes all previously drawn labels and lines. This ensures that the scatter plot does not accumulate stale points or outdated regression segments.
Because the visualization is rebuilt from the current rolling dataset, clearing old drawings first is necessary for a clean and accurate live display.
15) Final Execution Flow
if barstate.islast or barstate.isrealtime
data_plot.clear_drawings()
data_plot.calculate_bounds()
data_plot.draw_axes(bar_index)
data_plot.draw_points(bar_index, i_pt_char)
data_plot.draw_regression(bar_index, i_show_dev)
This block summarizes the entire display engine.
On the latest bar or in realtime:
the script clears old drawings,
recalculates the current bounds,
draws the plot frame,
plots all scatter points,
and overlays the regression line with optional deviation bands.
So the chart always shows a fresh snapshot of the current price volume relationship based on the selected lookback window. Indicator

Indicator

Ehlers Loops [BigBeluga]The Ehlers Loops indicator is based on the concepts developed by John F. Ehlers, which provide a visual representation of the relationship between price and volume dynamics. This tool helps traders predict future market movements by observing how price and volume data interact within four distinct quadrants of the loop, each representing different combinations of price and volume directions. The unique structure of this indicator provides insights into the strength and direction of market trends, offering a clearer perspective on price behavior relative to volume.
🔵 KEY FEATURES & USAGE
● Four Price-Volume Quadrants:
The Ehlers Loops chart consists of four quadrants:
+Price & +Volume (top-right) – Typically indicates a bullish continuation in the market.
-Price & +Volume (bottom-right) – Generally shows a bearish continuation.
+Price & -Volume (top-left) – Typically indicates an exhaustion of demand with a potential reversal.
-Price & -Volume (bottom-left) – Indicates exhaustion of supply and near trend reversal.
By watching how symbols move through these quadrants over time, traders can assess shifts in momentum and volume flow.
● Price and Volume Scaling in Standard Deviations:
Both price and volume data are individually filtered using HighPass and SuperSmoother filters, which transform them into band-limited signals with zero mean. This scaling allows traders to view data in terms of its deviation from the average, making it easier to spot abnormal movements or trends in both price and volume.
● Loops Trajectories with Tails:
The loops draw a trail of price and volume dynamics over time, allowing traders to observe historical price-volume interactions and predict future movements based on the curvature and direction of the rotation.
● Price & Volume Histograms:
On the right side of the chart, histograms for each symbol provide a summary of the most recent price and volume values. These histograms allow traders to easily compare the strength and direction of multiple assets and evaluate market conditions at a glance.
● Flexible Symbol Display & Customization:
Traders can select up to five different symbols to be displayed within the Ehlers Loops. The settings also allow customization of symbol size, colors, and visibility of the histograms. Additionally, traders can adjust the LPPeriod and HPPeriod to change the smoothness and lag of the loops, with a shorter LPPeriod offering more responsiveness and a longer HPPeriod emphasizing longer-term trends.
🔵 USAGE
🔵 SETTINGS
Low pass Period: default is 10 to
obtain minimum lag with just a little smoothing.
High pass Period: default is 125 (half of the year if Daily timeframe) to capture the longer term moves.
🔵 CONCLUSION
The Ehlers Loops indicator offers a visually rich and highly customizable way to observe price and volume dynamics across multiple assets. By using band-limited signals and scaling data into standard deviations, traders gain a powerful tool for identifying market trends and predicting future movements. Whether you're tracking short-term fluctuations or long-term trends, Ehlers Loops can help you stay ahead of the market by offering key insights into the relationship between price and volume. Indicator

Relative Strength Scatter Plot [LuxAlgo]The Relative Strength Scatter Plot indicator is a tool that shows the historical performance of various user-selected securities against a selected benchmark.
This tool is inspired by Relative Rotation Graphs®. Relative Rotation Graphs® is a registered trademark of JOOS Holdings B.V. This script is neither endorsed, nor sponsored, nor affiliated with them.
🔶 USAGE
This tool depicts a simple scatter plot using the relative strength ratio as the X-axis and its momentum as the Y-axis of the user-selected symbols against the selected benchmark.
The graph is divided into four quadrants, and the interpretation of the graph is done depending on where a point is situated on the graph:
A point in the green quadrant would indicate that the security is leading the benchmark in strength, with positive strength momentum.
A point in the yellow quadrant would indicate that the security is leading the benchmark in strength, with negative strength momentum.
A point in the blue quadrant would indicate that the security is lagging behind the benchmark in strength, with positive strength momentum.
A point in the red quadrant would indicate that the security is lagging behind the benchmark in strength, with negative strength momentum.
The trail of each symbol allows the user to see the evolution of the relative strength momentum relative to the relative strength ratio. The length of the trail can be controlled by the "Trail Length" setting.
🔶 DETAILS
Our relative strength ratio estimate is first obtained from the relative strength between the symbol of interest and the benchmark, the result is then smoothed using a linearly weighted moving average (wma). This result is then normalized with a wma of the smoothed relative strength, this ratio is again smoothed with the wma and multiplied by 100.
The relative strength momentum estimate is obtained from the ratio between the previously estimated RS-Ratio and its wma, this ratio is then multiplied by 100.
🔶 SETTINGS
Calculation Window: Calculation window of the RS-Ratio and RS-Momentum metrics.
Symbols: Symbols used for the computation of the graph, each settings line allows us to determine whether the symbol is to be displayed on the graph as well as its color.
Benchmark: Benchmark symbol used for the computation of the graph. Indices are commonly used as a benchmark.
🔹 Graph Settings
Trail Length: Number of past data points to display on the graph for each symbol.
Resolution: Controls the horizontal length of the graph.
Indicator

Volume and Price Z-Score [Multi-Asset] - By LeviathanThis script offers in-depth Z-Score analytics on price and volume for 200 symbols. Utilizing visualizations such as scatter plots, histograms, and heatmaps, it enables traders to uncover potential trade opportunities, discern market dynamics, pinpoint outliers, delve into the relationship between price and volume, and much more.
A Z-Score is a statistical measurement indicating the number of standard deviations a data point deviates from the dataset's mean. Essentially, it provides insight into a value's relative position within a group of values (mean).
- A Z-Score of zero means the data point is exactly at the mean.
- A positive Z-Score indicates the data point is above the mean.
- A negative Z-Score indicates the data point is below the mean.
For instance, a Z-Score of 1 indicates that the data point is 1 standard deviation above the mean, while a Z-Score of -1 indicates that the data point is 1 standard deviation below the mean. In simple terms, the more extreme the Z-Score of a data point, the more “unusual” it is within a larger context.
If data is normally distributed, the following properties can be observed:
- About 68% of the data will lie within ±1 standard deviation (z-score between -1 and 1).
- About 95% will lie within ±2 standard deviations (z-score between -2 and 2).
- About 99.7% will lie within ±3 standard deviations (z-score between -3 and 3).
Datasets like price and volume (in this context) are most often not normally distributed. While the interpretation in terms of percentage of data lying within certain ranges of z-scores (like the ones mentioned above) won't hold, the z-score can still be a useful measure of how "unusual" a data point is relative to the mean.
The aim of this indicator is to offer a unique way of screening the market for trading opportunities by conveniently visualizing where current volume and price activity stands in relation to the average. It also offers features to observe the convergent/divergent relationships between asset’s price movement and volume, observe a single symbol’s activity compared to the wider market activity and much more.
Here is an overview of a few important settings.
Z-SCORE TYPE
◽️ Z-Score Type: Current Z-Score
Calculates the z-score by comparing current bar’s price and volume data to the mean (moving average with any custom length, default is 20 bars). This indicates how much the current bar’s price and volume data deviates from the average over the specified period. A positive z-score suggests that the current bar's price or volume is above the mean of the last 20 bars (or the custom length set by the user), while a negative z-score means it's below that mean.
Example: Consider an asset whose current price and volume both show deviations from their 20-bar averages. If the price's Z-Score is +1.5 and the volume's Z-Score is +2.0, it means the asset's price is 1.5 standard deviations above its average, and its trading volume is 2 standard deviations above its average. This might suggest a significant upward move with strong trading activity.
◽️ Z-Score Type: Average Z-Score
Calculates the custom-length average of symbol's z-score. Think of it as a smoothed version of the Current Z-Score. Instead of just looking at the z-score calculated on the latest bar, it considers the average behavior over the last few bars. By doing this, it helps reduce sudden jumps and gives a clearer, steadier view of the market.
Example: Instead of a single bar, imagine the average price and volume of an asset over the last 5 bars. If the price's 5-bar average Z-Score is +1.0 and the volume's is +1.5, it tells us that, over these recent bars, both the price and volume have been consistently above their longer-term averages, indicating sustained increase.
◽️ Z-Score Type: Relative Z-Score
Calculates a relative z-score by comparing symbol’s current bar z-score to the mean (average z-score of all symbols in the group). This is essentially a z-score of a z-score, and it helps in understanding how a particular symbol's activity stands out not just in its own historical context, but also in relation to the broader set of symbols being analyzed. In other words, while the primary z-score tells you how unusual a bar's activity is for that specific symbol, the relative z-score informs you how that "unusualness" ranks when compared to the entire group's deviations. This can be particularly useful in identifying symbols that are outliers even among outliers, indicating exceptionally unique behaviors or opportunities.
Example: If one asset's price Z-Score is +2.5 and volume Z-Score is +3.0, but the group's average Z-Scores are +0.5 for price and +1.0 for volume, this asset’s Relative Z-Score would be high and therefore stand out. This means that asset's price and volume activities are notably high, not just by its own standards, but also when compared to other symbols in the group.
DISPLAY TYPE
◽️ Display Type: Scatter Plot
The Scatter Plot is a visual tool designed to represent values for two variables, in this case the Z-Scores of price and volume for multiple symbols. Each symbol has it's own dot with x and y coordinates:
X-Axis: Represents the Z-Score of price. A symbol further to the right indicates a higher positive deviation in its price from its average, while a symbol to the left indicates a negative deviation.
Y-Axis: Represents the Z-Score of volume. A symbol positioned higher up on the plot suggests a higher positive deviation in its trading volume from its average, while one lower down indicates a negative deviation.
Here are some guideline insights of plot positioning:
- Top-Right Quadrant (High Volume-High Price): Symbols in this quadrant indicate a scenario where both the trading volume and price are higher than their respective mean.
- Top-Left Quadrant (High Volume-Low Price): Symbols here reflect high trading volumes but prices lower than the mean.
- Bottom-Left Quadrant (Low Volume-Low Price): Assets in this quadrant have both low trading volume and price compared to their mean.
- Bottom-Right Quadrant (Low Volume-High Price): Symbols positioned here have prices that are higher than their mean, but the trading volume is low compared to the mean.
The plot also integrates a set of concentric squares which serve as visual guides:
- 1st Square (1SD): Encapsulates symbols that have Z-Scores within ±1 standard deviation for both price and volume. Symbols within this square are typically considered to be displaying normal behavior or within expected range.
- 2nd Square (2SD): Encapsulates those with Z-Scores within ±2 standard deviations. Symbols within this boundary, but outside the 1 SD square, indicate a moderate deviation from the norm.
- 3rd Square (3SD): Represents symbols with Z-Scores within ±3 standard deviations. Any symbol outside this square is deemed to be a significant outlier, exhibiting extreme behavior in terms of either its price, its volume, or both.
By assessing the position of symbols relative to these squares, traders can swiftly identify which assets are behaving typically and which are showing unusual activity. This visualization simplifies the process of spotting potential outliers or unique trading opportunities within the market. The farther a symbol is from the center, the more it deviates from its typical behavior.
◽️ Display Type: Columns
In this visualization, z-scores are represented using columns, where each symbol is presented horizontally. Each symbol has two distinct nodes:
- Left Node: Represents the z-score of volume.
- Right Node: Represents the z-score of price.
The height of these nodes can vary along the y-axis between -4 and 4, based on the z-score value:
- Large Positive Columns: Signify a high or positive z-score, indicating that the price or volume is significantly above its average.
- Large Negative Columns: Represent a low or negative z-score, suggesting that the price or volume is considerably below its average.
- Short Columns Near 0: Indicate that the price or volume is close to its mean, showcasing minimal deviation.
This columnar representation provides a clear, intuitive view of how each symbol's price and volume deviate from their respective averages.
◽️ Display Type: Circles
In this visualization style, z-scores are depicted using circles. Each symbol is horizontally aligned and represented by:
- Solid Circle: Represents the z-score of price.
- Transparent Circle: Represents the z-score of volume.
The vertical position of these circles on the y-axis ranges between -4 and 4, reflecting the z-score value:
- Circles Near the Top: Indicate a high or positive z-score, suggesting the price or volume is well above its average.
- Circles Near the Bottom: Represent a low or negative z-score, pointing to the price or volume being notably below its average.
- Circles Around the Midline (0): Highlight that the price or volume is close to its mean, with minimal deviation.
◽️ Display Type: Delta Columns
There's also an option to utilize Z-Score Delta Columns. For each symbol, a single column is presented, depicting the difference between the z-score of price and the z-score of volume.
The z-score delta essentially captures the disparity between how much the price and volume deviate from their respective mean:
- Positive Delta: Indicates that the z-score of price is greater than the z-score of volume. This suggests that the price has deviated more from its average than the volume has from its own average. Such a scenario could point to price movements being more significant or pronounced compared to the changes in volume.
- Negative Delta: Represents that the z-score of volume is higher than the z-score of price. This might mean that there are substantial volume changes, yet the price hasn't moved as dramatically. This can be indicative of potential build-up in trading interest without an equivalent impact on price.
- Delta Close to 0: Means that the z-scores for price and volume are almost equal, indicating their deviations from the average are in sync.
◽️ Display Type: Z-Volume/Z-Price Heatmap
This visualization offers a heatmap either for volume z-scores or price z-scores across all symbols. Here's how it's presented:
Each symbol is allocated its own horizontal row. Within this row, bar-by-bar data is displayed using a color gradient to represent the z-score values. The heatmap employs a user-defined gradient scale, where a chosen "cold" color represents low z-scores and a chosen "hot" color signifies high z-scores. As the z-score increases or decreases, the colors transition smoothly along this gradient, providing an intuitive visual indication of the z-score's magnitude.
- Cold Colors: Indicate values significantly below the mean (negative z-score)
- Mild Colors: Represent values close to the mean, suggesting minimal deviation.
- Hot Colors: Indicate values significantly above the mean (positive z-score)
This heatmap format provides a rapid, visually impactful means to discern how each symbol's price or volume is behaving relative to its average. The color-coded rows allow you to quickly spot outliers.
VOLUME TYPE
The "Volume Type" input allows you to choose the nature of volume data that will be factored into the volume z-score calculation. The interpretation of indicator’s data changes based on this input. You can opt between:
- Volume (Regular Volume): This is the classic measure of trading volume, which represents the volume traded in a given time period - bar.
- OBV (On-Balance Volume): OBV is a momentum indicator that accumulates volume on up bars and subtracts it on down bars, making it a cumulative indicator that sort of measures buying and selling pressure.
Interpretation Implications:
- For Volume Type: Regular Volume:
Positive Z-Score: Indicates that the trading volume is above its average, meaning there's unusually high trading activity .
Negative Z-Score: Suggests that the trading volume is below its average, signifying unusually low trading activity.
- For Volume Type: OBV:
Positive Z-Score: Signifies that “buying pressure” is above its average.
Negative Z-Score: Signifies that “selling pressure” is above its average.
When comparing Z-Score of OBV to Z-Score of price, we can observe several scenarios. If Z-Price and Z-Volume are convergent (have similar z-scores), we can say that the directional price movement is supported by volume. If Z-Price and Z-Volume are divergent (have very different z-scores or one of them being zero), it suggests a potential misalignment between price movement and volume support, which might hint at possible reversals or weakness. Indicator

DataChartLibrary "DataChart"
Library to plot scatterplot or heatmaps for your own set of data samples
draw(this)
draw contents of the chart object
Parameters:
this : Chart object
Returns: current chart object
init(this)
Initialize Chart object.
Parameters:
this : Chart object to be initialized
Returns: current chart object
addSample(this, sample, trigger)
Add sample data to chart using Sample object
Parameters:
this : Chart object
sample : Sample object containing sample x and y values to be plotted
trigger : Samples are added to chart only if trigger is set to true. Default value is true
Returns: current chart object
addSample(this, x, y, trigger)
Add sample data to chart using x and y values
Parameters:
this : Chart object
x : x value of sample data
y : y value of sample data
trigger : Samples are added to chart only if trigger is set to true. Default value is true
Returns: current chart object
addPriceSample(this, priceSampleData, config)
Add price sample data - special type of sample designed to measure price displacements of events
Parameters:
this : Chart object
priceSampleData : PriceSampleData object containing event driven displacement data of x and y
config : PriceSampleConfig object containing configurations for deriving x and y from priceSampleData
Returns: current chart object
Sample
Sample data for chart
Fields:
xValue : x value of the sample data
yValue : y value of the sample data
ChartProperties
Properties of plotting chart
Fields:
title : Title of the chart
suffix : Suffix for values. It can be used to reference 10X or 4% etc. Used only if format is not format.percent
matrixSize : size of the matrix used for plotting
chartType : Can be either scatterplot or heatmap. Default is scatterplot
outliersStart : Indicates the percentile of data to filter out from the starting point to get rid of outliers
outliersEnd : Indicates the percentile of data to filter out from the ending point to get rid of outliers.
backgroundColor
plotColor : color of plots on the chart. Default is color.yellow. Only used for scatterplot type
heatmapColor : color of heatmaps on the chart. Default is color.red. Only used for heatmap type
borderColor : border color of the chart table. Default is color.yellow.
plotSize : size of scatter plots. Default is size.large
format : data representation format in tooltips. Use mintick.percent if measuring any data in terms of percent. Else, use format.mintick
showCounters : display counters which shows totals on each quadrants. These are single cell tables at the corners displaying number of occurences on each quadrant.
showTitle : display title at the top center. Uses the title string set in the properties
counterBackground : background color of counter table cells. Default is color.teal
counterTextColor : text color of counter table cells. Default is color.white
counterTextSize : size of counter table cells. Default is size.large
titleBackground : background color of chart title. Default is color.maroon
titleTextColor : text color of the chart title. Default is color.white
titleTextSize : text size of the title cell. Default is size.large
addOutliersToBorder : If set, instead of removing the outliers, it will be added to the border cells.
useCommonScale : Use common scale for both x and y. If not selected, different scales are calculated based on range of x and y values from samples. Default is set to false.
plotchar : scatter plot character. Default is set to ascii bullet.
ChartDrawing
Chart drawing objects collection
Fields:
properties : ChartProperties object which determines the type and characteristics of chart being plotted
titleTable : table containing title of the chart.
mainTable : table containing plots or heatmaps.
quadrantTables : Array of tables containing counters of all 4 quandrants
Chart
Chart type which contains all the information of chart being plotted
Fields:
properties : ChartProperties object which determines the type and characteristics of chart being plotted
samples : Array of Sample objects collected over period of time for plotting on chart.
displacements : Array containing displacement values. Both x and y values
displacementX : Array containing only X displacement values.
displacementY : Array containing only Y displacement values.
drawing : ChartDrawing object which contains all the drawing elements
PriceSampleConfig
Configs used for adding specific type of samples called PriceSamples
Fields:
duration : impact duration for which price displacement samples are calculated.
useAtrReference : Default is true. If set to true, price is measured in terms of Atr. Else is measured in terms of percentage of price.
atrLength : atrLength to be used for measuring the price based on ATR. Used only if useAtrReference is set to true.
PriceSampleData
Special type of sample called price sample. Can be used instead of basic Sample type
Fields:
trigger : consider sample only if trigger is set to true. Default is true.
source : Price source. Default is close
highSource : High price source. Default is high
lowSource : Low price source. Default is low
tr : True range value. Default is ta.tr Library

RSI Impact Heat Map [Trendoscope]Here is a simple tool to measure and display outcome of certain RSI event over heat map.
🎲 Process
🎯Event
Event can be either Crossover or Crossunder of RSI on certain value.
🎯Measuring Impact
Impact of the event after N number of bars is measured in terms of highest and lowest displacement from the last close price. Impact can be collected as either number of times of ATR or percentage of price. Impact for each trigger is recorded separately and stored in array of custom type.
🎯Plotting Heat Map
Heat map is displayed using pine tables. Users can select heat map size - which can vary from 10 to 90. Selecting optimal size is important in order to get right interpretation of data. Having higher number of cells can give more granular data. But, chart may not fit into the window. Having lower size means, stats are combined together to get less granular data which may not give right picture of the results. Default value for size is 50 - meaning data is displayed in 51X51 cells.
Range of the heat map is adjusted automatically based on min and max value of the displacement. In order to filter out or merge extreme values, range is calculated based on certain percentile of the values. This will avoid displaying lots of empty cells which can obscure the actual impact.
🎲 Settings
Settings allow users to define their event, impact duration and reference, and few display related properties. The description of these parameters are as below:
🎲 Use Cases
In this script, we have taken RSI as an example to measure impact. But, we can do this for any event. This can be price crossing over/under upper/lower bollinger bands, moving average crossovers or even complex entry or exit conditions. Overall, we can use this to plot and evaluate our trade criteria.
🎲 Interpretation
Q1 - If more coloured dots appear on the top right corner of the table, then the event is considered to trigger high volatility and high risk environment.
Q2 - If more coloured dots appear on the top left corner, then the events are considered to trigger bearish environment.
Q3 - If more coloured dots appear on the bottom left corner of the chart, then the events are considered insignificant as they neither generate higher displacement in positive or negative side. You can further alter outlier percentage to reduce the bracket and hence have higher distribution move towards
Q4 - If more coloured dots appear on the bottom right corner, then the events are considered to trigger bullish environment.
Will also look forward to implement this as library so that any conditions or events can be plugged into it. Indicator
