Geometry Academy# geometry academy — projection, levels and market timing
geometry academy is an educational indicator dedicated to market geometry, price levels, projections and timing.
it combines several classical methods inside a single interface:
* fibonacci retracements and extensions
* golden pocket
* ab=cd projection
* double top and double bottom
* ichimoku system
* andrews pitchfork
* session vwap
* anchored vwap
* approximate volume profile
* poc, vah and val
* linear regression channel
* cycle interval estimation
* relative strength against a benchmark
* confluence scanner
* educational lessons
* reference curriculum
* built-in glossary
the objective is not to generate automatic entries or promise a result. the indicator is designed to explain where important zones are located, why they exist and how several independent methods can converge around the same area.
a single line represents one piece of information. several independent levels grouped in the same area form a confluence zone worth studying.
---
## general operation
geometry academy uses confirmed pivots to build its geometry.
a pivot high or pivot low becomes available only after the number of bars defined in the “swing · right bars” setting has closed.
this means a swing is never known exactly when it forms. it is confirmed several bars later and then displayed on its original bar.
this behavior prevents an unfinished high or low from being treated as a definitive pivot.
rolling tools such as vwap, volume profile, regression and relative strength naturally continue to update as new bars are added.
---
# indicator modules
## fibonacci retracement
the fibonacci module measures the retracement depth of the latest confirmed leg.
the available levels are:
* 0.0
* 0.236
* 0.382
* 0.5
* 0.618
* 0.786
* 1.0
on a bullish leg, the levels help study pullback zones below the latest high.
on a bearish leg, they help study rebound zones above the latest low.
the levels are not buy or sell signals. they only identify areas where a reaction may become relevant.
## golden pocket
the golden pocket is the zone between the 0.618 and 0.65 retracement levels.
it is displayed as a zone rather than a precise line because market reactions do not always occur at one exact price.
a trade should not be decided only because price touches this area. price reaction, structure and other nearby levels must also be studied.
## fibonacci extensions
the 1.272, 1.618 and 2.0 extensions project targets beyond the reference leg.
they are mainly intended for studying potential objectives after the original movement resumes.
an extension is generally more useful when it aligns with:
* a previous high or low
* a vah or val
* a poc
* a pitchfork median
* an ab=cd projection
* a regression band
## ab=cd projection
the ab=cd model studies symmetry between two price legs.
the distance from a to b is projected from point c to estimate a potential point d.
point d is a mathematical completion zone. it does not guarantee a reversal.
a projection becomes more relevant when:
* bc is a coherent retracement of ab
* cd moves in the same direction as ab
* point d aligns with another important zone
* the duration of cd remains close to the duration of ab
* price shows a confirmed reaction around d
## double top and double bottom
the module looks for structures such as:
* high, low, high for a double top
* low, high, low for a double bottom
the tolerance between the two highs or two lows is calculated with atr.
the second high or low only creates the initial structure.
a double top is confirmed when price closes below the neckline.
a double bottom is confirmed when price closes above the neckline.
before the neckline breaks, the pattern remains a possibility rather than a confirmed setup.
## ichimoku kinko hyo
the ichimoku system is displayed with:
* tenkan-sen
* kijun-sen
* senkou span a
* senkou span b
* kumo
* chikou span
simplified interpretation:
* price above the kumo: bullish regime
* price below the kumo: bearish regime
* price inside the kumo: neutral or uncertain regime
* tenkan above kijun: positive short-term momentum
* tenkan below kijun: negative short-term momentum
the cloud is intentionally projected forward. chikou is intentionally shifted backward. these displacements are part of the standard ichimoku construction.
a tenkan and kijun cross must always be interpreted within context. a bullish cross below a bearish cloud does not carry the same meaning as a bullish cross above a bullish cloud.
## andrews pitchfork
the pitchfork is built from three alternating confirmed pivots.
the median line begins at the first pivot and passes through the midpoint of the next two pivots.
the two outer lines are parallel to the median.
the pitchfork helps study:
* the geometric direction of the swing
* returns toward the median
* acceleration toward an outer line
* structural weakness after a breakout
* areas where the median aligns with another level
the pitchfork depends directly on the quality of the three selected pivots. when a new significant swing is confirmed, the geometry may be recalculated.
## session vwap
vwap represents the session’s volume-weighted average price.
simplified interpretation:
* price above a rising vwap: intraday advantage for buyers
* price below a falling vwap: intraday advantage for sellers
* return toward vwap: return toward the session’s weighted average
* loss and reclaim of vwap: potential intraday control change
vwap is especially useful on markets with meaningful volume data.
## anchored vwap
anchored vwap begins its calculation from the selected date.
it can be used to study the volume-weighted average price since a specific event:
* origin of a movement
* breakout
* important high or low
* monthly open
* asset launch
* fundamental event
* regime change
anchored vwap does not reveal the exact price paid by every market participant. it represents a weighted average from the selected anchor.
the quality of the level therefore depends directly on the relevance of the selected date.
## volume profile
the volume profile distributes the lookback volume across several price zones.
it provides:
* poc
* vah
* val
* an optional horizontal histogram
the poc represents the profile row that received the largest allocated volume.
the vah is the upper boundary of the value area.
the val is the lower boundary of the value area.
simplified interpretation:
* price near poc: potential high-acceptance zone
* price between vah and val: price located inside the value area
* price above vah: price above the studied value zone
* price below val: price below the studied value zone
this profile is an approximation calculated from the ohlcv data available on the chart. it does not replace a native profile built from more detailed intrabar data.
## linear regression channel
the center line represents the best-fit linear trend over the selected period.
the bands are calculated using the dispersion of residuals around that line.
the module helps study:
* the statistical direction of price
* the distance between price and its central trend
* periods of extension
* returns toward the mean
* slope changes
a band touch is not automatically a reversal signal.
in a strong trend, price may remain close to an outer band for several bars.
## cycle projection
the cycle module measures the intervals between several confirmed swing lows.
it uses their average spacing to project a potential future time window.
this projection represents an area of attention rather than a guaranteed reversal date.
cycles may contract, expand or disappear during a regime change.
price level must always be studied separately from timing.
## relative strength
relative strength compares the chart symbol with a benchmark.
it is calculated using the ratio:
asset divided by benchmark
simplified interpretation:
* rising ratio: the asset is outperforming the benchmark
* falling ratio: the asset is underperforming the benchmark
* bullish turn in the ratio: improving relative performance
* bearish turn in the ratio: weakening relative performance
this relative strength measure is not the rsi oscillator.
for an altcoin, btc may be used as the benchmark. for a stock, a sector index or broad market index may be more appropriate.
---
# explanation of every input
## anchors
### swing · left bars
defines the number of bars located to the left of the pivot.
a higher value selects more significant swings and reduces the number of detected pivots.
a lower value detects more minor movements.
### swing · right bars
defines the number of bars required after the pivot before it becomes confirmed.
a higher value produces more stable geometry but increases confirmation delay.
a lower value reacts faster but includes more market noise.
---
## fibonacci
### auto-fibonacci on the active leg
enables or disables the automatic fibonacci drawn on the latest confirmed leg.
### extension targets
enables the 1.272, 1.618 and 2.0 projections.
### highlight the golden pocket
displays the area between 0.618 and 0.65.
### 0.0
displays the reference end of the movement.
### 0.236
displays a shallow retracement, mainly useful in strong trends.
### 0.382
displays a moderate retracement.
### 0.5
displays the midpoint of the movement. this is not a pure fibonacci ratio, but it is widely used.
### 0.618
displays the retracement related to the inverse golden ratio.
### 0.786
displays a deep retracement near the full invalidation of the leg.
---
## ab=cd symmetry
### project the ab=cd completion
enables or disables the point d projection based on the latest compatible pivots.
---
## chart patterns
### detect double top / double bottom
enables the search for double top and double bottom structures.
### twin-peak tolerance
defines the maximum allowed distance between the two highs or two lows.
the tolerance is expressed as an atr multiple.
example:
* 0.3 atr: strict detection
* 0.6 atr: balanced setting
* 1.0 atr: more permissive detection
---
## ichimoku kinko hyo
### ichimoku cloud
enables the ichimoku system.
### tenkan-sen
defines the period of the fast conversion line.
the classical setting is 9.
### kijun-sen
defines the period of the base line.
the classical setting is 26.
### senkou span b
defines the period used for the second cloud boundary.
the classical setting is 52.
### cloud displacement
defines how far the cloud is projected into the future.
the classical setting is 26.
### chikou span
enables the current close displayed backward according to the ichimoku displacement.
---
## andrews pitchfork
### andrews pitchfork from last 3 anchors
enables the pitchfork built from the latest three confirmed alternating pivots.
---
## vwap
### session / rolling vwap
enables the standard session vwap.
### anchored vwap
enables the vwap calculated from a specific date.
### anchor date
defines the starting point of the anchored vwap.
it is better to choose a date linked to an event that had real importance on the chart.
---
## volume profile
### volume profile
enables the profile, poc, vah and val.
### profile lookback
defines the number of bars included in the calculation.
a short lookback follows recent structure.
a long lookback describes a broader market area but reacts more slowly.
### number of price bins
defines the vertical resolution of the profile.
fewer bins:
* simpler profile
* wider levels
* lighter calculation
more bins:
* more detailed profile
* more precise levels
* greater sensitivity to noise
### value area %
defines the percentage of allocated volume included around the poc.
the classical setting is 70%.
### draw the profile histogram
shows or hides the horizontal profile bars while keeping the main levels.
---
## regression channel
### linear regression channel
enables the regression channel.
### regression length
defines the number of bars used to calculate the linear trend.
a small value follows price quickly.
a large value represents a slower and more structural trend.
### channel width
multiplies the dispersion of residuals around the center line.
a low value produces a narrow channel.
a high value produces a wider channel.
---
## market cycles
### project the next cycle low
enables the projection of the next time window based on the average spacing between confirmed swing lows.
---
## relative strength
### benchmark symbol
selects the asset used as the reference.
examples:
* btc to compare an altcoin
* a broad market index to compare a stock
* a sector index to compare a company with its industry
* another currency pair to study relative rotation
### rs lookback
defines the period used to measure the change in the asset-to-benchmark ratio.
a low value reacts quickly.
a high value measures a more persistent relative trend.
---
## education ui
### panel · geometry dashboard
displays the main dashboard.
it summarizes:
* ichimoku regime
* tenkan and kijun relationship
* nearest fibonacci level
* poc
* vah and val
* price position inside the value area
* pitchfork median
* anchored vwap
* regression position
* ab=cd target
* relative strength
### dashboard position
defines the position of the main dashboard.
### panel · level-confluence scanner
enables the scanner that compares current price with the calculated levels.
### confluence position
defines the position of the confluence scanner.
### confluence cluster tolerance
defines the maximum distance between current price and a level for that level to be considered nearby.
the distance is expressed in atr.
example:
* 0.25 atr: very tight confluence
* 0.5 atr: precise confluence
* 0.75 atr: balanced setting
* 1.0 atr or more: wide zone
a tolerance that is too large may classify too many levels as nearby.
### panel · deep lesson
enables the panel containing a detailed educational lesson.
### lesson topic
allows the selection of one of twelve subjects:
1. fibonacci retracement
2. fibonacci extension
3. ab=cd and harmonic patterns
4. chart patterns
5. elliott wave
6. ichimoku
7. andrews pitchfork
8. vwap and anchored vwap
9. volume profile
10. regression channels
11. market cycles
12. relative strength
### panel · source curriculum
displays the main historical and methodological references associated with the modules.
### panel · glossary
displays quick definitions of the terms used in the indicator.
---
## style
### bull / support
defines the color used for bullish information and support areas.
### bear / resistance
defines the color used for bearish information and resistance areas.
### accent / value
defines the color used for value levels, poc, medians and important elements.
### geometry accent
defines the main color of the geometry tools and panel titles.
### secondary text
defines the color of secondary text and neutral information.
### panel background
defines the background color of the panels and selected labels.
---
# mini tutorial
## step 1 — begin with the default settings
keep the following values for a first use:
* swing left: 8
* swing right: 8
* fibonacci enabled
* ichimoku enabled
* pitchfork enabled
* vwap enabled
* volume profile enabled
* regression length: 120
* confluence tolerance: 0.75 atr
these settings provide a balanced view of structure, levels and context.
## step 2 — identify the regime
begin by observing the kumo:
* above the cloud: mainly bullish context
* below the cloud: mainly bearish context
* inside the cloud: uncertain context
then check tenkan and kijun.
a bullish projection should not be interpreted the same way in a bearish regime.
## step 3 — locate price
observe:
* the active fibonacci retracement
* the golden pocket
* vah and val
* poc
* vwap
* anchored vwap
* pitchfork median
* regression bands
the objective is to determine whether price is:
* inside a value zone
* inside an extension zone
* near a potential reaction level
* in the middle of an area with no clear advantage
## step 4 — check confluence
open the confluence scanner.
several tools located near the same price may identify an area worth monitoring.
example:
* 0.618 fibonacci
* val
* anchored vwap
* lower regression band
this combination does not guarantee a bounce, but it describes a technically more important zone than a single isolated level.
## step 5 — wait for the reaction
then observe actual price behavior:
* wick rejection
* close above or below the level
* vwap reclaim
* neckline break
* structure change
* volatility expansion
* improvement or deterioration in relative strength
geometry provides the area. price provides the confirmation.
---
# use cases
## example 1 — pullback in a bullish trend
context:
* price above the kumo
* tenkan above kijun
* latest confirmed movement is bullish
* price is retracing
procedure:
1. identify the 0.382, 0.5, 0.618 and 0.786 levels
2. check whether the golden pocket aligns with val or anchored vwap
3. check the pitchfork median
4. consult the confluence scanner
5. wait for a bullish close or reaction around the zone
an entry in the middle of the movement generally provides less structure than an entry studied around a pullback into confluence.
## example 2 — range market
context:
* price inside the kumo
* nearly flat regression
* price between vah and val
* frequent returns toward poc
procedure:
1. treat poc as the center of rotation
2. observe vah as the upper value boundary
3. observe val as the lower value boundary
4. avoid interpreting every internal move as a new trend
5. wait for a close and acceptance outside the value area before considering a breakout
in this context, fibonacci extensions are often less useful than volume profile and regression.
## example 3 — double top
context:
* first confirmed high
* pullback toward a pivot low
* second high close to the first one
procedure:
1. confirm that both highs respect the atr tolerance
2. identify the neckline at the intermediate pivot low
3. do not treat the pattern as confirmed at the second high
4. wait for a close below the neckline
5. use the height of the structure as a theoretical projection
6. check whether the target aligns with val, an extension or previous support
## example 4 — studying an altcoin against btc
context:
* chart symbol: an altcoin
* benchmark: binance:btcusdt
procedure:
1. study the normal trend of the asset
2. study its relative strength against btc
3. favor assets that are also gaining against the benchmark
4. remain cautious when the asset rises in usd but underperforms btc
5. combine relative strength with structure, volume profile and ichimoku
## example 5 — projection target
context:
* valid ab=cd structure
* point d close to a 1.618 extension
* vah or a previous high in the same area
* upper regression band nearby
procedure:
1. treat the area as a potential objective
2. do not automatically assume a reversal
3. observe price reaction on arrival
4. distinguish a simple pause from a real structure break
5. use confluence to organize the analysis
---
# available alerts
## price entered bullish regime
triggers when price closes above the ichimoku cloud.
## price entered bearish regime
triggers when price closes below the ichimoku cloud.
## tenkan/kijun bullish cross
triggers when tenkan crosses above kijun.
## tenkan/kijun bearish cross
triggers when tenkan crosses below kijun.
## avwap reclaimed
triggers when price reclaims anchored vwap.
## avwap lost
triggers when price loses anchored vwap.
## relative strength turned up
triggers when relative strength begins rising again.
## relative strength turned down
triggers when relative strength begins falling again.
to reduce intrabar alerts, use a bar-close frequency in the tradingview alert settings.
---
# multi-timeframe use
a simple method is to separate context from execution.
swing example:
* daily chart: ichimoku regime, volume profile and relative strength
* 4-hour chart: fibonacci, pitchfork and regression
* 1-hour chart: price reaction and confirmation
intraday example:
* 1-hour chart: general structure
* 15-minute chart: value area, vwap and fibonacci levels
* 5-minute chart: reaction around the zone
pivot settings should be adapted to the timeframe.
on a low timeframe, slightly increasing the pivot values may reduce noise.
on a high timeframe, pivot settings that are too large may produce very few new structures.
---
# data behavior
pivots are confirmed only after several bars.
a pivot may therefore appear on an earlier bar only after its confirmation.
fibonacci levels, pitchfork and ab=cd projection change when a new confirmed pivot updates the active geometry.
volume profile, vwap, regression, cycles and relative strength are rolling calculations. their values change as each new bar is added.
no projection tool should be interpreted as certainty about the future.
---
# good practices
* begin with only a few visible modules
* add tools gradually
* do not use one line as a complete signal
* identify the regime before looking for an entry
* separate projection from confirmation
* adapt pivot settings to the timeframe
* choose a meaningful anchored vwap date
* choose a coherent benchmark
* keep a reasonable confluence tolerance
* study price reaction before making a decision
* use the lessons and glossary to understand each tool
geometry academy is designed as an educational and analytical environment. it helps connect structure, value, geometry, timing and relative strength inside an organized market-reading process.
Indicator

ChatgptLibraryLibrary "ChatgptLibrary"
TODO: add library description here
effective_period(high_series, low_series, volume_series, period_length, lookback_length, max_search)
Calculates adaptive effective period.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Adaptive effective period.
adaptive_ema(source, high_series, low_series, volume_series, period_length, lookback_length, max_search)
Adaptive EMA using effective period.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Adaptive EMA, alpha and effective period.
adaptive_channel(high_series, low_series, volume_series, period_length, lookback_length, smooth_length, max_search)
Adaptive price channel.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
smooth_length (simple int) : EMA smoothing.
max_search (int) : Maximum search distance.
Returns: Effective period, upper, lower, middle and width.
adaptive_rsi(source, high_series, low_series, volume_series, period_length, lookback_length, max_search)
Adaptive RSI.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Adaptive RSI and effective period.
adaptive_atr(high_series, low_series, close_series, volume_series, period_length, lookback_length, max_search)
Adaptive ATR.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Adaptive ATR and effective period.
adaptive_macd(source, high_series, low_series, volume_series, fast_period, slow_period, signal_period, lookback_length, max_search)
Adaptive MACD.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
fast_period (simple int) : Fast adaptive period.
slow_period (simple int) : Slow adaptive period.
signal_period (int) : Signal EMA period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: MACD, Signal, Histogram.
adaptive_bollinger(source, high_series, low_series, volume_series, period_length, deviation, lookback_length, max_search)
Adaptive Bollinger Bands.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
deviation (float) : Standard deviation multiplier.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Upper band, Middle band, Lower band, Band width and Effective period.
adaptive_supertrend(high_series, low_series, close_series, volume_series, period_length, multiplier, lookback_length, max_search)
Adaptive SuperTrend.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
multiplier (float) : ATR multiplier.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: SuperTrend, Trend Direction and Effective Period.
adaptive_donchian(high_series, low_series, volume_series, period_length, lookback_length, max_search)
Adaptive Donchian Channel.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Upper band, Lower band, Middle line, Width and Effective period.
adaptive_keltner(source, high_series, low_series, close_series, volume_series, period_length, multiplier, lookback_length, max_search)
Adaptive Keltner Channel.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
multiplier (float) : ATR multiplier.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Upper band, Middle band, Lower band, Width and Effective period.
adaptive_adx(high_series, low_series, close_series, volume_series, period_length, lookback_length, max_search)
Adaptive ADX.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: ADX, +DI, -DI and Effective Period.
adaptive_stochastic(close_series, high_series, low_series, volume_series, period_length, smooth_k, smooth_d, lookback_length, max_search)
Adaptive Stochastic.
Parameters:
close_series (float) : Close price series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
smooth_k (int) : K smoothing.
smooth_d (int) : D smoothing.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: K, D and Effective Period.
adaptive_cci(high_series, low_series, close_series, volume_series, period_length, lookback_length, max_search)
Adaptive Commodity Channel Index.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: CCI and Effective Period.
adaptive_williams_r(high_series, low_series, close_series, volume_series, period_length, lookback_length, max_search)
Adaptive Williams %R.
Parameters:
high_series (float) : High price series.
low_series (float) : Low price series.
close_series (float) : Close price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: Williams %R and Effective Period.
adaptive_roc(source, high_series, low_series, volume_series, period_length, lookback_length, max_search)
Adaptive Rate of Change.
Parameters:
source (float) : Source series.
high_series (float) : High price series.
low_series (float) : Low price series.
volume_series (float) : Volume series.
period_length (simple int) : Base period.
lookback_length (simple int) : EMA lookback multiplier.
max_search (int) : Maximum search distance.
Returns: ROC and Effective Period.
adaptive_pivot(source, left_bars, right_bars)
Adaptive Pivot Detector.
Parameters:
source (float) : Source series.
left_bars (int) : Left pivot bars.
right_bars (int) : Right pivot bars.
Returns: Pivot High, Pivot Low, Pivot High Price, Pivot Low Price.
adaptive_divergence(price_source, indicator_source, pivot_length)
Adaptive Divergence Detector.
Parameters:
price_source (float) : Price series.
indicator_source (float) : Indicator series.
pivot_length (int) : Pivot length.
Returns: Bullish divergence, Bearish divergence and Divergence strength.
adaptive_pivot_divergence(price_source, signal_source, pivot_length)
Adaptive Pivot Divergence Detector.
Parameters:
price_source (float) : Price series.
signal_source (float) : Indicator series.
pivot_length (int) : Pivot length.
Returns: Bullish divergence, Bearish divergence and Divergence strength.
adaptive_flat_channel(upper_channel, lower_channel, flat_length, tolerance)
Adaptive Flat Channel Detector.
Parameters:
upper_channel (float) : Upper channel.
lower_channel (float) : Lower channel.
flat_length (int) : Number of bars to evaluate.
tolerance (float) : Maximum allowed movement.
Returns: Flat upper, Flat lower and Flat channel.
adaptive_breakout_strength(close_series, upper_channel, lower_channel, channel_width, volume_series, volume_length)
Adaptive Breakout Strength.
Parameters:
close_series (float) : Close price.
upper_channel (float) : Upper channel.
lower_channel (float) : Lower channel.
channel_width (float) : Channel width.
volume_series (float) : Volume.
volume_length (simple int) : Volume EMA length.
Returns: Breakout direction and Breakout strength.
adaptive_channel_rejection(open_series, high_series, low_series, close_series, upper_channel, lower_channel)
Adaptive Channel Rejection.
Parameters:
open_series (float) : Open price.
high_series (float) : High price.
low_series (float) : Low price.
close_series (float) : Close price.
upper_channel (float) : Upper channel.
lower_channel (float) : Lower channel.
Returns: Rejection direction and Rejection strength.
adaptive_channel_compression(channel_width, compression_length)
Adaptive Channel Compression.
Parameters:
channel_width (float) : Width of the channel.
compression_length (simple int) : Number of bars.
Returns: Compression ratio, Is compressing, Is expanding.
adaptive_market_energy(channel_width, volume_series, volume_length)
Adaptive Market Energy.
Parameters:
channel_width (float) : Width of channel.
volume_series (float) : Volume series.
volume_length (simple int) : Volume EMA length.
Returns: Energy score.
adaptive_market_phase(adx, rsi, compression_ratio, breakout_strength)
Adaptive Market Phase.
Parameters:
adx (float) : Adaptive ADX.
rsi (float) : Adaptive RSI.
compression_ratio (float) : Channel compression ratio.
breakout_strength (float) : Breakout strength.
Returns: Market phase.
adaptive_rsi_zigzag(rsi_series, center_level, lookback_length)
Adaptive RSI Zigzag Detector.
Parameters:
rsi_series (float) : RSI series.
center_level (float) : Center level.
lookback_length (int) : Number of bars.
Returns: Zigzag count and Zigzag detected.
adaptive_flat_level(level_series, flat_length, tolerance)
Adaptive Flat Level Detector.
Parameters:
level_series (float) : Channel upper or lower series.
flat_length (int) : Number of bars.
tolerance (float) : Maximum allowed movement.
Returns: Flat state and Flat strength.
adaptive_level_strength(level_series, high_series, low_series, tolerance, lookback_length)
Adaptive Level Strength.
Parameters:
level_series (float) : Support or resistance level.
high_series (float) : High price series.
low_series (float) : Low price series.
tolerance (float) : Touch tolerance.
lookback_length (int) : Number of bars.
Returns: Touch count and Level strength.
adaptive_breakout_probability(breakout_strength, level_strength, compression_ratio, volume_ratio)
Adaptive Breakout Probability.
Parameters:
breakout_strength (float) : Breakout strength.
level_strength (float) : Level strength.
compression_ratio (float) : Channel compression ratio.
volume_ratio (float) : Volume ratio.
Returns: Breakout probability.
adaptive_reversal_probability(rsi, divergence_strength, rejection_strength, flat_strength, channel_width_percent)
Adaptive Reversal Probability.
Parameters:
rsi (float) : Relative Strength Index.
divergence_strength (float) : Divergence strength.
rejection_strength (float) : Rejection strength.
flat_strength (float) : Flat level strength.
channel_width_percent (float) : Channel width percentage.
Returns: Reversal probability.
adaptive_trend_exhaustion(rsi, adx, momentum, roc)
Adaptive Trend Exhaustion.
Parameters:
rsi (float) : Relative Strength Index.
adx (float) : Average Directional Index.
momentum (float) : Momentum.
roc (float) : Rate of Change.
Returns: Trend exhaustion score.
adaptive_channel_memory(upper_channel, lower_channel, tolerance, lookback_length)
Adaptive Channel Memory.
Parameters:
upper_channel (float) : Upper channel.
lower_channel (float) : Lower channel.
tolerance (float) : Maximum channel difference.
lookback_length (int) : Number of bars.
Returns: Memory score.
adaptive_false_breakout(breakout_strength, rejection_strength, volume_ratio)
Adaptive False Breakout Detector.
Parameters:
breakout_strength (float) : Breakout strength.
rejection_strength (float) : Rejection strength.
volume_ratio (float) : Current volume divided by average volume.
Returns: False breakout probability.
adaptive_trap_detector(breakout_direction, breakout_strength, rejection_strength, rsi)
Adaptive Trap Detector.
Parameters:
breakout_direction (int) : Breakout direction.
breakout_strength (float) : Breakout strength.
rejection_strength (float) : Rejection strength.
rsi (float) : Relative Strength Index.
Returns: Trap direction and Trap probability.
adaptive_rsi_behavior(rsi, zigzag_count, divergence_strength, rejection_strength)
Adaptive RSI Behavior.
Parameters:
rsi (float) : Relative Strength Index.
zigzag_count (int) : RSI zigzag count.
divergence_strength (float) : Divergence strength.
rejection_strength (float) : Rejection strength.
Returns: RSI behavior score.
adaptive_market_behavior(trend_strength, reversal_probability, breakout_probability, exhaustion, energy, rsi_behavior)
Adaptive Market Behavior.
Parameters:
trend_strength (float) : Trend strength.
reversal_probability (float) : Reversal probability.
breakout_probability (float) : Breakout probability.
exhaustion (float) : Trend exhaustion.
energy (float) : Market energy.
rsi_behavior (float) : RSI behavior.
Returns: Market behavior score. Library

Isotropic Coordinate System (ICS)Library "ICS"
Isotropic Coordinate System (ICS): a dimensionless price-time space
for scale-invariant chart geometry.
Vertical axis: y = ln(price) / sigma, where sigma is the Yang-Zhang (2000)
minimum-variance, drift-independent, gap-consistent OHLC volatility estimator.
Horizontal axis: two scalings via the XScale enum.
legacy : x = bars / lookback. Linear window fraction. Backward compatible.
isotropic : x = sqrt(bars / lookback), with y additionally divided by
sqrt(lookback). Diffusion-consistent (sqrt-time scaling), so that
tan(theta) equals the z-score of the move and 45 degrees
corresponds to a move of exactly one standard deviation
of the n-bar log-return distribution. Assumes approximately
iid returns within the sigma window (the standard assumption
behind sqrt-time scaling; see Danielsson & Zigrand, 2006, for
its known limits under vol clustering and jumps).
Every output (angle, length, area, centroid) is a pure dimensionless number,
comparable across symbols, currencies, and timeframes.
Reference: Yang, D. & Zhang, Q. (2000), "Drift-Independent Volatility
Estimation Based on High, Low, Open, and Close Prices",
The Journal of Business, 73(3), 477-492.
yangZhangSigma(length)
Yang-Zhang volatility estimator. Minimum-variance, unbiased,
drift-independent, and consistent with opening gaps
(Yang & Zhang, 2000). Uses the unbiased sample variance
(biased = false) for both the overnight and open-to-close
components, matching the estimator's unbiasedness claim.
Parameters:
length (simple int) : (simple int) Rolling window length. Must be >= 2.
Returns: (series float) Per-bar sigma, floored at 1e-10.
toX(bars, lookback, mode)
Dimensionless horizontal coordinate.
Parameters:
bars (int) : (series int) Signed bar distance from the anchor.
lookback (int) : (series int) Window length acting as the horizontal unit.
mode (series XScale) : (series XScale) Scaling mode.
Returns: (series float) Signed dimensionless x.
toY(price, sigma, lookback, mode)
Dimensionless vertical coordinate.
Parameters:
price (float) : (series float) Price. Must be > 0.
sigma (float) : (series float) Yang-Zhang sigma. Must be > 1e-10.
lookback (int) : (series int) Window length (used by isotropic mode only).
mode (series XScale) : (series XScale) Scaling mode.
Returns: (series float) Dimensionless y, or na when inputs are invalid.
moveZScore(dLogPrice, sigma, bars)
Z-score of a log-price move over n bars: dLog / (sigma * sqrt(n)).
In isotropic mode this equals tan(theta) of the same move.
Parameters:
dLogPrice (float) : (series float) ln(target) - ln(anchor).
sigma (float) : (series float) Per-bar Yang-Zhang sigma. Must be > 1e-10.
bars (int) : (series int) Number of bars in the move. Must be > 0.
Returns: (series float) The z-score, or na when inputs are invalid.
triangle(td, anchorPrice, anchorBar, targetPrice, targetBar, sig, lookback, mode)
Right triangle between an anchor and a target, computed entirely
in ICS space. Writes results in place into `td` and returns it.
On invalid inputs every field is set to na, so world X never
receives contaminated numbers.
Parameters:
td (TriangleData) : (TriangleData) Output object, updated in place.
anchorPrice (float) : (series float) Anchor price (world A). Must be > 0.
anchorBar (int) : (series int) Anchor bar_index.
targetPrice (float) : (series float) Target price (world A). Must be > 0.
targetBar (int) : (series int) Target bar_index. Must differ from anchorBar.
sig (float) : (series float) Yang-Zhang sigma. Must be > 1e-10.
lookback (int) : (series int) Horizontal unit window.
mode (series XScale) : (series XScale) Scaling mode.
Returns: (TriangleData) The same `td`, for chaining.
pinTriangle(td, anchorPrice, anchorBar, extremePrice, bodyPrice, curBar, sig, lookback, mode)
Pin (wick) triangle with three vertices in ICS space:
A = anchor, B = candle extreme, C = candle body edge.
Side BC is the wick. theta = signed angle at A between AB and AC.
Since xB = xC, the shoelace area reduces exactly to
0.5 * |yB - yC| * |dx|.
Parameters:
td (TriangleData) : (TriangleData) Output object, updated in place.
anchorPrice (float) : (series float) Anchor price (hh or ll). Must be > 0.
anchorBar (int) : (series int) Anchor bar_index.
extremePrice (float) : (series float) Candle extreme (high or low). Must be > 0.
bodyPrice (float) : (series float) Candle body edge. Must be > 0.
curBar (int) : (series int) Current bar_index. Must differ from anchorBar.
sig (float) : (series float) Yang-Zhang sigma. Must be > 1e-10.
lookback (int) : (series int) Horizontal unit window.
mode (series XScale) : (series XScale) Scaling mode.
Returns: (TriangleData) The same `td`, for chaining.
zeroTri(td)
Resets a TriangleData to na. Use when the structure is inactive,
so inactive periods never enter moving averages or normalization
as fake zero values.
Parameters:
td (TriangleData) : (TriangleData) Object to reset, updated in place.
Returns: (TriangleData) The same `td`, for chaining.
TriangleData
One triangle's measurements in ICS space. All fields dimensionless.
Fields:
theta (series float) : Signed hypotenuse angle in degrees; in isotropic mode tan(theta) is the z-score of the move.
dy (series float) : Signed Euclidean magnitude of the hypotenuse.
area (series float) : Triangle area (>= 0).
centroidY (series float) : Vertical centroid of the triangle.
FrozenAnchors
Anchors frozen at a reference bar, plus activity state.
Fields:
hh (series float) : Highest high at the freeze bar (world-A price units).
ll (series float) : Lowest low at the freeze bar (world-A price units).
mid (series float) : Geometric mean sqrt(hh * ll) at the freeze bar.
bar_x (series int) : bar_index of the freeze bar.
time_x (series int) : time of the freeze bar.
is_active (series bool) : Whether the frozen structure is currently active. Library

DivergenceLineLabelOutput_UtilitiesDivergenceLineLabelOutput_Utilities is a shared Pine v6 output library for scripts that already have their own oscillator, pivot, structure, or divergence logic but want a reusable divergence-rendering layer.
It centralizes the parts of the workflow that tend to get rewritten across oscillator scripts:
• HH / LH / HL / LL / EQ structure resolution
• regular / hidden divergence state checks
• same-structure context state checks
• divergence and context color routing
• standardized divergence/context label text
• price-pane and oscillator-pane line helpers
• price-pane and oscillator-pane label helpers
• confirmed-object slot visibility helpers
• live-preview line and label helpers
• native-pane and price-pane pivot context box helpers
On the example chart, the confirmed divergence lines, live preview lines, divergence labels, context labels, and pivot context boxes are all materially driven by this library.
This library is intentionally focused on output and object management. It does not calculate RSI, MACD, VFI, volume flow, pressure, or any other oscillator. It does not confirm pivots or decide which pivots are valid. Calling scripts remain responsible for their own oscillator engine, pivot engine, comparison logic, colors, visibility modes, and signal interpretation.
How to use
Import the library near the top of your script in global scope, alongside any other imports, before you start calling its helpers.
Typical placement:
//@version=6
indicator(...) or strategy(...)
import MYNAMEISBRANDON/DivergenceLineOutput_Utilities/1 as DivUtils
Replace /1 with the latest published version if a newer version is available.
This library expects the calling script to already know the price pivot, oscillator pivot, prior pivot reference, structure state, and output settings it wants to use. The library then handles the reusable line, label, live-preview, slot-budget, and box output layer.
➖Structure + Divergence State Helpers➖
These helpers convert pivot comparisons into structure tags and divergence/context states.
divStructure(curr, prev, isHigh)
Resolves HH, LH, HL, LL, or EQ from a current pivot and previous pivot.
Parameters:
curr (float): Current pivot value
prev (float): Previous pivot value
isHigh (bool): True for high-side comparison, false for low-side comparison
Returns:
Structure string
divState(priceStruct, oscStruct)
Resolves regular and hidden divergence states from price and oscillator structure tags.
Returns:
regularBear, regularBull, hiddenBear, hiddenBull, anyDivergence
divContextState(priceStruct, oscStruct)
Resolves same-structure context states from price and oscillator structure tags.
Returns:
highContinuation, highFade, lowContinuation, lowLift, anyContext
divColor(priceStruct, oscStruct, regularBearColor, regularBullColor, hiddenBearColor, hiddenBullColor, highContinuationColor, lowContinuationColor, highFadeColor, lowLiftColor, fallbackColor)
Routes a divergence or context pair to the matching caller-supplied color.
Returns:
Resolved color
➖Style + Label Helpers➖
These helpers keep divergence output styling consistent across scripts.
divLineStyle(styleIn)
Converts user-facing line-style text into Pine line-style enums.
Parameters:
styleIn (simple string): Solid, Dashed, or Dotted
Returns:
Pine line style
divLabelSize(sizeIn)
Converts user-facing label-size text into Pine label-size enums.
Parameters:
sizeIn (simple string): Tiny, Small, Normal, Large, or Huge
Returns:
Pine label size
divContrastText(bg)
Chooses black or white text based on background brightness.
Parameters:
bg (color): Background color
Returns:
Readable contrast text color
divLabelText(divType, divSide, priceStruct, oscStruct, formatMode)
Builds standardized divergence label text.
Parameters:
divType (simple string): Usually Reg or Hid
divSide (simple string): Usually Bull or Bear
priceStruct (string): Price structure tag
oscStruct (string): Oscillator structure tag
formatMode (simple string): Full, No Prefix, or Type Only
Returns:
Formatted label text
➖Confirmed Line Helpers➖
These helpers create and manage confirmed divergence or context lines.
clearLines(lines, colors)
Deletes all lines in an array and clears the matching color array.
pushOscLine(lines, colors, show, active, x1, y1, x2, y2, lineColor, lineTransp, lineWidth, lineStyle, maxLines)
Pushes a confirmed oscillator-pane line into line/color arrays.
pushPriceLine(lines, colors, show, active, x1, y1, x2, y2, lineColor, lineTransp, lineWidth, lineStyle, maxLines)
Pushes a confirmed price-pane line into line/color arrays using force_overlay=true.
Note:
Price helpers draw on the main chart from overlay=false oscillator scripts. Oscillator helpers draw in the script’s native pane.
➖Confirmed Label Helpers➖
These helpers create and manage confirmed divergence or context labels.
clearLabels(labels, colors)
Deletes all labels in an array and clears the matching color array.
pushOscLabel(labels, colors, show, active, xIndex, y, labelText, styleText, lineColor, labelTextOnly, labelBgTransp, labelSize, maxLabels)
Pushes a confirmed oscillator-pane label into label/color arrays.
pushPriceLabel(labels, colors, show, active, xTime, labelText, ylocText, styleText, lineColor, labelTextOnly, labelBgTransp, labelSize, maxLabels)
Pushes a confirmed price-pane label into label/color arrays using force_overlay=true.
Note:
For price-pane labels, xTime uses bar time and ylocText controls whether the label appears above or below the price bar.
➖Confirmed Slot Visibility Helpers➖
These helpers allow scripts to keep confirmed lines and labels stored while only showing the most recent visible slots.
applyLineSlots(lines, colors, visibleSlots)
Applies a visible slot budget to confirmed line arrays without deleting older objects.
applyLabelSlots(labels, colors, visibleSlots, labelTextOnly, labelBgTransp)
Applies a visible slot budget to confirmed label arrays without deleting older objects.
Example:
• Max Regular Lines = 1
- Live regular active = live regular only
- No live regular = latest confirmed regular only
• Max Regular Lines = 2
- Live regular active = live regular + latest confirmed regular
- No live regular = latest two confirmed regular lines
➖Live Preview Line Helpers➖
These helpers create, update, or delete live divergence preview lines.
syncLiveOscLine(ln, show, x1, y1, x2, y2, lineColor, lineWidth, lineStyle)
Creates, updates, or deletes a live oscillator-pane line.
syncLivePriceLine(ln, show, x1, y1, x2, y2, lineColor, lineWidth, lineStyle)
Creates, updates, or deletes a live price-pane line using force_overlay=true.
➖Live Preview Label Helpers➖
These helpers create, update, or delete live divergence preview labels.
syncLiveOscLabel(lbl, show, xIndex, y, labelText, styleText, lineColor, labelTextOnly, labelBgTransp, labelSize)
Creates, updates, or deletes a live oscillator-pane label.
syncLivePriceLabel(lbl, show, xTime, labelText, ylocText, styleText, lineColor, labelTextOnly, labelBgTransp, labelSize)
Creates, updates, or deletes a live price-pane label using force_overlay=true.
➖Pivot Context Box Helpers➖
These helpers provide lightweight box utilities for scripts that want to frame confirmed pivot zones.
divPivotBoxBounds(pivotValue, innerPct)
Resolves a thin box around a pivot value using an inner percentage.
Returns:
top, bottom, ok
syncNativeBox(bx, show, left, right, top, bottom, fillColor, borderColor, borderStyle, borderWidth)
Creates, updates, or deletes a native-pane pivot context box.
syncPriceBox(bx, show, left, right, top, bottom, fillColor, borderColor, borderStyle, borderWidth)
Creates, updates, or deletes a price-pane pivot context box using force_overlay=true.
➖Divergence Model➖
Regular Bearish Divergence:
Price makes HH while oscillator makes LH.
Regular Bullish Divergence:
Price makes LL while oscillator makes HL.
Hidden Bearish Divergence:
Price makes LH while oscillator makes HH.
Hidden Bullish Divergence:
Price makes HL while oscillator makes LL.
➖Structure Context Model➖
High-side continuation:
Price makes HH while oscillator also makes HH.
High-side fading:
Price makes LH while oscillator also makes LH.
Low-side continuation:
Price makes LL while oscillator also makes LL.
Low-side lifting:
Price makes HL while oscillator also makes HL.
Structure context is not divergence. It shows same-structure agreement between price and oscillator.
➖Important Notes➖
This library is an output utility layer only.
It does not:
• calculate an oscillator
• confirm pivots
• choose pivot anchors
• decide whether a divergence is valid
• decide trade direction
• decide final signal logic
Calling scripts remain responsible for:
• oscillator calculation
• pivot confirmation
• price/oscillator comparison logic
• visibility settings
• color choices
• max-line and max-label budgets
• final visual interpretation
For overlay=false oscillator scripts, Price + Oscillator / Price Only / Oscillator Only / Hide output modes work well.
For overlay=true price-pane scripts, Price Only / Hide output modes usually make the most sense. Library

Obj_XABCD_HarmonicLibrary "Obj_XABCD_Harmonic"
Harmonic XABCD Pattern object and associated methods. Easily validate, draw, and get information about harmonic patterns. See example code at the end of the script for details.
init_params(pct_error, pct_asym, types, w_e, w_p, w_d)
Create a harmonic parameters object (used by xabcd_harmonic object for pattern validation and scoring).
Parameters:
pct_error (float) : Allowed % error of leg retracement ratio versus the defined harmonic ratio
pct_asym (float) : Allowed leg length/period asymmetry % (a leg is considered invalid if it is this % longer or shorter than the average length of the other legs)
types (array) : Array of pattern types to validate (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark, 6=Cypher, 7=Alt-Bat, 8=Deep Butterfly, 9=Deep Crab)
w_e (float) : Weight of ratio % error (used in score calculation, dft = 1)
w_p (float) : Weight of PRZ confluence (used in score calculation, dft = 1)
w_d (float) : Weight of Point D / PRZ confluence (used in score calculation, dft = 1)
Returns: harmonic_params object instance. It is recommended to store and reuse this object for multiple xabcd_harmonic objects rather than creating new params objects unnecessarily.
method erase_pattern(p)
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic)
init(x, a, b, c, d, params, tp, p)
Initialize an xabcd_harmonic object instance from a given set of points
If the pattern is valid, an xabcd_harmonic object instance is returned. If you want to specify your
own validation and scoring parameters, you can do so by passing a harmonic_params object (params).
Or, if you prefer to do your own validation, you can explicitly pass the harmonic pattern type (tp)
and validation will be skipped. You can also pass in an existing xabcd_harmonic instance if you wish
to re-initialize it (e.g. for re-validation and/or re-scoring).
Parameters:
x (point type from reees/Pattern/1) : Point X
a (point type from reees/Pattern/1) : Point A
b (point type from reees/Pattern/1) : Point B
c (point type from reees/Pattern/1) : Point C
d (point type from reees/Pattern/1) : Point D
params (harmonic_params) : harmonic_params used to validate and score the pattern. Validation will be skipped if a type (tp) is explicitly passed in.
tp (int) : Pattern type
p (xabcd_harmonic) : xabcd_harmonic object instance to initialize (optional, for re-validation/re-scoring)
Returns: xabcd_harmonic object instance if a valid harmonic, else na
init(xX, xY, aX, aY, bX, bY, cX, cY, dX, dY, params, tp, p)
Initialize an xabcd_harmonic object instance from a given set of x and y coordinate values.
If the pattern is valid, an xabcd_harmonic object instance is returned. If you want to specify your
own validation and scoring parameters, you can do so by passing a harmonic_params object (params).
Or, if you prefer to do your own validation, you can explicitly pass the harmonic pattern type (tp)
and validation will be skipped. You can also pass in an existing xabcd_harmonic instance if you wish
to re-initialize it (e.g. for re-validation and/or re-scoring).
Parameters:
xX (int) : Point X bar index (required)
xY (float) : Point X price/level (required)
aX (int) : Point A bar index (required)
aY (float) : Point A price/level (required)
bX (int) : Point B bar index (required)
bY (float) : Point B price/level (required)
cX (int) : Point C bar index (required)
cY (float) : Point C price/level (required)
dX (int) : Point D bar index
dY (float) : Point D price/level
params (harmonic_params) : harmonic_params used to validate and score the pattern. Validation will be skipped if a type (tp) is explicitly passed in.
tp (int) : Pattern type
p (xabcd_harmonic) : xabcd_harmonic object instance to initialize (optional, for re-validation/re-scoring)
Returns: xabcd_harmonic object instance if a valid harmonic, else na
init(pattern, params, tp, p)
Initialize an xabcd_harmonic object instance from a given pattern
If the pattern is valid, an xabcd_harmonic object instance is returned. If you want to specify your
own validation and scoring parameters, you can do so by passing a harmonic_params object (params).
Or, if you prefer to do your own validation, you can explicitly pass the harmonic pattern type (tp)
and validation will be skipped. You can also pass in an existing xabcd_harmonic instance if you wish
to re-initialize it (e.g. for re-validation and/or re-scoring).
Parameters:
pattern (pattern type from reees/Pattern/1) : Pattern
params (harmonic_params) : harmonic_params used to validate and score the pattern. Validation will be skipped if a type (tp) is explicitly passed in.
tp (int) : Pattern type
p (xabcd_harmonic) : xabcd_harmonic object instance to initialize (optional, for re-validation/re-scoring)
Returns: xabcd_harmonic object instance if a valid harmonic, else na
method get_name(p)
Get the pattern name
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: Pattern name (string)
method get_symbol(p)
Get the pattern symbol from a pattern instance
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: Pattern symbol string
get_symbol(tp)
Get the pattern symbol for a given pattern type integer.
Static overload — does not require a pattern instance.
Parameters:
tp (int) : Pattern type (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark,
6=Cypher, 7=Alt-Bat, 8=Deep Butterfly, 9=Deep Crab)
Returns: Pattern symbol string
method get_pid(p)
Get the Pattern ID. Patterns of the same type with the same coordinates will have the same Pattern ID.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: Pattern ID (string)
method prz_range(p)
Returns cached PRZ upper and lower bounds.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns:
method incomplete_pid(p)
Returns the pattern ID as if point D were unconfirmed (na).
Used to match incomplete patterns against their completed counterparts
during deduplication. Ensures pid format is consistent with the
library's internal pid generation.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: Pattern ID string with D forced to na
method set_target(p, target, target_lvl, calc_target)
Set value for a target. Use the calc_target parameter to automatically calculate the target for a specific harmonic ratio.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
target (int) : Target (1 or 2)
target_lvl (float) : Target price/level (required if calc_target is not specified)
calc_target (string) : Target to auto calculate (required if target is not specified)
Options:
Returns: Target price/level (float)
method draw_pattern(p, clr)
Draw the pattern
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
clr (color)
Returns: Pattern lines
method erase_label(p)
Erase the pattern label
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: p
method draw_prz_levels(p, clr, extendBars)
Draw PRZ target levels as horizontal dashed lines for incomplete patterns.
Shows where point D needs to land without implying a specific price path.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
clr (color) : Line color
extendBars (int) : Number of bars to extend the lines to the right (default 50)
Returns: — the two PRZ level lines
method draw_label(p, clr, txt_clr, txt, tooltip)
Draw the pattern label. Default text is the pattern name.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
clr (color) : Label color
txt_clr (color) : Text color
txt (string) : Label text
tooltip (string) : Tooltip text
Returns: Label
method is_complete(p)
Returns true if the pattern has a confirmed point D.
A pattern is complete when D exists AND is not an unconfirmed pivot.
Use this instead of checking na(p.d.x) directly — invalid_d being
false is a required condition that bare na checks miss.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
Returns: bool
method age_pct(p, tLimitMult)
Returns how far through the pattern's time limit it is, as a 0.0–1.0 float.
0.0 = just confirmed, 1.0 = time limit reached.
Returns na if pattern has no confirmed D point.
Namespace types: xabcd_harmonic
Parameters:
p (xabcd_harmonic) : Instance of xabcd_harmonic object
tLimitMult (float) : Pattern time limit multiplier (same value used in main script)
Returns: float 0.0–1.0
harmonic_params
Validation and scoring parameters for a Harmonic Pattern object (xabcd_harmonic)
Fields:
pct_error (series float) : Allowed % error of leg retracement ratio versus the defined harmonic ratio
pct_asym (series float)
types (array)
w_e (series float)
w_p (series float)
w_d (series float)
xabcd_harmonic
Harmonic Pattern object
Fields:
bull (series bool) : Bullish pattern flag
tp (series int)
x (point type from reees/Pattern/1)
a (point type from reees/Pattern/1)
b (point type from reees/Pattern/1)
c (point type from reees/Pattern/1)
d (point type from reees/Pattern/1)
r_xb (series float)
re_xb (series float)
r_ac (series float)
re_ac (series float)
r_bd (series float)
re_bd (series float)
r_xd (series float)
re_xd (series float)
score (series float)
score_eAvg (series float)
score_prz (series float)
score_eD (series float)
prz_bN (series float)
prz_bF (series float)
prz_xN (series float)
prz_xF (series float)
przUpper (series float)
przLower (series float)
t1Hit (series bool) : Target 1 flag
t1 (series float)
t2Hit (series bool)
t2 (series float)
sHit (series bool) : Stop flag
stop (series float) : Stop level
entry (series float) : Entry level
eHit (series bool)
e (point type from reees/Pattern/1)
invalid_d (series bool)
pLines (array)
pLabel (series label)
cdLine (series line)
pid (series string)
params (harmonic_params) Library

Library

Indicator

CyberSignalLib# CyberSignalLib v2
CyberSignalLib provides advanced signal processing tools for Pine Script traders, combining Kalman filtering, entropy-based changepoint detection, and market microstructure analysis in a single dependency.
## What it does
SignalLib delivers three core capabilities: N-dimensional Kalman filters for multi-feature state estimation (price, velocity, z-scores), entropy-based changepoint detectors for regime shifts (NIS, CUSUM, BOCPD), and microstructure metrics for order flow analysis (delta, aggression, volume imbalance). Traders use these tools to build adaptive indicators that respond to market regime changes—for example, a Kalman filter tracking price and volatility simultaneously, with automatic parameter adjustment when a changepoint detector signals a structural break.
The library outputs filtered state estimates (smoothed price, velocity, Mahalanobis distance), changepoint probabilities (0-1 scores indicating regime shift likelihood), and microstructure features (signed delta, aggression ratio, volume-weighted imbalance). All functions support real-time bar-by-bar updates with minimal memory overhead via circular buffers and packed covariance matrices.
## How it works
The Kalman filter implementation uses an N-dimensional state vector with upper-triangular packed covariance storage, reducing memory from O(N²) to O(N(N+1)/2). The filter supports diagonal process noise (Q) and scalar measurement noise (R), both adaptive via innovation tracking. The update step follows the standard predict-correct cycle: predict state using transition matrix F, compute innovation (measurement - prediction), update state and covariance via Kalman gain. Normalized Innovation Squared (NIS) is computed as `innovation² / (H·P·H' + R)` to detect outliers and trigger adaptive R adjustments.
Changepoint detection uses three methods:
1. **NIS-based**: Flags regime change when NIS exceeds a threshold (e.g., 9.0 for 99% confidence under chi-squared distribution)
2. **CUSUM**: Cumulative sum of log-likelihood ratios, resets when crossing upper/lower bounds
3. **BOCPD (Bayesian Online Changepoint Detection)**: Maintains run-length distribution, computes changepoint probability via hazard function
Entropy calculations support four modes: binary (up/down), ternary (up/flat/down), combo (binary + ternary), and composite (weighted average). Shannon entropy is computed as `-Σ p_i log₂(p_i)` where p_i are empirical frequencies over a rolling window. High entropy (near maximum) indicates unpredictable price action; low entropy signals trending or mean-reverting regimes.
Microstructure metrics derive from tick-level order flow:
- **Delta**: Signed volume (buy volume - sell volume)
- **Aggression**: Ratio of aggressive orders (market orders) to total volume
- **Imbalance**: `(buy_vol - sell_vol) / (buy_vol + sell_vol)`, range
These metrics are computed via request.security calls to lower timeframes (1-minute typical) and aggregated to the chart timeframe.
## Why this is original
CyberSignalLib is the only TradingView library combining Kalman filtering, changepoint detection, and microstructure analysis in a unified interface. Existing Kalman filter libraries are limited to 1D or 2D state spaces and lack adaptive noise parameters. No public library offers BOCPD or CUSUM changepoint detection. Microstructure metrics typically require manual request.security calls with hardcoded timeframes—SignalLib abstracts this into reusable functions with configurable lookback windows.
Unique features:
- **Tri-packed covariance**: Memory-efficient N-dimensional Kalman filter (supports up to 16 features on TradingView's memory limits)
- **Adaptive Q/R**: Automatic process/measurement noise tuning based on innovation statistics, eliminating manual parameter tweaking
- **Trajectory store**: Circular buffer for Kalman state history, enabling lookback analysis (e.g., "was price above Kalman estimate 5 bars ago?")
- **Mahalanobis distance**: 3D analytic formula with shrinkage regularization for outlier detection in multi-feature space
- **Unified changepoint API**: Single enum-based interface for NIS/CUSUM/BOCPD, simplifying regime-switching indicator logic
No other Pine library provides this combination of statistical rigor (Kalman optimality, Bayesian changepoint inference) and practical usability (adaptive parameters, memory-efficient storage, microstructure integration).
## How to use it
```pine
//@version=6
indicator("CyberSignalLib Demo", overlay=true)
import cybermediaboy/CyberSignalLib/2 as SL
import cybermediaboy/NumLib/5 as N
// Example 1: 2D Kalman filter (price + velocity)
var kal = SL.f_kalman_init(nfeat=2, P0=1.0, Q0=0.01, R0=0.1, innov_window=20)
if not na(close)
kal.update_scalar(0, close, 1.0) // Measure price (feature 0)
kal.predict(SL.f_transition_identity(2))
kal.adapt_Q(Q_min=0.001, Q_max=0.1, gain=1.5)
kal.adapt_R(high_thresh=9.0, low_thresh=1.0, R_step=0.1)
float price_est = array.get(kal.x, 0)
float velocity_est = array.get(kal.x, 1)
plot(price_est, "Kalman Price", color.blue, linewidth=2)
plot(close + velocity_est * 10, "Velocity Offset", color.orange)
// Example 2: NIS-based changepoint detection
bool changepoint = kal.lastnis > 9.0 // 99% confidence threshold
bgcolor(changepoint ? color.new(color.red, 80) : na, title="Regime Change")
// Example 3: Entropy calculation (ternary mode)
var ent_buf = array.new(50, 0)
int direction = close > close ? 1 : (close < close ? -1 : 0)
array.push(ent_buf, direction)
if array.size(ent_buf) > 50
array.shift(ent_buf)
float entropy = SL.f_entropy_ternary(ent_buf)
plot(entropy, "Ternary Entropy", color.green)
// Example 4: Mahalanobis distance (3D outlier detection)
var z_vec = array.from(close, volume, ta.rsi(close, 14))
var mu_vec = array.from(ta.sma(close, 50), ta.sma(volume, 50), 50.0)
var cov_tri = array.from(1.0, 0.0, 0.0, 1.0, 0.0, 1.0) // Identity covariance
float maha = SL.f_mahalanobis_3d(z_vec, mu_vec, cov_tri, shrinkage=0.1)
plot(maha, "Mahalanobis Distance", color.purple)
```
## Inputs, outputs, expected behavior
**Kalman filter** (`f_kalman_init`, `update_scalar`, `predict`):
- **Inputs**: `nfeat` (int, 1-16 typical), `P0/Q0/R0` (float, initial noise estimates), `measurement` (float), `H` (float, observation matrix row)
- **Outputs**: Updated state vector `x` (array), NIS value `lastnis` (float, unbounded), ready flag `ready` (bool)
- **Edge cases**: Returns unmodified state if measurement is NA, requires ≥20 bars for adaptive Q/R to stabilize
**Changepoint detection** (`f_changepoint_nis`, `f_changepoint_cusum`, `f_changepoint_bocpd`):
- **Inputs**: `nis` (float, typically from Kalman filter), `threshold` (float, 9.0 for 99% confidence), `hazard` (float, 0.01-0.1 for BOCPD)
- **Outputs**: Changepoint probability (float, ) or binary flag (bool)
- **Edge cases**: CUSUM resets on boundary crossing, BOCPD requires ≥10 bars for stable run-length distribution
**Entropy functions** (`f_entropy_binary`, `f_entropy_ternary`, `f_entropy_combo`):
- **Inputs**: `data` (array, direction codes: -1/0/1), `window` (int, 20-100 typical)
- **Outputs**: Shannon entropy (float, ), max entropy = 1.0 for binary, 1.585 for ternary
- **Edge cases**: Returns 0.0 if all elements identical, handles empty arrays gracefully
**Microstructure metrics** (`f_get_micro_state`, `f_get_scientific_delta`, `f_get_aggregated_volume`):
- **Inputs**: `timeframe` (string, "1" for 1-minute), `lookback` (int, bars to aggregate)
- **Outputs**: Delta (float, signed volume), aggression (float, ), imbalance (float, )
- **Edge cases**: Returns NA if lower timeframe data unavailable, requires Premium/Pro account for intraday request.security
**Trajectory store** (`f_trajectory_new`, `push`, `read`):
- **Inputs**: `snap_dim` (int, state vector length), `capacity` (int, max snapshots), `offset` (int, 0=latest)
- **Outputs**: Snapshot array (array, length `snap_dim`)
- **Edge cases**: Returns NA-filled array if offset exceeds filled count, circular overwrite after capacity reached
## Limitations
1. **Kalman filter assumes linear dynamics**: The transition matrix F is diagonal (no cross-feature coupling). For non-linear systems (e.g., price-volatility feedback loops), the filter may diverge. Extended Kalman Filter (EKF) or Unscented Kalman Filter (UKF) variants are not implemented.
2. **Changepoint detection requires tuning**: NIS threshold (default 9.0) assumes Gaussian measurement noise. In heavy-tailed distributions (crypto, low-liquidity assets), false positives increase. CUSUM and BOCPD require manual hazard/boundary tuning per asset and timeframe.
3. **Microstructure functions require lower timeframe data**: `f_get_micro_state` and related functions call request.security with `timeframe="1"` (1-minute). This fails on daily/weekly charts or for symbols without intraday data. Users must handle NA returns or pre-filter symbols.
4. **Memory overhead for high-dimensional Kalman**: An N=16 feature Kalman filter requires 136 floats for packed covariance (16×17/2) plus state vector. On TradingView's 50,000 float limit per script, this restricts other arrays. Reduce `nfeat` or use sparse feature selection.
5. **Entropy calculations assume discrete states**: Binary/ternary entropy requires pre-discretized input (direction codes -1/0/1). Continuous price data must be manually binned. The library does not auto-discretize or suggest bin counts.
6. **No multi-step prediction**: The Kalman filter supports one-step-ahead prediction only. For multi-bar forecasts (e.g., "predict price 5 bars ahead"), users must manually iterate the predict step, which compounds uncertainty without re-measurement.
7. **Adaptive Q/R convergence time**: Adaptive noise parameters require 20-50 bars to stabilize after initialization or regime change. During this period, filter estimates may be suboptimal. Consider using fixed Q/R for the first 50 bars, then enabling adaptation.
Library

Smart Trader, Episode 07, ICS Geometric Buyers/Sellers Pressure🔶 Overview
ICS Geometric Buyer/Seller Pressure measures the real-time balance between buying and selling forces through a geometric framework built on triangle areas. Rather than relying on volume, oscillators, or moving-average crossovers, this indicator constructs two right triangles on every bar — one representing seller pressure above the current price, one representing buyer pressure below it — and computes their areas inside a normalized coordinate system called the Isotropic Coordinate System (ICS).
The ICS transforms raw price and time into a dimensionless plane using Yang-Zhang composite volatility as the scaling factor. Because both axes are divided by the same volatility estimate, the resulting triangle areas carry no unit — they are pure geometric ratios. This makes the pressure reading comparable across any instrument, any timeframe, and any price scale, without the trader needing to adjust parameters when switching charts.
From these two normalized areas, the indicator derives a single metric called B, which condenses the entire buyer-versus-seller balance into a value between −1 and +1. B is then converted into intuitive percentage readings (Red % for seller dominance, Blue % for buyer dominance) and visualized through a gradient barometer column, a triangle fan overlay, and data-window plots ready for alerts.
🔶 Conceptual framework
To measure the real-time balance between buying and selling forces, this indicator takes a geometric approach rather than relying on volume analysis, oscillator divergences, or moving-average crossovers. Two right triangles are constructed on every bar — one above the current price toward the range ceiling, one below toward the range floor — and their areas are compared to determine which side of the market currently dominates.
Computing triangle areas in raw price-versus-time coordinates, however, introduces a structural problem: the same price movement produces a different geometric shape depending on the chart's zoom level, time compression, or display resolution. A 30-point rally on a compressed weekly chart creates a steep, narrow triangle; the identical rally on a stretched intraday chart creates a flat, wide one. The areas differ even though the underlying market event is the same.
To eliminate this distortion, the indicator applies a normalization layer referred to here as the Isotropic Coordinate System (ICS). The principle behind it is dimensional analysis — a well-established technique in physics and engineering for removing unit-dependent artifacts from measurements. The horizontal axis (time) is rescaled by dividing bar offsets by sigma, and the vertical axis (price) is rescaled by dividing the natural logarithm of price by the same sigma. Because both axes share the same divisor, the resulting coordinate plane is isotropic: triangle areas reflect only the structural relationship between price and range boundaries, not how the chart happens to be displayed.
The sigma used for this normalization is the Yang-Zhang (2000) composite volatility estimator, a published academic method (Journal of Business, Vol. 73, No. 3). It combines three independent variance components — overnight (close-to-open), intraday (open-to-close), and the Rogers-Satchell high-low-close estimator — into a single unbiased measure with minimum-variance weighting. This makes sigma robust across instruments with overnight gaps (equities, futures) and those that trade continuously (forex, crypto).
The practical result: the normalization layer adapts to the volatility regime of each instrument, making triangle areas structurally comparable across different charts and timeframes and reducing the need for manual recalibration when switching instruments.
🔶 The B metric: from triangle geometry to a single number
The core output of this indicator is a single value called B, which captures the instantaneous buyer-versus-seller balance in one dimensionless number.
Picture any bar on your chart. The indicator draws two right triangles around it. The upper triangle sits between the bar's high and the range ceiling: its three vertices are (1) the current bar's high, (2) the range ceiling at the current bar, and (3) the range ceiling at the prime-offset bar, 101 bars back. This triangle represents seller territory — the geometric "room" that sellers occupy above the current price. The lower triangle mirrors this below: its vertices are the current bar's low, the range floor at the current bar, and the range floor at that same prime-offset bar. This is buyer territory — the room below the current price. The larger the seller triangle relative to the buyer triangle, the more the market is tilted toward selling pressure, and vice versa.
Why prime-numbered offsets?
The indicator uses the first 25 prime numbers (3, 5, 7, 11, ... 97, 101) as its sampling offsets. Prime numbers share no common factors with each other or with any periodic cycle in the data. When a signal is sampled at evenly spaced intervals (e.g. every 10, 20, 30 bars), there is a risk that the sampling grid locks onto a periodic pattern in the price — a weekly cycle, an options expiration rhythm, or any recurring structure — and either amplifies or masks it. This is a form of harmonic aliasing. Prime offsets avoid this: because no prime is a multiple of any other, the sampling set {3, 5, 7, ... 101} is maximally non-periodic, ensuring that each offset captures a structurally independent slice of the price range.
Two roles: measurement and visualization
For the B calculation itself, only the widest triangle is used — the one anchored at prime offset 101. This single pair of triangles (upper and lower) captures the broadest structural pressure across the entire lookback window. The remaining 24 primes serve a visual role: they generate the triangle fan overlay you see on the chart. But this visual layer is not merely decorative. Each triangle in the fan maps a pressure boundary at a different time horizon.
As the screenshot above illustrates, candles that approach the red triangle edges tend to encounter resistance and reverse — the fan effectively draws a multi-scale map of where selling pressure intensifies. The blue fan does the same for buyer pressure below. Taken together, the fan gives the trader a spatial reading of how pressure distributes across shorter and longer horizons.
A notable property observed during testing across multiple instruments and timeframes: regardless of triangle size or lookback period, B consistently produces values within the bounded range of -1 to +1. This is not a coincidence — it is a mathematical consequence of the symmetric ratio formula that derives B from the two triangle areas.
The formula
Both triangle areas are first computed using the Shoelace formula — a standard computational geometry method that yields the exact area of any polygon from its vertex coordinates. Then B is derived through a symmetric ratio:
r1 = A_hi / A_lo r2 = A_lo / A_hi B = (r1 - r2) / (r1 + r2)
When the seller triangle is much larger than the buyer triangle (A_hi >> A_lo), r1 grows large while r2 shrinks, and B approaches +1. When buyer pressure dominates, B approaches -1. When both areas are equal, B = 0 — balanced pressure. The formula is symmetric by construction, meaning it treats buyer and seller sides with identical mathematical weight.
Percentage conversion
To make B immediately readable on the chart, the indicator converts it into two percentage values:
Red % = (B + 1) x 50 seller dominance, scale 0 to 100
Blue % = (1 - B) x 50 buyer dominance, scale 0 to 100
Red % and Blue % always sum to 100. They are available in the Data Window for any bar and are exposed as alert-ready plots, allowing traders to set threshold-based alerts (e.g. "Red % crosses above 80") directly from TradingView's alert builder, without writing any code.
🔶 Features at a glance
🔸 Gradient barometer — A vertical column rendered to the right of the last bar. It splits the effective range into a red (seller) zone and a blue (buyer) zone, with the dividing line set by B. The gradient fades from full opacity at the split point to near-transparent at each range boundary, giving an immediate visual sense of which side is dominant and by how much.
🔸 Prime triangle fan — 25 filled triangles (one per prime offset from 3 to 101) overlaid on the chart. Upper triangles are colored red (seller pressure), lower triangles blue (buyer pressure). Together they form a fan that maps pressure intensity across multiple time horizons simultaneously. Optional dashed outlines can be enabled for each side independently.
🔸 Range lines with price labels — Horizontal lines marking the effective high and low of the lookback window. Each line carries a price label placed to the left of the range start. When the channel is frozen (see Freeze/Revival below), a snowflake icon (❄) appears on the labels.
🔸 Diamond markers and prime labels — At each prime-offset bar, a diamond marker is placed at both the range ceiling and the range floor. The corresponding prime number is displayed above the ceiling diamond, providing a visual ruler of the sampling structure.
🔸 Freeze / Revival system — When a confirmed close breaches the range boundary, the mother channel freezes and a child channel is born on the breach side. The child computes its own pressure metric (B'), and when the opposing force inside the child reaches a user-defined threshold, the mother channel revives. This mechanism tracks regime transitions without discarding the prior range context. A dedicated label at the breach candle shows the child's B' value in real time.
🔸 Live and Closed display modes — "Live" updates tick by tick using the current bar's data. "Closed" anchors all calculations on the last confirmed bar, eliminating intra-bar noise for traders who prefer signal stability.
🔸 Data Window and alert-ready plots — Three invisible plots (Red %, Blue %, raw B) are exposed in the Data Window and available for TradingView's alert condition builder. Traders can create threshold, crossover, or crossing alerts on any of these values without writing Pine Script.
🔸 Full visual customisation — Every visual element (triangle fill colors, line colors, diamond size, text size, barometer width, barometer offset, gradient steps) is independently configurable through the indicator's settings panel.
🔶 Deep dive: the barometer
The barometer is a vertical gradient column displayed to the right of the last bar on the chart. Its purpose is to translate the abstract B value into a shape that the eye can read instantly: a column split into a red zone (seller pressure) on top and a blue zone (buyer pressure) on the bottom.
The column spans the full effective range — from rangeLow at the bottom to rangeHigh at the top. The split point between red and blue is not placed at the midpoint of the range. Instead, it is calculated directly from B:
yMid = rangeHigh − (B + 1) × range / 2
When B = 0 (balanced), yMid sits at the exact center of the range. When B approaches +1 (full seller dominance), yMid drops toward the range floor, making the red zone fill nearly the entire column. When B approaches −1 (full buyer dominance), yMid rises toward the range ceiling, and the blue zone dominates.
The gradient is rendered using a configurable number of boxes (default: 50). In the red zone, opacity is strongest near yMid and fades to near-transparent at rangeHigh. In the blue zone, opacity is strongest near yMid and fades toward rangeLow. This creates a natural "heat" effect: the most intense color always concentrates at the boundary where the two forces meet.
At the top and bottom of the column, percentage labels display the Red % and Blue % values. These are the same percentages available in the Data Window, presented here as a quick visual reference.
The barometer responds to the selected display mode. In "Live" mode, it updates on every tick using the current bar's B value. In "Closed" mode, it uses the B computed from the last confirmed bar, providing a stable reading that does not flicker with intra-bar price movement.
Barometer settings
🔸 Show barometer — Toggle the entire barometer on or off. Default: on.
🔸 Offset (bars right) — How far to the right of the last bar the column is placed. Default: 11. Increase this if the barometer overlaps with other right-margin elements.
🔸 Width (bars) — The horizontal thickness of the column, measured in bars. Default: 5.
🔸 Gradient steps — The number of boxes used to render the gradient. Higher values produce a smoother fade. Default: 50.
🔶 Deep dive: the prime triangle fan
The triangle fan is the indicator's signature visual element. It renders 25 filled triangles on the chart — one for each prime offset from 3 to 101 — fanning out from the current bar toward the left side of the lookback window. Upper triangles are shaded red (seller pressure) and lower triangles are shaded blue (buyer pressure), each with high transparency so the underlying candlesticks remain clearly visible.
Every triangle in the fan shares two of its three vertices with the current bar: the bar's high (for upper triangles) or the bar's low (for lower triangles), and the corresponding range boundary at that bar. The third vertex sits at the range boundary at the prime-offset bar. Because each prime offset is a different distance back in time, the triangles vary in width — the smallest is narrow and captures very short-term pressure, while the largest stretches across the full lookback and captures the broadest structural picture.
Reading the fan as a pressure map
The fan functions as a multi-scale pressure map. Each triangle edge represents a boundary where one side's territory begins. When price approaches a cluster of red triangle edges from below, it is entering a zone where seller pressure intensifies across multiple time horizons simultaneously. The denser the overlap of red edges at a given price level, the stronger the structural resistance at that level. The same logic applies in reverse for blue edges and buyer support.
This is visible in practice: candles that push into the red fan often stall or reverse at the triangle boundaries, while candles that drop into the blue fan tend to find support. The fan gives the trader a spatial sense of how much room each side has — a wide blue zone with thin red edges suggests buyers have structural space to move, and vice versa.
Color flipping during freeze
When the Freeze/Revival system is active and price moves beyond the frozen range boundary, the triangle colors on the breached side flip to reflect the new structural reality.
Consider a downward breach: price closes below the frozen rangeLow and continues falling. The lower triangles — which normally appear blue to represent buyer territory — switch to red. This signals that what was once the buyer's domain has been structurally penetrated; the geometry now measures selling pressure extending below the old floor. At the same time, the upper triangles remain red as they always are, and because the distance between the current price and the frozen rangeHigh has grown dramatically, the seller area expands. The visual result: the entire fan turns uniformly red, reflecting overwhelming seller dominance across every time horizon in the fan.
The mirror case works identically. During an upward breach, price closes above the frozen rangeHigh and continues rising. The upper triangles flip from red to blue, signaling that seller space has been penetrated from below. The lower triangles remain blue, and because the gap between the current price and the frozen rangeLow is now vast, buyer area dominates. The entire fan turns uniformly blue, reflecting overwhelming buyer dominance.
The color flip is automatic and requires no user intervention. It is driven entirely by the relationship between the current price and the frozen boundaries — when price returns inside the frozen range, colors revert to their normal assignment.
Diamond markers and prime labels
At each prime-offset bar, the indicator places diamond-shaped markers at both the range ceiling and the range floor. Above the ceiling diamond, the prime number itself is displayed as a label. These markers serve as a visual ruler: they show the trader exactly where each sampling point falls in time and make the non-periodic spacing of the primes immediately visible on the chart.
Fan settings
🔸 Show lower triangle lines / Show upper triangle lines — Toggle dashed outlines for each side. Default: off. When enabled, the outlines make individual triangle edges more distinct, which can be helpful when reading overlapping edges at specific price levels.
🔸 Lower / Upper line color — Stroke color for the dashed outlines.
🔸 Lower / Upper fill color — Fill color and transparency for the triangle bodies. Default: high transparency so candles remain readable.
🔸 Show vertical lines — Draws a vertical line at each prime-offset bar. Default: off.
🔸 Show prime labels — Displays the prime number and diamond at each offset. Default: on.
🔸 Diamond color / Diamond size — Visual styling for the diamond markers.
🔸 Label text size — Font size for the prime number labels.
🔸 Deep dive: Freeze / Revival
Markets do not stay inside ranges forever. When price breaks out, most range-based indicators simply reset and start a new range from scratch, discarding whatever structural context existed before the breakout. The Freeze/Revival system takes a different approach: it preserves the prior range as a frozen reference while simultaneously tracking the new regime that emerges beyond it.
How a freeze is triggered
A freeze occurs when a confirmed close — not a wick, not an intra-bar spike — breaches the effective range boundary. The indicator compares the previous bar's close against the range that existed one bar before it, so the breach signal is fully confirmed and cannot repaint. Once a breach is detected:
🔸 The mother channel freezes — its high and low are locked at the values they held just before the breach.
🔸 A child channel is born on the breach side. For an upward breach, the child's floor is the frozen rangeHigh and its ceiling expands with each new high. For a downward breach, the child's ceiling is the frozen rangeLow and its floor drops with each new low.
🔸 A snowflake icon (❄) appears on the range price labels, and the triangle colors flip as described in the section above.
The child channel and B'
While the mother channel is frozen, the child channel computes its own independent pressure metric called B'. B' uses the same ICS triangle formula as the mother's B, but measured against the child's own boundaries. This means B' tracks the buyer/seller balance exclusively inside the new regime — the territory beyond the old range.
A dedicated label appears at the breach candle showing the current B' value, converted to the percentage of the opposing force. For a downward breach, the label displays the buyer percentage inside the child; for an upward breach, it displays the seller percentage. This tells the trader how much counter-pressure is building inside the breakout zone.
B' as a structural overbought / oversold reading
When B' shows a very low opposing-force percentage shortly after a breach, the breakout side is structurally dominant — price has moved aggressively beyond the old range with minimal resistance. This condition is analogous to what traders call an overbought or oversold state, but derived from geometry rather than from momentum oscillators. The reading reflects the spatial imbalance between the two forces inside the child channel: one side occupies nearly all the geometric territory.
As time passes, if the opposing force gradually builds — the B' percentage climbs — it signals that the breakout is losing its structural one-sidedness. The market is beginning to rebalance inside the new territory. Watching B' evolve over successive bars gives the trader a real-time gauge of whether the breakout retains its structural conviction or is approaching exhaustion.
Revival: when does the freeze end?
The freeze lifts when the opposing force inside the child channel reaches a user-defined threshold (default: 50%). At that point, the indicator interprets this as the exhaustion of the breakout: the force that drove the breach is being met by equal or greater counter-pressure. The freeze is lifted, all freeze state is reset, and the mother channel resumes normal range tracking. The snowflake icons, B' label, and color flips are removed.
The revival threshold is configurable. A lower value makes the system more sensitive — it revives sooner, treating even moderate counter-pressure as a regime reset. A higher value makes it more patient — it waits for stronger opposition before releasing the freeze. The default represents balanced equilibrium: the freeze ends when the opposing side has matched the breach side.
Why this matters
The Freeze/Revival cycle gives the trader a structured way to observe regime transitions. Rather than watching a range silently reset after a breakout, the trader sees the old range preserved as context (frozen lines with ❄), the new regime measured in real time (B' at the breach candle with its overbought/oversold implication), and a clear signal when the transition is complete (revival). This makes it possible to distinguish between a genuine regime change and a brief spike that reverts — without relying on arbitrary time delays or fixed-bar re-entry rules.
🔸 Reading the indicator
This indicator does not generate buy or sell signals. It is a measurement tool that quantifies the geometric balance between buyer and seller pressure. How that measurement is incorporated into a trading decision is entirely up to the trader. The following observations describe what the indicator shows, not what the trader should do.
The barometer as a quick-glance gauge
The barometer provides the fastest reading. A column dominated by red indicates that seller pressure is structurally larger than buyer pressure across the lookback window. A column dominated by blue indicates the reverse. When the split point sits near the center, pressure is approximately balanced. Watching how the split point migrates over successive bars reveals whether the pressure balance is shifting gradually or remaining stable.
The fan as a spatial context layer
The triangle fan adds spatial depth to the barometer's single-number reading. While the barometer tells you the current balance, the fan shows you where that balance is concentrated in price space. Areas where multiple triangle edges converge represent zones of intensified pressure — structural resistance above (red edges) or structural support below (blue edges). When price trades inside a region with sparse triangle coverage, it has more structural room to move before encountering the next pressure boundary.
Freeze events as regime markers
When a freeze occurs, it marks a structural event: price has left the established range. The frozen lines (marked with ❄) preserve the old context, and B' at the breach candle provides a real-time measure of how one-sided the new regime is. A very low opposing-force reading in B' indicates a structurally extended condition — the breakout side has occupied nearly all geometric territory. As B' climbs toward the revival threshold, it indicates increasing counter-pressure. The moment of revival itself marks the point where the new regime's one-sidedness has been structurally neutralized.
Combining readings
The three visual layers — barometer, fan, and freeze state — work together. For example, a barometer showing strong seller dominance combined with a fan whose red edges are densely clustered near the current price suggests concentrated structural resistance. If a freeze is also active with a low B', the structural picture is one of strong directional conviction on the breach side. Conversely, a barometer near balance with widely spaced fan edges and no active freeze suggests a structurally neutral environment.
Data Window and alerts
The Red %, Blue %, and raw B values are available in TradingView's Data Window for any bar by hovering over it. These same values are exposed as alert-ready plots, meaning traders can set alerts directly from TradingView's alert builder — for example, triggering when Red % crosses above or below a chosen level, or when B crosses zero. No Pine Script knowledge is required to create these alerts.
🔸 Open-source structure and reusability
This script is published open-source under the Mozilla Public License 2.0. The full computation pipeline — the Yang-Zhang volatility estimator, the ICS coordinate transformation, the Shoelace area calculation, and the symmetric ratio that produces B — is readable, auditable, and reusable.
B is a bounded output: it always falls between −1 and +1, carries no unit, and is computed from normalized geometry. These properties make it suitable as an input for other scripts. Examples of how B can serve as input to further analysis include:
🔸 Plotting B as a standalone oscillator with its own zero line and structural extremes.
🔸 Applying moving averages of different periods to B and studying their crossovers as indicators of shifting pressure regimes.
🔸 Using B as a weighting coefficient to scale other measurements by the current geometric pressure balance.
🔸 Comparing B across timeframes, since the ICS normalization makes the metric structurally comparable regardless of the chart resolution.
🔸 Testing for divergences between B and price action.
🔸 Using B as a filter condition for entry or exit logic in other strategies.
The code is available for study and extension under MPL 2.0. Traders and developers who wish to build on this metric have full access to its derivation.
🔸 Settings reference
Range Lines
🔸 Lookback length — Number of historical bars used to compute the high/low range. Default: 101.
🔸 Line width — Pixel width of the horizontal range lines. Default: 1.
🔸 Display mode — "Live" updates tick by tick using the current bar. "Closed" anchors on the last confirmed bar, eliminating intra-bar noise. Default: Live.
ICS
🔸 ICS Window — Number of bars fed into the Yang-Zhang volatility estimator. Controls how much historical data shapes the normalization sigma. Default: 101.
Prime Verticals and Labels
🔸 Show vertical lines — Draws a vertical line at each prime-offset bar. Default: off.
🔸 Show prime labels — Displays the prime number and diamond marker at each offset. Default: on.
🔸 Vertical line color — Color for vertical lines at prime offsets.
🔸 Diamond color — Color of diamond markers and their labels.
🔸 Label text size — Font size for prime number labels, in points.
🔸 Diamond size — Size of the diamond-shaped markers, in points.
Prime Triangles
🔸 Show lower triangle lines — Toggle dashed outlines for lower (buyer) triangles. Default: off.
🔸 Show upper triangle lines — Toggle dashed outlines for upper (seller) triangles. Default: off.
🔸 Lower line color — Stroke color for lower triangle dashed outlines.
🔸 Upper line color — Stroke color for upper triangle dashed outlines.
🔸 Lower fill color — Fill color and transparency for lower (buyer) triangle bodies.
🔸 Upper fill color — Fill color and transparency for upper (seller) triangle bodies.
Barometer
🔸 Show barometer — Toggle the barometer column on or off. Default: on.
🔸 Offset (bars right) — Horizontal distance from the last bar to the barometer column. Default: 11.
🔸 Width (bars) — Horizontal thickness of the barometer column. Default: 5.
🔸 Gradient steps — Number of boxes used to render the gradient. Higher values produce a smoother fade. Default: 50.
Freeze and Revival
🔸 Revival threshold (B') — When the opposing force inside the child channel reaches this percentage, the freeze ends and the mother channel resumes. A lower value revives sooner; a higher value waits for stronger counter-pressure. Default: 50.
🔸 Disclaimer
This indicator is a technical analysis tool designed for educational and informational purposes. It measures the geometric balance between buyer and seller pressure using the methodology described above. It does not predict future price movements, does not guarantee any outcome, and does not constitute financial, investment, or trading advice.
The B metric, the barometer, the triangle fan, and the Freeze/Revival system are structural measurements derived from historical price data. Like all technical indicators, they reflect past and present conditions and carry inherent limitations. Market conditions can change rapidly, and no single measurement tool can account for all factors that influence price.
Traders should use this indicator as one component within a broader analytical framework, always in combination with their own research, risk management practices, and judgment. Past performance of any reading or pattern observed through this indicator is not indicative of future results.
Use this tool at your own risk. The author assumes no liability for any trading decisions made based on the information provided by this indicator. Indicator

Gann Fan v15 [Phases + Signals]Gann Fan v15 is a strategy inspired by the classic Gann Fan and Gann Angles methodology attributed to W.D. Gann. Gann’s original approach studied the relationship between price, time, geometry, and market angles to identify trend strength, diagonal support and resistance, and potential changes in market behavior.
Credit:
The base concept of the fan angles comes from the Gann Fan / Gann Angles method attributed to W.D. Gann. This script does not claim to reproduce Gann’s original work exactly. It is an independent strategy built around that historical concept, with additional logic for phase detection, signal confirmation, visual analysis, and risk management.
What makes this strategy different:
This script is not only a traditional Gann Fan drawing tool. A classic Gann Fan usually plots diagonal angle levels from a selected high or low. This strategy adds a complete decision framework on top of the Gann Fan concept.
The main differences are:
1. Automatic pivot detection
The script automatically detects recent pivot highs and pivot lows instead of requiring the user to manually anchor the fan.
2. ATR-normalized angle calculation
Instead of using only fixed visual chart angles, the script calculates movement angles using ATR normalization. This helps adapt the angle reading to the volatility of the current symbol.
3. Market phase classification
The script classifies the market into four phases based on the calculated angle:
ACCUM: weak angle or low momentum.
MODER: moderate directional movement.
EXPAN: stronger directional expansion.
ACCEL: extreme acceleration.
4. Visual phase background
The chart background changes according to the detected phase and direction. This helps the user quickly identify whether the market is in accumulation, moderate movement, expansion, or acceleration.
5. LONG and SHORT signal logic
The strategy generates LONG and SHORT signals using Gann-inspired angle behavior, swing direction, EMA confirmation, and candle confirmation depending on the selected entry mode.
6. Multiple entry modes
The user can choose between three signal modes:
Strict, Medium, and Easy.
Each mode changes how much confirmation is required before a signal appears.
7. Built-in risk management
The strategy includes configurable Stop Loss, Take Profit, optional Trailing Stop, and visual TP/SL guide lines.
8. Dashboard
A table shows the current swing direction, live angle, current phase, bullish fan angle, bearish fan angle, active mode, and phase thresholds.
How the strategy enters LONG:
A LONG signal appears when the market structure is bullish and the selected entry mode confirms that the bullish movement has enough strength.
Mode 1 - Strict:
A LONG entry requires the market phase to transition from ACCUM or MODER into EXPAN or ACCEL. The swing must be bullish, EMA 8 must be above EMA 21, and the candle must close bullish.
Mode 2 - Medium:
A LONG entry can appear when the current phase is MODER, EXPAN, or ACCEL. The swing must be bullish, EMA 8 must be above EMA 21, and the candle must close bullish.
Mode 3 - Easy:
A LONG entry can appear when the current angle is above the weak angle threshold, the swing is bullish, price closes above EMA 8, and the candle is bullish.
How the strategy enters SHORT:
A SHORT signal appears when the market structure is bearish and the selected entry mode confirms that the bearish movement has enough strength.
Mode 1 - Strict:
A SHORT entry requires the market phase to transition from ACCUM or MODER into EXPAN or ACCEL. The swing must be bearish, EMA 8 must be below EMA 21, and the candle must close bearish.
Mode 2 - Medium:
A SHORT entry can appear when the current phase is MODER, EXPAN, or ACCEL. The swing must be bearish, EMA 8 must be below EMA 21, and the candle must close bearish.
Mode 3 - Easy:
A SHORT entry can appear when the current angle is above the weak angle threshold, the swing is bearish, price closes below EMA 8, and the candle is bearish.
Risk management:
The strategy includes a configurable Stop Loss percentage and Take Profit percentage.
When Trailing Stop is enabled, the Take Profit level is used as the trail activation price.
The strategy also includes an optional open-profit protection feature that can close the position after a minimum open profit condition is reached.
TP and SL levels are displayed on the chart while a position is active.
Visual elements:
Dynamic bullish and bearish Gann Fan levels.
Phase-colored background.
EMA 8 and EMA 21.
LONG and SHORT labels.
Live angle label.
Dashboard with current market state.
TP and SL lines.
Important usage notes:
Gann Fan and angle-based analysis can be sensitive to chart scaling, timeframe, volatility, and market conditions.
This strategy should be tested on each symbol and timeframe before use.
The default parameters are only a starting point.
Users should adjust the angle thresholds, pivot periods, Stop Loss, Take Profit, and Trailing Stop according to their own testing.
Disclaimer:
This script is for educational and analytical purposes only.
It does not provide financial advice.
It does not guarantee profits.
Past performance does not guarantee future results.
Always use proper risk management. Strategy

Pine3D: A Native 3D Graphical Rendering EnginePine3D is a full 3D rendering engine for TradingView, powered by Pine Script™ v6.
Pine3D pushes forward the frontier of TradingView 3D rendering capabilities, providing a fully fledged graphical engine under an intuitive, chainable, object oriented API. Build meshes, transform them in world space, light them, cast shadows, project them through a perspective camera, and render the result directly on your chart, all without ever bothering about trigonometry synchronization or optimization.
The library brings forth a streamlined process for anyone that wishes to visualize data in 3D, without needing to know anything about the complex math that has previously gatekept such indicators. Pine3D does all the heavy lifting, including extreme optimization techniques designed for production ready indicators.
The entire API is chainable and tag addressable, so spawning a mesh, registering it, pointing the camera at it, and rendering the frame is a four line affair:
Mesh mybox = cube(40.0, color.orange).setTag("hero").rotateBy(0.0, 45.0, 0.0)
scene.add(mybox)
scene.lookAt("hero")
render(scene)
🔷 SURFACES: CONTOUR BAND RENDERING
Pine Script imposes a hard ceiling of 100 polylines and 500 lines per indicator . On the surface this looks fatal for dense 3D meshes: every triangle drawn naively burns one of those 100 slots, or two of the 500, and the budget evaporates within a few hundred faces.
The conventional escape hatch is strip stitching , tracing a polyline forward along one row of a grid and back along the next, packing a ribbon of quads into a single drawing slot. It buys a meaningful multiplier, but it pays for that multiplier with two structural constraints baked into the geometry itself:
One color per strip. A polyline carries a single stroke and fill color, so every cell along the ribbon must share the same shade. The moment you want per cell lighting, contour banding, or value driven gradients, every color change forces a new polyline and the budget collapses.
One contiguous ribbon per slot. Strips can only describe topologically connected runs of cells. Disjoint regions, holes, islands, and value clustered fragments scattered across the surface each demand their own polyline.
Pine3D breaks both constraints at once.
At the core of the engine sits an innovation that redefines the limits for visual fidelity: contour band rendering using degenerate bridge stitching . The technique quantizes a surface's elevation into colored bands, then collapses every cell that falls inside the same band, no matter where it sits on the screen , into one continuous, hole aware polyline path per band, threading invisible zero width bridges between disjoint islands so that a single polyline can carry thousands of polygon equivalent fragments scattered across the geometry.
The result:
A single polyline can render up to 2,000 disconnected triangle equivalents , spread across arbitrarily separated regions of the surface.
Theoretical ceiling of around 200,000 disconnected faces inside the 100 polyline budget, a regime that strip based stitching cannot enter at any color count above one.
A 40 x 40 heightmap (around 3,000 triangles) renders inside the budget with full per band contour coloring and room to spare. Stress harnesses have run 40 x 80 grids .
Each band's path is depth sorted and near plane culled, and cached between bars , so once geometry is built only the screen space projection runs per frame.
This algorithm enables scenes with extreme detail relative to the 100 polyline limit, and shifts the optimization focus from "drawing limits" to "CPU limits", which Pine3D natively handles with aggressive caching at every layer of the pipeline. The contour technique is currently integrated into the surface() function, with the same compression strategy generalizable to any mesh class and ultimately full scene rendering in future versions.
Non-uniform grids out of the box. surface() accepts optional axisX and axisZ arrays that override the default uniform spacing with custom column and row positions. This means logarithmic strike spacing on an option volatility surface, irregular timestamp spacing on a market depth heatmap, or any other non-evenly-sampled grid renders correctly without resampling the data first. The contour band engine, axis ticks, and gridBox cage all snap to the custom positions automatically.
A full contour surface is just a handful of lines; the damped ripple below builds once and never needs updating:
//@version=6
indicator("Pine3D - Contour Surface", overlay = false, max_polylines_count = 100, max_lines_count = 500, max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
var p3d.Scene scene = p3d.newScene()
var p3d.Mesh heatmap = na
if barstate.isfirst
// Damped cosine ripple
int N = 20
matrix data = matrix.new(N, N, 0.0)
for r = 0 to N - 1
for c = 0 to N - 1
float dx = c - (N - 1) / 2.0
float dz = r - (N - 1) / 2.0
float d = math.sqrt(dx * dx + dz * dz) * 0.7
data.set(r, c, math.cos(d) * math.exp(-d * 0.12) * 50.0)
heatmap := p3d.surface(data, 200.0, color.blue, color.red, 24)
.gridBox()
.gridLabels(color.white, "X", "Amplitude", "Z")
scene.add(heatmap)
scene.camera.orbit(35.0, 25.0, 380.0)
if barstate.islast
p3d.render(scene, lighting = true)
🔷 TRAIL3D: STREAMED OSCILLATOR PATHS
Trail3D is a first class streaming primitive built for visualizing two correlated time series as a 3D ribbon evolving through time. You give it a rolling buffer capacity and push (u, v) samples bar by bar; the primitive maintains the buffer, builds the ribbon geometry, and renders it inside a normalized bounding cube so the path always fits cleanly in view regardless of the underlying data range.
Under the hood, Trail3D is a coordinated bundle of polylines: one for the main ribbon, two for optional shadow projections onto the back wall and floor, and one for the wireframe cage. All four are depth sorted and occlusion clipped against the rest of the scene, and the primitive auto normalizes incoming samples against the rolling window's min/max so streaming data always fills the cube without manual scaling.
This enables a class of visualizations that would otherwise require dozens of polylines and manual buffer management: phase space portraits, Lissajous figures, oscillator pair correlations, attractor trajectories, and any "two indicators evolving together over time" study. The demo above shows a sine and cosine pair pushing samples each bar to trace a clean spiral inside the cage, the same pattern you would use to plot RSI vs MFI, momentum vs volatility, or any custom (u, v) signal pair.
A full streamed scene is a handful of lines:
//@version=6
indicator("Pine3D - Trail3D", overlay = false, max_polylines_count = 100, max_lines_count = 500, max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
var p3d.Scene scene = p3d.newScene()
var p3d.Trail3D trail = na
if barstate.isfirst
trail := p3d.trail3D(220.0, 200, color.yellow)
.cage(true)
.axisLabels("sin", "cos", color.white)
trail._uProj.col := #00ffff69
trail._vProj.col := #ff00ff71
scene.add(trail)
scene.camera.orbit(215.0, 20.0, 360.0)
float phase = bar_index * 0.15
float sinX = math.sin(phase) * 100.0
float cosY = math.cos(phase) * 100.0
if barstate.isconfirmed
trail.pushSample(sinX, cosY)
p3d.render(scene)
🔷 BARS3D: CATEGORICAL 3D BAR CHARTS
bars3D() turns any series of values into a fully lit, depth sorted 3D bar chart in a single call. Each bar is height mapped to its value, color graded between a low and high color, and packed into one combined mesh with per bar depth grouping so individual bars sort correctly even inside the merged geometry. The companion updateBars() mutator refreshes heights, colors, and labels in place every bar without rebuilding geometry, making it suitable for live rankings, rolling windows, and animated comparisons.
The chainable barLabels(catNames, valNames) helper attaches category labels at the base of each bar and value labels at the top, both depth sorted with the rest of the scene. Category labels are set once at build time, while value labels can be passed to updateBars(values, valLabels = ...) each frame to reflect live data. Combined with wireGrid() for the floor and a contour surface() in the background, bars3D() becomes the centerpiece of dashboards comparing assets, sectors, timeframes, or any categorical metric.
Negative values are handled automatically: bars below zero extrude downward from the base plane with reversed face winding, so signed series like PnL, delta, or momentum histograms render correctly without any extra setup.
A complete labeled bar chart is just a few lines:
//@version=6
indicator("Pine3D - Bars3D", overlay = false, max_polylines_count = 100, max_lines_count = 500, max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
var p3d.Scene scene = p3d.newScene()
var p3d.Mesh bars = na
array values = array.from(volume - volume , volume - volume , volume - volume , volume - volume , volume - volume , volume - volume )
array names = array.from("ΔV0", "ΔV-1", "ΔV-2", "ΔV-3", "ΔV-4", "ΔV-5")
if barstate.isfirst
bars := p3d.bars3D(values, 30.0, 30.0, 10.0, color.blue, color.red, 200.0)
.barLabels(names)
scene.add(bars)
p3d.wireGrid(scene, 300.0, 300.0, 6, 6, color.new(color.gray, 80))
scene.camera.orbit(215.0, 25.0, 360.0)
if barstate.islast
bars.updateBars(values)
p3d.render(scene, lighting = true)
Omitting valLabels in updateBars() tells the engine to auto format each numeric value via str.tostring() . Pass valLabels only when you need custom strings.
🔷 SCATTER CLOUDS: POINTS IN 3D SPACE
Pine3D treats scatter clouds as a first class use case without needing a dedicated scatter API. Because Label3D is the primitive and scene.add(array) is a single batch operation, you can scatter up to 500 points anywhere in 3D space, each with independent color, symbol, size, and tooltip , and have them depth sorted and occlusion clipped against the rest of the scene automatically.
Each point is a fully addressable Label3D with mutable fields. You can change position , textColor , bgColor , labelStyle (any label.style_* glyph including circles, squares, diamonds, triangles, crosses, arrows, flags), labelSize (any size.* preset), and text per point per bar. The renderer reads these mutations every frame, so animation is just direct field assignment.
This unlocks a wide class of visualizations: clustered data scatter, K means visualizations, particle systems, parametric surfaces sampled as point clouds, gradient colored attractors, multi class classification overlays, and structured curves like the demo above. The double helix demo plots two intertwined parametric strands as ~500 points with alternating colors and per point sizing, all inside the standard scene.add(array) pipeline.
The pattern is straightforward: build the array once in barstate.isfirst , add it to the scene, then mutate point fields per bar to animate.
//@version=6
indicator("Pine3D - Scatter Cloud", overlay = false, max_polylines_count = 100, max_lines_count = 500, max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
var p3d.Scene scene = p3d.newScene()
var array points = array.new()
if barstate.isfirst
for i = 0 to 499
p3d.Vec3 pos = p3d.vec3(0.0, 0.0, 0.0)
points.push(p3d.Label3D.new(position = pos, txt = "•"))
scene.add(points)
scene.camera.orbit(35.0, 20.0, 400.0)
if barstate.islast
for i = 0 to points.size() - 1
float t = i * 0.05 + bar_index * 0.01
p3d.Label3D pt = points.get(i)
pt.position := p3d.vec3(80.0 * math.cos(t), i * 0.4 - 100.0, 80.0 * math.sin(t))
pt.textColor := i % 2 == 0 ? color.aqua : color.fuchsia
p3d.render(scene)
----------------------------------------------------------------------------------------------------------------
🔷 TWO LAYER ARCHITECTURE
Pine3D ships as a clean, two layer library:
🔸 Layer 1 - DIY API. First principle building blocks ( Vec3 , Mesh , Camera , Light , Scene , plus world space overlay primitives) for total creative control. Author your own geometry, camera behavior, lighting setup, and scene graph from scratch.
🔸 Layer 2 - High Level Helpers. Production ready wrappers like surface() , bars3D() , trail3D() , updateBars() , updateSurface() , sphere() , torus() , cylinder() , and wireGrid() , plus chainable contour helpers gridBox() and gridLabels() that wrap the primitives into a few lines of code. Scatter clouds use the standard Label3D primitive directly.
The object model is chainable and scene oriented, so complex setups still read cleanly.
🔷 FEATURE LIST
Contour Surface Rendering - The most powerful 3D surface engine ever released for Pine Script. Render tens of thousands of polygon equivalent faces using a single polyline per contour band, delivering smooth, continuous terrain with natural ridges and valleys.
Adaptive Rail Sharing - Solid meshes drawn with the default linefill backend reuse one edge line between adjacent coplanar faces, averaging roughly 1.6 lines per face instead of the naive two, pushing practical mesh capacity up to ~360 faces depending on topology.
Interior Face Culling on Merge - mergeMeshes(meshes, removeInterior = true) detects coincident faces with opposing normals and strips them, so voxel style scenes (stacked cubes, block walls, lattice geometry) ship only their exterior shell and spend no budget on hidden interior faces.
True Perspective Camera System - Full 3D camera with position, target, fov, and orbit() controls. Supports cinematic camera movement, lookAt by mesh tag, and realistic depth.
Real Time Lighting and Shadows - Directional and point lights with configurable ambient, shadow strength, self shadowing, and a spatial grid acceleration structure for fast shadow queries.
High Performance Update System - updateSurface() and updateBars() let you animate massive datasets bar by bar without rebuilding geometry, keeping CPU usage minimal.
Rich Primitive Library - Cubes, cuboids, spheres, cylinders, tori, pyramids, planes, discs, circles, custom meshes, and the groundbreaking bars3D() with automatic labels.
Streamed Trail Primitive - trail3D() maintains a rolling buffer of (u, v) samples and renders them as a 3D ribbon inside a bounding cube, with optional projections onto the back wall and floor and a wireframe cage.
Depth Sorted Overlays - 3D labels, lines, polylines, wire grids, and trails, all correctly occluded and painter sorted against the rest of the scene.
Professional Contour Helpers - gridBox() and gridLabels() automatically add clean bounding boxes and axis titles, ticks, and series names that refresh on every updateSurface() call.
Tag Based Scene Graph - Every Mesh , Label3D , Line3D , and Polyline3D can carry a string tag. Scene exposes getMesh() , getLabel() , getLine() , getPolyline() , lookAt() , and remove() by tag, turning your scene into a lookup by name graph instead of an index juggling exercise.
Chainable, Intuitive API - Everything is designed for maximum readability and speed of development. Build complex scenes in just a few lines.
Production Ready Optimizations - World vertex caching, view projection caching, face preprocessing cache, shadow grid cache, and contour geometry cache, all managed automatically.
----------------------------------------------------------------------------------------------------------------
🔷 THE RENDERER
Every frame is produced by a single call to render(scene, ...) . The renderer runs the full pipeline: world transform, camera transform, back face culling, occlusion culling, depth sort, directional or point lighting with shadows, and perspective projection.
⚠ render() clears the entire chart drawing pool at the start of every call - every polyline , line , label , and linefill on the chart is deleted before Pine3D redraws, not just the ones it created. If you mix Pine3D with manual label.new() , line.new() , or similar calls, those drawings must be emitted after render() or they will be wiped every frame.
🔸 Setup Requirements. Pine3D consumes polylines, lines, and labels simultaneously, so your indicator() declaration must raise all three budgets, and the library must be imported under an alias:
indicator("My 3D Scene", overlay = false,
max_polylines_count = 100,
max_lines_count = 500,
max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
🔸 render() parameters.
maxFaces (int, default 100). Hard cap on solid faces drawn per frame. Contour bands, wireframe edges, labels, lines, and overlay polylines are not counted against this cap, and are bounded only by TradingView's global 100 polyline / 500 line / 500 label budgets.
culling (bool, default true). Enable back face culling.
lighting (bool, default false). Enable diffuse shading. Reads scene.light if set; otherwise falls back to the render() args.
lightDir (Vec3). Overrides scene.light.direction when provided. Points toward the light.
ambient (float, default 0.3). Minimum brightness for shadowed faces (0.0-1.0).
wireframe (bool, default false). Force outline only output for the entire scene.
occlusion (bool, default true). Sparse raster pass that drops hidden faces before drawing. Major perf win on dense scenes.
occlusionRaster (int, default 768). Raster resolution of the occlusion buffer. Lower = faster but coarser; higher = stricter hidden face rejection.
Explicit render() args always win over scene.light , which makes render() the right place for ad hoc, per frame lighting tweaks.
----------------------------------------------------------------------------------------------------------------
🔷 MESH DRAWING MODES
Two independent axes control how a mesh appears on the chart:
🔸 Style (via mesh.setStyle(...) ) - what gets drawn:
"solid" . Filled faces. Default.
"wireframe" . All edges, no fill. Shows interior geometry.
"wireframe_front" . Only front facing edges. Cleaner silhouette for convex meshes.
🔸 Draw Mode (via mesh.drawMode ) - which TradingView primitive carries the solid faces:
"linefill" (default). Uses the line and linefill budgets. An adaptive rail sharing optimization reuses one edge line between adjacent coplanar faces, pushing practical capacity up to ~360 faces per mesh depending on topology. Supports in place updates via updateSurface() and updateBars() . Rails are drawn transparent, so solid faces in this mode have no visible outline - use a wireframe style or "poly" drawMode if you need stroked edges. Recommended for all new code.
"poly" . Legacy polyline backend. Capacity ~100 faces, no in place updates, but renders the face outline using mesh.lineStyle and mesh.lineWidth . Use only when you need styled solid face outlines.
Wireframe styles always render with line primitives regardless of drawMode. Stroke width and style on edges (and on poly mode face outlines) come from mesh.lineWidth and mesh.lineStyle , which you mutate by direct field assignment.
----------------------------------------------------------------------------------------------------------------
🔷 QUICK START
The best practice lifecycle is simple:
Create one persistent Scene with newScene() .
Build meshes and helper overlays once in barstate.isfirst .
On later bars, mutate objects in place with transforms or helper mutators like updateBars() and updateSurface() .
Call render(scene, ...) once per frame. It automatically clears the previous chart drawings.
A complete, lit, animated 3D scene is still a handful of lines:
//@version=6
indicator("My First 3D Scene", overlay = false, max_polylines_count = 100, max_lines_count = 500, max_labels_count = 500)
import Alien_Algorithms/Pine3D/1 as p3d
var p3d.Scene scene = p3d.newScene()
var p3d.Mesh sun = na
if barstate.isfirst
scene.setLightDir(1.0, -1.0, 0.5).setAmbient(0.3)
sun := p3d.sphere(50.0, 16, 12, color.orange).setTag("sun")
scene.add(sun)
p3d.wireGrid(scene, 300.0, 300.0, 6, 6, color.new(color.gray, 80))
scene.camera.orbit(35.0, 25.0, 220.0)
if barstate.islast
sun.rotateBy(0.0, 1.5, 0.0)
p3d.render(scene, lighting = true)
----------------------------------------------------------------------------------------------------------------
🔷 RECOMMENDED USAGE PATTERN
Use your Scene and major meshes in var .
Build geometry once in barstate.isfirst .
Use updateSurface() and updateBars() on later bars instead of rebuilding meshes.
Use scene level helpers like wireGrid() when you want overlays added immediately.
Use trail3D() when you want a streamed oscillator style path with built in wall projections and cage geometry.
For scatter clouds, build an array once, hand it to scene.add(pts) , then mutate pt.position , pt.textColor , etc. each bar to animate.
Use mesh level gridBox() and gridLabels() (contour) and barLabels() (bars) to attach overlays to the mesh setup chain. They are drained into the scene by scene.add(mesh) .
🔷 CONSIDERATIONS
scene.clear() vs render(). scene.clear() removes objects from the scene graph (meshes, labels, lines, polylines). render() only clears the previous frame's TradingView drawings and redraws from the current scene graph. You almost never need scene.clear() in the build once and update pattern.
Global scope series for updateSurface() / updateBars(). If your data uses Pine's history operator ( ) or calls functions like ta.rsi() , ta.atr() , request.security() , those must be declared at global scope so Pine tracks their bar by bar history. Calling them inside barstate.islast produces inconsistent results or compiler errors.
gridLabels() tick values auto refresh. When you call updateSurface() , any tick value labels created by gridLabels() are automatically updated to reflect the new data range. Axis titles and positions stay constant. You don't need to rebuild them.
barLabels() value labels via updateBars(). Create category labels once with mesh.barLabels(catNames) at build time, then pass valLabels to updateBars() on each frame. Value labels are refreshed automatically. Don't call barLabels() again.
Lighting convenience methods are chainable. scene.setLightDir() , setLightPos() , setLightMode() , setAmbient() , setShadowStrength() , and showLightSource() all return Scene and can be chained: scene.setLightMode("point").setLightPos(0, 200, 150).setAmbient(0.25) .
Mesh transforms return Mesh. moveTo() , moveBy() , rotateTo() , rotateBy() , scaleTo() , scaleUniform() , setTag() , setStyle() , setColor() , show() , hide() all return Mesh for chaining: mesh.moveTo(0, -20, 0).rotateTo(0, 45, 0).setStyle("solid") .
Degrees vs radians. rotateTo() and rotateBy() on Mesh expect degrees. The low level Vec3.rotateX/Y/Z() methods expect radians.
scene.lookAt() is tag only. scene.lookAt(t) accepts a string tag and points the camera at that mesh. To aim the camera at an arbitrary Vec3 , call scene.camera.lookAt(vec) directly.
remove(tag) removes one object. The search order is meshes, then labels, then lines, then polylines, and the first hit wins. Avoid reusing tags across primitive types if you intend to delete by tag.
Shadow grid acceleration is directional light only. The spatial shadow grid is only built when lightMode == "directional" . Point lights fall back to a linear O(M) scan, so heavy shadow scenes are fastest in directional mode.
guiShift and yOffset. scene.guiShift and scene.yOffset position the 3D viewport on the chart without consuming historical bar slots. Increase guiShift to push the scene rightward into future bar space; adjust yOffset to slide it vertically in price units.
bar_time projection. All chart drawings are emitted with xloc.bar_time , so the scene can sit arbitrarily far left or right of bar_index without forcing Pine to extend its history buffer. This is what keeps the engine stable on long charts and future projected scenes.
barLabels() without values. When you call mesh.barLabels(catNames) and omit value labels, every later updateBars(values) auto formats the numeric values via str.tostring() . Pass valLabels only when you need custom strings.
Direct mesh.vertices mutation requires invalidateCache(). Transform mutators ( moveTo , rotateBy , scaleTo , etc.) invalidate the world vertex cache on their own. Only raw index writes like mesh.vertices.set(i, newVec) need a manual mesh.invalidateCache() call to force re-projection. Skipping it will make the renderer draw stale geometry.
Drawing budgets fail silently. If a scene emits more than 100 polylines, 500 lines, or 500 labels in a single frame, TradingView silently drops the overflow without raising a runtime error. Missing geometry almost always means a budget overrun - lower maxFaces , drop a contour level, or simplify overlay primitives to bring the frame back inside the caps.
render() deletes non Pine3D drawings too. Every render() call clears polyline.all , line.all , label.all , and linefill.all before redrawing. Any manual label.new() , line.new() , etc. issued before render() in the same frame will be wiped. Issue custom drawings after the render call if you need them to persist.
mergeMeshes() preserves depth grouping. When every source mesh passed into mergeMeshes() has the same vertex and face count (e.g. identical primitives in a voxel grid), the merged mesh auto derives depth group boundaries so the combined geometry still sorts correctly per original instance. Mixing primitives with different topologies disables the grouping.
CPU timeouts: knobs to turn. Pine Script enforces a per bar execution budget, and dense scenes can trip it before the drawing budget ever does. If a scene compiles but times out at runtime, reach for these levers in order: lower occlusionRaster (e.g. 768 -> 384) for the biggest single perf win, reduce maxFaces to cap the solid face pool, drop levels on contour surfaces, simplify sphere/torus segment counts, and gate heavy work behind barstate.islast so history bars only build geometry rather than render it.
----------------------------------------------------------------------------------------------------------------
🔷 MORE EXAMPLES
The following scenes were all built entirely in Pine Script™ v6 using Pine3D as the rendering layer. They exist to demonstrate that the library is a real engine capable of complex, production grade visualizations.
🔸 4D Hypercube (Tesseract). A rotating tesseract, projected from 4D to 3D to 2D in real time using a custom 4D rotation matrix layered on top of Pine3D's standard projection pipeline.
🔸 Solar System. Following the publication of my 3D Solar System back in 2024, which introduced new graphical rendering concepts into Pine Script, we have seen a wave of various interpretations of the underlying vector classes, ranging from tutorials to niche specific integrations using hardcoded math. It became clear that a unified architecture was needed, one that would lower the barrier to entry while simultaneously handling the optimization process, which is both complex and error prone to do manually.
That architecture is what Pine3D delivers. Below is a re-creation of the classic 3D Solar System rebuilt entirely on top of the library. It uses a fraction of the original code , renders roughly 5x faster , and adds real lighting cast directly from the Sun , all while consuming only a third of the available drawing budget thanks to the occlusion and culling mechanisms Pine3D handles out of the box.
----------------------------------------------------------------------------------------------------------------
🔷 API REFERENCE
🔸 Top Level Entry Points. newScene() creates a ready to use Scene with a default camera and light. render(scene, ...) draws the current frame and auto clears the previous frame's chart drawings; see the Renderer section above for the full parameter list. vec3(x, y, z) creates a Vec3. colorBrightness() is an exported color utility helper.
🔸 Mesh Factories.
Primitives - cube() , cuboid() , pyramid() , plane() , sphere() , cylinder() , torus() , grid() , disc() , circle() for ready made geometry.
customMesh(verts, faces) - Low level escape hatch for authoring your own topology.
mergeMeshes(meshes, tag, removeInterior) - Bakes transforms and combines many meshes into one. With removeInterior = true , coincident faces with opposing normals (e.g. shared walls between adjacent cubes in a grid) are culled so only the exterior shell survives, a major optimization for dense voxel style scenes.
surface(heights, size, lowCol, highCol, levels, axisX, axisZ) - Creates a contour surface mesh.
bars3D(values, barWidth, barDepth, spacing, lowCol, highCol, maxHeight) - Creates a combined 3D bar chart mesh; add labels with the chainable barLabels(names, values) method.
🔸 UDT Constructors. Overlay primitives and face descriptors are plain UDTs. Because these types have many fields, always instantiate them with named arguments rather than positional, e.g. Label3D.new(position = pos, txt = "•") :
Face - fields: vi (array of vertex indices into the parent mesh), col . Used when authoring customMesh() topology; every face must have at least 3 indices and should be planar.
Label3D - fields: position , txt , textColor , bgColor , labelStyle , labelSize , fontFamily , tooltip , visible , tag . Only position is required.
Line3D - fields: start , end , col , width , visible , tag , lineStyle .
Polyline3D - fields: points , col , fillColor , width , closed , visible , tag , lineStyle .
Vec3.new(x, y, z) or the vec3(x, y, z) shorthand.
🔸 Trail Primitive. trail3D(size, capacity, trailCol, minSamples) creates a streamed Trail3D primitive with a main trail, two projection polylines, and a cage polyline. capacity is internally clamped to 300 samples to keep the rolling buffer inside Pine's execution budget; passing a larger value silently resolves to 300. minSamples (default 60) is the sample count at which the cage reaches its full cube width: below that the cage stays cube shaped and samples stretch across it; above that the cage grows rightward at a fixed step until capacity is hit. scene.add(trail) registers the sub primitives into the scene. Trail3D methods: pushSample() , axisLabels() , cage() , moveTo() , show() , hide() .
🔸 Mesh Methods.
Transform - moveTo() , moveBy() , rotateTo() , rotateBy() , scaleTo() , scaleUniform() .
Appearance - setColor() , setFaceColor() , setStyle() , show() , hide() , setTag() .
Stroke styling (direct) - mesh.lineWidth := 3 and mesh.lineStyle := line.style_dashed control width and style of every visible mesh edge in wireframe modes and the outline of solid faces in drawMode = "poly" .
Shadow opt out (direct) - mesh.castShadow := false excludes the mesh from shadow casting while still receiving light. Useful for ghost overlays, debug geometry, or semi transparent meshes you do not want occluding the scene.
Lifecycle - clone() , faceCount() , invalidateCache() .
Data mutation - updateSurface() and updateBars() refresh persistent meshes in place. updateBars() refreshes any bar label positions automatically; pass catLabels / valLabels to also update the text.
Contour helpers - gridBox() and gridLabels() queue overlays on the mesh and hand them to the scene when you call scene.add(mesh) .
Bar helpers - barLabels() is chainable on a bars3D() mesh and queues its category and value labels for the next scene.add(mesh) .
Note: rotateTo() and rotateBy() expect degrees. The low level Vec3.rotateX/Y/Z() methods work in radians.
🔸 Scene Methods.
Lighting - setLightDir() , setLightPos() , setLightMode() , setAmbient() , setShadowStrength() , showLightSource() .
Scene graph - add(mesh) , add(label) , add(array) , add(line) , add(polyline) , add(trail) , remove(index) , remove(tag) , clear() .
Lookup and navigation - getMesh() , getLabel() , getLine() , getPolyline() , lookAt() , totalFaces() .
Cache control - invalidateLightCache() after mutating light direction or scene bounds externally; invalidateAllCaches() to also invalidate every mesh's world vertex cache (use after directly mutating mesh.vertices ).
Note: scene.clear() clears the scene graph itself. render() only clears the previous frame's TradingView drawings.
🔸 Camera Methods. setPosition(x, y, z) moves the camera. lookAt(x, y, z) / lookAt(vec3) points at a world space target. orbit(angleX, angleY, distance) does a spherical orbit around the current target. setFov(val) sets the perspective scale factor. Camera fields ( position , target , fov ) are also directly mutable via assignment when you need to tune them outside the provided setters, e.g. scene.camera.fov := 1200.0 .
🔸 Light Field Mutation. In addition to the scene level convenience setters, every field on scene.light is directly mutable for fine grained tuning: scene.light.selfShadow := true enables self shadowing, scene.light.shadowBias := 0.2 adjusts the shadow acne offset, scene.light.shadowStrength and scene.light.ambient are also exposed. Mutate them after newScene() or between frames; the renderer reads them every call.
🔸 Vec3 Methods. Core math: add() , sub() , scale() , negate() , dot() , cross() , length() , normalize() , distanceTo() , lerp() . Rotation and helpers: rotateX() , rotateY() , rotateZ() , copy() , toString() .
🔸 Overlay Primitive Methods.
Label3D - moveTo() , moveBy() , setText() , setTextColor() , setTooltip() , show() , hide() , setTag() .
Line3D - setStart() , setEnd() , setPoints() , setColor() , show() , hide() , setTag() .
Polyline3D - setColor() , show() , hide() , setTag() .
Every UDT field is mutable via direct assignment for properties without a chainable setter:
Label3D - bgColor , labelStyle (label.style_*), labelSize (size.*), fontFamily (font.family_*), visible .
Line3D - width , lineStyle (line.style_solid / _dashed / _dotted / _arrow_left / _arrow_right / _arrow_both), visible .
Polyline3D - width , lineStyle (line.style_solid / _dashed / _dotted only; arrow styles are not supported by TradingView's polyline primitive), fillColor , closed , visible .
Mutations are read per frame by the renderer, so they animate freely.
🔸 High Level Scene Helpers. wireGrid(scene, w, d, divX, divZ, col) adds a depth sorted ground grid. scene.add(array) adds a batch of labels in one call - the idiomatic way to push a scatter cloud into the scene.
🔸 Mesh Level Chainable Overlays. mesh.barLabels(names, values, ...) adds category and value labels on a bars3D() mesh. mesh.gridBox(col, divs) adds a wireframe bounding box cage on a surface() mesh. mesh.gridLabels(col, xName, yName, zName, ticks, fmt) adds axis titles and tick value labels on a surface() mesh; tick values auto refresh on updateSurface() . All three are queued on the mesh and drained into the scene by scene.add(mesh) .
----------------------------------------------------------------------------------------------------------------
This work is licensed under (CC BY-NC-SA 4.0) , meaning usage is free for non-commercial purposes given that Alien_Algorithms is credited in the description for the underlying software. For commercial use licensing, contact Alien_Algorithms
Library

HeikinAshiTrendUtilities
Library HeikinAshiTrendUtilities
This library contains reusable Heikin Ashi helpers for building Pine scripts that use Heikin Ashi as more than a candle style.
It centralizes the Heikin Ashi foundation, HA-based oscillator engines, streak and confirmed-trend logic, Pressure Meter helpers, max-move scanning, Fib Backbone structure helpers, and Primary Trend helpers so those parts do not need to be rewritten across multiple scripts.
Everything on the example chart is materially driven by the library, whether through the Heikin Ashi calculations themselves, the HA-based oscillator and pressure engine, the predictive close logic, the smoothed HA overlay, the Fib Backbone context window, or the structure geometry used to project key analytical visuals.
How to use
Import the library near the top of your script in global scope, alongside any other imports, before you start calling its helpers.
Typical placement:
• //@version=6
• indicator(...) or strategy(...)
• import MYNAMEISBRANDON/HeikinAshiTrendUtilities/1 as haUtils
For more information on libraries and incorporating them into your scripts, see the Libraries section of the Pine Script User Manual: www.tradingview.com
➖Heikin Ashi Core Helpers➖
These helpers handle the basic building blocks of Heikin Ashi. They let a script create standard HA candles, estimate the price needed to flip the current HA candle, and generate a smoothed HA version for a cleaner trend view. In other words, this region provides the core HA math used to build the rest of the library’s trend, engine, and structure tools.
heikinAshi(openValue, closeValue, highValue, lowValue, haOpenPrev, haClosePrev)
Builds one Heikin Ashi candle from real OHLC and prior HA state
Parameters:
openValue (float): Real open
closeValue (float): Real close
highValue (float): Real high
lowValue (float): Real low
haOpenPrev (float): Prior Heikin Ashi open
haClosePrev (float): Prior Heikin Ashi close
Returns: HA open, HA close, HA high, HA low, is HA up, is HA down
haPredictClose(haOpen, openValue, highValue, lowValue)
Estimates the real close price needed to flip the current HA candle
Parameters:
haOpen (float): Current Heikin Ashi open
openValue (float): Real open
highValue (float): Real high
lowValue (float): Real low
Returns: Predicted real close needed to flip the HA candle
smoothedHeikinAshi(openValue, highValue, lowValue, closeValue, len1, len2)
Builds double-smoothed Heikin Ashi values from real OHLC inputs
Parameters:
openValue (float): Real open
highValue (float): Real high
lowValue (float): Real low
closeValue (float): Real close
len1 (simple int): First EMA smoothing length applied to real OHLC
len2 (simple int): Second EMA smoothing length applied to HA OHLC
Returns: Smoothed HA open, smoothed HA high, smoothed HA low, smoothed HA close, is smoothed HA up, is smoothed HA down
➖HA Oscillator Foundation Helpers➖
These helpers turn raw Heikin Ashi candle movement into a usable oscillator foundation. They measure the HA candle’s bullish or bearish range, normalize that movement so it can be compared more consistently across bars, and build upper/lower guide levels that help a script judge when that oscillator is stretching into stronger trend pressure. In other words, this region creates the base signal that the HA Blend, HA Range Base, color engine, and Pressure Meter can build from.
haSignedRangePct(haHigh, haLow, haClose, haIsBull, haIsBear)
Returns the signed HA range-percent foundation used by the oscillator engine
Parameters:
haHigh (float): Heikin Ashi high
haLow (float): Heikin Ashi low
haClose (float): Heikin Ashi close
haIsBull (bool): True when the current HA candle is bullish
haIsBear (bool): True when the current HA candle is bearish
Returns: Signed HA range-percent foundation
haPreparedOscSource(signedSrc, normLen, useClamp, clampRange)
Returns the normalized / optionally clamped HA oscillator source
Parameters:
signedSrc (float): Signed HA foundation
normLen (simple int): Normalization lookback length
useClamp (simple bool): Whether the normalized result should be clamped
clampRange (float): Absolute clamp boundary when useClamp is true
Returns: Prepared HA oscillator source
haOscGuides(src, lookback, guideFactor)
Returns upper and lower threshold guides from an oscillator series
Parameters:
src (float): Oscillator series
lookback (simple int): Guide lookback window
guideFactor (float): Scaling factor applied to the highest/lowest values
Returns: Upper guide, lower guide
➖HA Blend Engine Helpers➖
These helpers take the prepared HA oscillator source and turn it into a smoother trend engine by blending multiple EMA pairs together. They let the script choose a faster, more balanced, or slower blend profile, then optionally smooth that final output one more time. In other words, this region builds the more layered, trend-following version of the HA oscillator engine.
haBlendPairStackText(pairSet)
Returns the active EMA pair-stack text for the selected HA Blend pair set
Parameters:
pairSet (simple string): Pair-set label. Expected values: "Fast", "Balanced", or "Slow"
Returns: Pair-stack text
haBlendEngineCore(src, pairSet)
Returns the raw HA Blend engine core before final smoothing
Parameters:
src (float): Prepared HA signed source used by the blend engine
pairSet (simple string): Pair-set label. Expected values: "Fast", "Balanced", or "Slow"
Returns: Raw HA Blend engine core
haBlendEngine(src, pairSet, useFinalSmooth, finalSmoothLen, finalSmoothType)
Returns the final HA Blend engine with optional final smoothing
Parameters:
src (float): Prepared HA signed source used by the blend engine
pairSet (simple string): Pair-set label. Expected values: "Fast", "Balanced", or "Slow"
useFinalSmooth (simple bool): Whether final smoothing should be applied
finalSmoothLen (simple int): Final smoothing length
finalSmoothType (simple string): Final smoothing type. Expected values: "EMA" or "SMA"
Returns: Final HA Blend engine
➖HA Range Base Engine Helpers➖
These helpers take the prepared HA oscillator source and smooth it in a more direct way than the Blend engine. Instead of combining multiple EMA pairs, they use one selected smoothing length and MA type to create a cleaner base trend signal, with the option to smooth that result one more time. In other words, this region builds the simpler, more straightforward version of the HA oscillator engine.
haRangeEngineCore(src, rangeLen, rangeMaType)
Returns the raw HA Range Base engine core before final smoothing
Parameters:
src (float): Prepared HA signed source used by the Range Base engine
rangeLen (simple int): Core smoothing length used by the Range Base engine
rangeMaType (simple string): Core smoothing type. Expected values: "EMA" or "SMA"
Returns: Raw HA Range Base engine core
haRangeEngine(src, rangeLen, rangeMaType, useFinalSmooth, finalSmoothLen, finalSmoothType)
Returns the final HA Range Base engine with optional final smoothing
Parameters:
src (float): Prepared HA signed source used by the Range Base engine
rangeLen (simple int): Core smoothing length used by the Range Base engine
rangeMaType (simple string): Core smoothing type. Expected values: "EMA" or "SMA"
useFinalSmooth (simple bool): Whether final smoothing should be applied
finalSmoothLen (simple int): Final smoothing length
finalSmoothType (simple string): Final smoothing type. Expected values: "EMA" or "SMA"
Returns: Final HA Range Base engine
➖HA Threshold Color Helpers➖
This helper takes centered oscillator behavior and turns it into a usable visual color state. It helps a script decide when the HA-based oscillator is rising or falling above or below its guide levels so candles, rows, or other visuals can reflect stronger or weaker trend pressure.
haThresholdStateColor(src, upperGuide, lowerGuide, aboveUpperRiseColor, aboveZeroRiseColor, aboveZeroFallColor, belowZeroFallColor, belowLowerFallColor, belowZeroRiseColor)
Resolves a visual color from centered-oscillator threshold state
Parameters:
src (float): Source series
upperGuide (float): Upper threshold guide
lowerGuide (float): Lower threshold guide
aboveUpperRiseColor (color): Color used when src is above the upper guide and rising
aboveZeroRiseColor (color): Color used when src is above zero and rising
aboveZeroFallColor (color): Color used when src is above zero and falling
belowZeroFallColor (color): Color used when src is below zero and falling
belowLowerFallColor (color): Color used when src is below the lower guide and falling
belowZeroRiseColor (color): Color used when src is below zero and rising
Returns: Resolved visual color
➖HA Structure Scan Helpers➖
This helper scans a chosen lookback window and finds the strongest completed move inside it. It compares bullish and bearish candidates in the same scan, then returns whichever move was stronger along with the start and end anchors. In other words, this region gives a script a reusable way to locate the dominant move that can later be used for Fib Backbone structure, Primary Max Move logic, or other trend-structure work. :contentReference {index=0} :contentReference {index=1}
haScanMaxMove(lookback, includeCurrentBar, highSeries, lowSeries)
Scans a lookback window for the strongest upward or downward percentage move
Parameters:
lookback (simple int): Number of bars to scan
includeCurrentBar (simple bool): Whether bar 0 should be included in the scan
highSeries (float): High series used for upward and downward move detection
lowSeries (float): Low series used for upward and downward move detection
Returns: Winning direction, winning percent move, winning start bars-ago, winning end bars-ago, winning span bars
➖HA Streak Helpers➖
These helpers let a script keep track of active Heikin Ashi streaks. They determine whether the current HA sequence is bullish or bearish, count how long that streak has been running, assign a tier color based on streak length, and measure how far price has moved from the streak’s starting point. In other words, this region helps turn raw HA trend runs into usable streak state, color, and percent-move data for candles, rows, labels, and trend readouts. :contentReference {index=0}
haStreakState(haOpen, haClose, bullCountPrev, bearCountPrev)
Resolves raw HA bull/bear state, streak counts, and streak start offset
Parameters:
haOpen (float): Current Heikin Ashi open
haClose (float): Current Heikin Ashi close
bullCountPrev (int): Prior bullish streak count
bearCountPrev (int): Prior bearish streak count
Returns: is HA bullish, is HA bearish, bullish streak count, bearish streak count, current streak length, streak start bars-ago
haStreakTierColor(isHaBull, isHaBear, bullCount, bearCount, streakTierBars, bullTier1, bullTier2, bullTier3, bullTier4, bearTier1, bearTier2, bearTier3, bearTier4, neutralColor)
Returns the active streak-tier color from bull/bear streak counts
Parameters:
isHaBull (bool): True when the current HA streak is bullish
isHaBear (bool): True when the current HA streak is bearish
bullCount (int): Current bullish streak count
bearCount (int): Current bearish streak count
streakTierBars (simple int): Number of bars required before advancing to the next tier
bullTier1 (color): Bullish tier 1 color
bullTier2 (color): Bullish tier 2 color
bullTier3 (color): Bullish tier 3 color
bullTier4 (color): Bullish tier 4 color
bearTier1 (color): Bearish tier 1 color
bearTier2 (color): Bearish tier 2 color
bearTier3 (color): Bearish tier 3 color
bearTier4 (color): Bearish tier 4 color
neutralColor (color): Fallback color when no active streak is available
Returns: Active streak-tier color
haStreakPct(isHaBull, isHaBear, streakBars, highSeries, lowSeries)
Returns the wick-based percent move from the streak start to the current bar
Parameters:
isHaBull (bool): True when the current HA streak is bullish
isHaBear (bool): True when the current HA streak is bearish
streakBars (int): Current active streak length
highSeries (float): High series used for streak measurement
lowSeries (float): Low series used for streak measurement
Returns: Wick-based streak percent move
➖Confirmed HA Trend Helpers➖
These helpers let a script work with a slower, confirmation-based HA trend instead of flipping immediately on the first opposite HA candle. They track the currently confirmed direction, count how many opposite candles are building toward the next possible flip, project the confirmed trend using regular-price body or wick anchors, and measure how far that confirmed trend has moved from its confirmed start. In other words, this region helps scripts build a more stable HA trend model that filters out some of the noise of raw HA flips. :contentReference {index=0} :contentReference {index=1}
haConfirmedTrendState(enabled, rawDir, confirmBars, dirPrev, oppCountPrev, startBarPrev, firstOppBarPrev)
Resolves confirmed trend direction, build count, and confirmed start bar
Parameters:
enabled (simple bool): Whether the confirmed-trend engine is active
rawDir (int): Current raw HA direction: +1 bull, -1 bear, 0 neutral
confirmBars (simple int): Consecutive opposite raw HA bars required to confirm a flip
dirPrev (int): Prior confirmed direction
oppCountPrev (int): Prior opposite-side build count
startBarPrev (int): Prior confirmed trend start bar index
firstOppBarPrev (int): Prior first opposite raw HA bar index
Returns: Confirmed direction, opposite-side build count, confirmed start bar index, first opposite raw HA bar index, confirmed leg bars, confirmed start bars-ago
haConfirmedTrendProjection(confirmedDir, startOffset, openValue, highValue, lowValue, closeValue, anchorMode, pathMode, forwardBars)
Returns confirmed trend projection geometry from body/wick anchor rules
Parameters:
confirmedDir (int): Confirmed direction: +1 bull, -1 bear, 0 neutral
startOffset (int): Confirmed start bars-ago offset
openValue (float): Regular-price open
highValue (float): Regular-price high
lowValue (float): Regular-price low
closeValue (float): Regular-price close
anchorMode (simple string): Projection anchor mode: "Body" or "Wick"
pathMode (simple string): Projection path mode: "Same Side" or "Opposite Side"
forwardBars (simple int): Number of bars forward for projection
Returns: Has valid projection, start Y, current Y, future Y, slope
haConfirmedTrendPct(confirmedDir, startOffset, highSeries, lowSeries)
Returns confirmed streak percent movement from the confirmed start bar
Parameters:
confirmedDir (int): Confirmed direction: +1 bull, -1 bear, 0 neutral
startOffset (int): Confirmed start bars-ago offset
highSeries (float): HA high series used for confirmed move measurement
lowSeries (float): HA low series used for confirmed move measurement
Returns: Confirmed streak percent move
➖HA Pressure Meter Helpers➖
These helpers take the HA-based oscillator engine and convert it into an easier 0–100 pressure reading. They help a script decide when bullish or bearish pressure is becoming active, assign matching tier colors for rows or other visuals, and return the color state for a pressure strip or similar chart-edge signal. In other words, this region turns the HA oscillator into a simpler pressure model that is easier to read at a glance.
haPressureMeter(rawOsc, bullAnchor, bearAnchor)
Normalizes a raw oscillator value into a 0-100 Pressure Meter
Parameters:
rawOsc (float): Raw oscillator value
bullAnchor (float): Raw oscillator value that should map to 100
bearAnchor (float): Raw oscillator value that should map to 0
Returns: Pressure Meter value in the 0-100 range
haPressureState(pressureMeter, bullThreshold, bearThreshold)
Resolves bullish, bearish, and neutral threshold state from the Pressure Meter
Parameters:
pressureMeter (float): Normalized Pressure Meter value
bullThreshold (float): Meter level where bullish pressure becomes active
bearThreshold (float): Meter level where bearish pressure becomes active
Returns: Bull-active, bear-active, neutral-between
haPressureTierColors(pressureMeter, bullTier1, bullTier2, bullTier3, bullTier4, bearTier1, bearTier2, bearTier3, bearTier4, fallbackBg)
Returns tier-based pressure-row background and readable text color
Parameters:
pressureMeter (float): Normalized Pressure Meter value
bullTier1 (color): Bull tier 1 color
bullTier2 (color): Bull tier 2 color
bullTier3 (color): Bull tier 3 color
bullTier4 (color): Bull tier 4 color
bearTier1 (color): Bear tier 1 color
bearTier2 (color): Bear tier 2 color
bearTier3 (color): Bear tier 3 color
bearTier4 (color): Bear tier 4 color
fallbackBg (color): Fallback background when the meter is na
Returns: Row background color, row text color
haPressureStripColor(pressureMeter, bullThreshold, bearThreshold, bullTier1, bullTier2, bullTier3, bullTier4, bearTier1, bearTier2, bearTier3, bearTier4, neutralColor, activeTransp, neutralTransp)
Returns active or neutral strip color from the Pressure Meter state
Parameters:
pressureMeter (float): Normalized Pressure Meter value
bullThreshold (float): Meter level where bullish pressure becomes active
bearThreshold (float): Meter level where bearish pressure becomes active
bullTier1 (color): Bull tier 1 color
bullTier2 (color): Bull tier 2 color
bullTier3 (color): Bull tier 3 color
bullTier4 (color): Bull tier 4 color
bearTier1 (color): Bear tier 1 color
bearTier2 (color): Bear tier 2 color
bearTier3 (color): Bear tier 3 color
bearTier4 (color): Bear tier 4 color
neutralColor (color): Neutral-zone base color
activeTransp (int): Transparency used when bull or bear pressure is active
neutralTransp (int): Transparency used inside the neutral zone
Returns: Strip color
➖Fib Backbone Structure Helpers➖
These helpers take a winning max-move scan and turn it into the structure a script can use for Fib Backbone analysis. They define the backbone’s start and end anchors, determine the related support/resistance anchor geometry, calculate Fib level prices between those anchors, and measure how far current price is from those levels. In other words, this region helps convert a dominant move into a reusable backbone structure that can support diagonals, S/R anchors, boxes, and Fib-based readouts.
haFibBackboneStructure(dir, startBA, endBA, openValue, highValue, lowValue, closeValue)
Returns backbone coordinates, S/R anchors, and anchor-box geometry
Parameters:
dir (int): Winning move direction: +1 bull, -1 bear, 0 none
startBA (int): Winning move start bars-ago
endBA (int): Winning move end bars-ago
openValue (float): Regular-price open
highValue (float): Regular-price high
lowValue (float): Regular-price low
closeValue (float): Regular-price close
Returns: ok, xStart, xEnd, yStart, yEnd, startIsRes, endIsRes, anchorTopS, anchorBotS, anchorTopE, anchorBotE, isTopS, isTopE
haFibLevelPrice(yStart, yEnd, fibLevel)
Returns the price of one fib level between the backbone anchors
Parameters:
yStart (float): Backbone start anchor price
yEnd (float): Backbone end anchor price
fibLevel (float): Fib level such as 0.236, 0.382, 0.50, 0.618, 0.786
Returns: Fib level price
haFibPctFromClose(closeValue, fibPrice)
Returns percent distance from close to a fib level
Parameters:
closeValue (float): Current close
fibPrice (float): Fib level price
Returns: Percent from close to fib level
➖Fib Backbone Context Window Helpers➖
These helpers build the larger context window around the active Fib Backbone lookback. They let a script define the left/right range of that window, calculate its current high and low bounds, and find the midpoint of the same structure. In other words, this region helps frame the broader area that the active backbone move is being selected from, so the move can be viewed in context rather than in isolation.
haFibContextWindow(lookback, includeCurrentBar, sourceMode, highValue, lowValue, closeValue)
Returns the active Fib Backbone context window geometry
Parameters:
lookback (simple int): Context-window lookback length
includeCurrentBar (simple bool): Whether the current bar participates in the active window
sourceMode (simple string): Source selection. Expected values: "Wicks" or "Closes"
highValue (float): Regular-price high
lowValue (float): Regular-price low
closeValue (float): Regular-price close
Returns: ok, leftX, rightX, windowBars, windowHigh, windowLow, leftHigh, leftLow
haFibContextMidpoint(ok, windowHigh, windowLow)
Returns the midpoint of the active Fib Backbone context window
Parameters:
ok (bool): Whether the context window is valid
windowHigh (float): Active context-window high
windowLow (float): Active context-window low
Returns: Context-window midpoint
➖Primary Trend Window Helpers➖
These helpers scan a lookback window to find the strongest completed HA streak and turn that winner into usable trend information. They identify the winning streak, assign it the correct tier color, and return the anchor coordinates needed to project that streak as a chart-side diagonal. In other words, this region helps a script reduce a larger HA trend window down to its most important completed streak structure.
haPrimaryTrendWinner(lookback, haBull, haBear, bullCount, bearCount, haHigh, haLow)
Returns the strongest completed HA streak inside the lookback window
Parameters:
lookback (simple int): Number of bars to scan
haBull (bool): Bullish HA state series
haBear (bool): Bearish HA state series
bullCount (int): Bullish HA streak-count series
bearCount (int): Bearish HA streak-count series
haHigh (float): HA high series used for wick-based streak measurement
haLow (float): HA low series used for wick-based streak measurement
Returns: Winning streak length, winning direction, winning percent move, winning start bars-ago, winning end bars-ago, winning validity state
haPrimaryTrendTierColor(dir, streakLen, streakTierBars, bullTier1, bullTier2, bullTier3, bullTier4, bearTier1, bearTier2, bearTier3, bearTier4, fallbackBg)
Returns the winning Primary Trend tier color
Parameters:
dir (int): Winning streak direction: +1 bull, -1 bear, 0 none
streakLen (int): Winning streak length
streakTierBars (simple int): Number of bars required before advancing to the next tier
bullTier1 (color): Bullish tier 1 color
bullTier2 (color): Bullish tier 2 color
bullTier3 (color): Bullish tier 3 color
bullTier4 (color): Bullish tier 4 color
bearTier1 (color): Bearish tier 1 color
bearTier2 (color): Bearish tier 2 color
bearTier3 (color): Bearish tier 3 color
bearTier4 (color): Bearish tier 4 color
fallbackBg (color): Fallback background when no valid winner exists
Returns: Winning tier color
haPrimaryTrendCoords(dir, startBA, endBA, highSeries, lowSeries)
Returns diagonal coordinates from the winning streak anchors
Parameters:
dir (int): Winning streak direction: +1 bull, -1 bear, 0 none
startBA (int): Winning start bars-ago
endBA (int): Winning end bars-ago
highSeries (float): High series used for line anchors
lowSeries (float): Low series used for line anchors
Returns: ok, x1, x2, y1, y2
NOTES
This is a Heikin-Ashi-specific utility library. It is meant to provide the reusable HA math, state, and structure layer. Final rendering choices such as plot style, line objects, boxes, labels, tables, and overall UI layout are expected to remain script-level decisions.
Thanks to SimpleCryptoLife for the open-source HA core functions heikinAshi() & haPredictClose() and thus the inspiration that they've given me to create HA-based indicators for the HA trader enthusiast.
Library

FootprintCore
ExperimentaL WIP
The FootprintCore library is a Pine Script v6 toolset designed for deep analysis of order flow and footprint data. It provides structured data types and functions to extract, normalize, and interpret footprint features to identify market breakouts and execution regimes.
Core Data Types
FPBar: Captures raw footprint metrics including volume (total, buy, sell), Delta, POC/Value Area levels, and imbalance stack counts.
FPNorm: Stores normalized versions of key features, primarily using Z-Scores and Percentile Ranks to compare current activity against historical lookbacks.
FPDerived: Holds high-level interpretations such as "Stack Dominance," "Bullish Acceptance," and "Auction Failures".
FPSignal & FPExec: Define trade triggers and execution states (e.g., passive, caution, or avoid) based on current volatility and liquidity.
How to Use the Library
1. Feature Extraction
Use extractBar() to convert a footprint object into a structured FPBar type. You must provide price context (close, high, low) and an ATR value for normalization.
Pine Script
fp_data = footprint.get()
bar_features = FootprintCore.extractBar(fp_data, prevPoc, close, high, low, ta.atr(14))
2. Normalization
Pass the FPBar into normalizeBar() to calculate Z-Scores and Ranks for features like Value Area width and Delta efficiency.
Pine Script
norm_features = FootprintCore.normalizeBar(bar_features, 20, 100)
3. Generating Signals
The breakoutSignal() function identifies high-probability trade setups. It checks for:
Bullish/Bearish Acceptance: Price breaking out of the Value Area with positive/negative Delta.
+1
Stack Dominance: Presence of imbalance stacks (e.g., more than 3 buy stacks).
Efficiency: Delta efficiency and range compression requirements.
+1
4. Execution Governance
Before placing a trade, use executionState() to assess the "stress" of the current market.
ExecMode.avoid: Triggered when slippage proxies or fragility scores (based on Z-Scores) are too high.
+1
noTrade: A boolean flag that becomes true if footprint data is missing or the market structure is unstable.
5. Diagnostic Reason Codes
For debugging or logging, reasonCodeBreakout() returns a machine-readable string (e.g., "ACC|STACK|EFF|") indicating which specific conditions were met for a signal.
Library

Gann Time Price Geometry Ver 1.0Gann Time Price Geometry — Ver 1.0
This indicator builds a dynamic Gann Square grid directly on your chart, anchored to automatically detected swing highs and lows. It combines classical Gann geometry with a scoring-based signal engine to highlight high-confluence buy and sell opportunities.
How it works
The script uses a Vector Circle Search to find the best pivot pair within a harmonic window around your chosen Gann number (88 bars by default). It scores each candidate swing by how closely its price-per-bar ratio and duration match the ideal Gann proportion, then anchors the full grid to the winning pair.
What you get on the chart
What is Drawn on the Chart
🔲 Full Square
The outer Gann Square spans your chosen Gann number in bars horizontally, and 2× the detected swing range vertically. This is the master structure everything else is built inside.
🔲 Sub-Squares (4 Inner Cells)
The full square is divided into 4 equal inner cells — 2 columns × 2 rows. Each cell gets its own set of angle lines projected from its corners. This creates nested geometry that gives you finer entry and exit precision within the larger structure.
📐 Angle Lines
1x1 — the true balance angle between price and time, projected from all four corners of both the full square and each sub-cell
2x1 / 1x2 — steeper and shallower angles showing acceleration and deceleration zones
All angles are clamped within their respective square boundaries so the chart stays clean
⏱️ Time Cycle Verticals
Vertical lines mark Gann's 1/8 harmonic divisions of time across the square:
1/2 cycle (orange, prominent) — the most powerful time node, midpoint of the square
1/4 and 3/4 cycles (dashed) — secondary time divisions where reactions are common
1/8 minor cycles (optional) — finer subdivisions for short-term timing
When price reaches an angle line and a time cycle vertical at the same bar — that is a Gann confluence point, and where this indicator focuses its signals.
Signal scoring (max ~10 pts per signal)
Set Min Confluence Score to 3–4 for quality signals. Lower it to 0 to see all geometrically valid touches.
Settings to tune first
Match Gann Number to your timeframe (88 for most, 44 for fast charts)
Check the Info Table — if Swing pts/bar doesn't match Diagonal, update the Swing Diagonal Is dropdown
Adjust Period Divisor to the harmonic you are trading (1/2 suits swing traders)
Alerts included — Gann Buy and Gann Sell, fire on bar close.
First-Time Setup — 3 Steps
Step 1 — Choose your Gann Number
Start with 88 on Daily or 4H charts. Use 44 on 1H or faster. This defines the width of your square in bars.
Step 2 — Match the Diagonal
Open the chart, look at the Info Table. Find Swing pts/bar and the suggest note next to it. If it says "use 2x1", set the Swing Diagonal Is dropdown to 2x1. Green ✅ means you are calibrated correctly.
Step 3 — Set your Confluence Level
Start at 3. If you are getting too many signals, raise it to 4 or 5. If you want to study all geometric touches without filtering, set it to 0.
Works on: Any instrument — stocks, crypto, forex, indices, commodities
Works on: Any timeframe — tune Gann Number to match
Alerts: Gann Buy and Gann Sell included, fire on bar close
Note on Line Limits
TradingView Pine Script has a 500-line limit. Keep Squares Forward and Squares Backward at 2 or below to stay within this limit. The indicator will silently drop lines if the limit is exceeded.
Indicator

Vector Radius PBR ScalingVector Radius PBR Scaling — √Price Geometric Chart Calibration
WHAT THIS INDICATOR DOES
This indicator calculates a theoretically derived PBR (Points Per Bar) scaling value based on the concept of √price space geometry. You select a swing high and low using date inputs, and it outputs PBR values that can be used with TradingView's chart scaling for experimental geometric analysis with circle and arc tools.
It is designed for students and researchers of geometric market theory who want to explore how √price transformations affect chart scaling and circle geometry.
THE CONCEPT
Standard PBR divides the price range by the number of bars. This treats all price levels equally — a $100 move at $50 is handled the same as a $100 move at $50,000.
This indicator explores an alternative approach: what if price is better understood as a radial distance from zero? In this theoretical framework, √Price represents the radius — the distance from zero to any price level. The difference √H - √L represents the distance a move covers in this curved space, which is not the same as taking the square root of the range √(H-L). The velocity through this space, measured per bar, produces a scaling factor that accounts for the absolute price level of the instrument.
The formula explored is:
PBR = ((√H - √L) / B) × Radius
Where H is the high price, L is the low price, B is the number of bars, and Radius is either √H or √Mid depending on the mode selected.
TWO MODES
Impulse (× √H) scales by the outer radius, which is the maximum price reached during the swing. The theory suggests this may suit trending or impulsive market conditions where the high represents peak energy expression.
Equilibrium (× √Mid) scales by the midpoint radius, where Mid = (H + L) / 2. The theory suggests this may suit ranging or consolidating conditions where balance around the centre of the move matters more than its extremes.
WHY √H IS USED FOR BOTH UP AND DOWN LEGS
In this geometric framework, √H represents the outer boundary of the swing regardless of direction. Whether price moved up to a high or down from a high, the maximum price level defines the largest radius of the system. This is analogous to how a pendulum's behaviour is governed by its maximum displacement, not its direction of travel.
WHAT THIS DOES NOT DO
This indicator does not predict where price will go. It does not identify support or resistance levels. It does not generate trading signals. It does not guarantee that circles or arcs will align with future price action. It does not replace proper risk management or trading discipline.
Any observed alignments between geometric projections and actual price behaviour may be coincidental. Markets are influenced by fundamentals, sentiment, liquidity, and countless other factors that no geometric formula can fully capture.
HOW TO USE (FOR RESEARCH)
Add the indicator to your chart. Select start and end dates around a swing you want to study. Read the PBR values from the table. Experiment with entering the PBR into your chart scaling settings. Draw circles or arcs and observe. Do not treat any observations as predictive.
TABLE OUTPUT
The indicator displays the high, low, and mid prices of the selected range, the price range and bar count, the √H, √L, and √Mid values, the root speed (√H - √L) / B, and the final PBR for both Impulse and Equilibrium modes.
WHO THIS IS FOR
This is for researchers and students of geometric market analysis who want a tool to quickly calculate √price-based scaling values. It assumes familiarity with PBR scaling, square-the-range concepts, and circle or arc geometry on price charts.
If you are not familiar with these concepts, this indicator will not be useful to you out of the box. It is not a plug-and-play trading tool.
INDICATOR IN ACTION
NOTES
Works on all timeframes and all instruments. The formula uses absolute price levels, not just the range, so the same dollar move at different price levels produces different PBR values. This is a theoretical exploration, not a proven trading methodology. No representation is made about the accuracy, reliability, or profitability of any analysis derived from this tool.
This is an educational tool for geometric research. It is not financial advice. Do not trade based solely on geometric projections. Always use proper risk management.
DISCLAIMER: This indicator is strictly educational and experimental. It is based on geometric theory applied to price charts. It does not generate buy or sell signals, it does not predict future price movement, and it does not guarantee any outcome. Use at your own risk. Past geometric alignments do not imply future alignments. This is a research and study tool only.
Indicator

ZigZag ATR PctZigZag ATR % Library
A PineScript v6 library for detecting price pivots based on ATR percentage change (volatility shifts) rather than fixed ATR multiples.
How It Works
Traditional ZigZag indicators use a fixed price threshold to detect pivots. This library takes a different approach: pivots are detected when volatility is changing significantly .
The ATR % change measures how much the Average True Range has shifted over a lookback period:
atrPct = 100 * (atr / atr - 1)
Positive ATR % = Volatility expanding (market becoming more volatile)
Negative ATR % = Volatility contracting (market calming down)
Pivots form when |ATR %| exceeds your threshold, capturing turning points during volatility transitions.
Exported Types
Settings - Configuration (ATR length, lookback, threshold, display options)
Pivot - Pivot point data (price, time, direction, volume, ATR %)
ZigZag - Main state container
Exported Functions
newInstance(settings) - Create a new ZigZag instance
update(zz, atr, atrPct) - Update on each bar
getLastPivot(zz) - Get the most recent pivot
getPivot(zz, index) - Get pivot at specific index
getPivotCount(zz) - Get total number of pivots
calcTR() - Calculate True Range
calcATR(length) - Calculate ATR using EMA
calcATRPct(atr, atrPrev) - Calculate ATR % change
calcPricePct(startPrice, endPrice) - Calculate price % change
Usage Example
//@version=6
indicator("My ZigZag", overlay = true)
import DeepEntropy/ZigZagATRPct/1 as zz
// Settings
var zz.Settings settings = zz.Settings.new(
atrLength = 14,
atrLookback = 14,
atrPctThreshold = 5.0,
depth = 10
)
var zz.ZigZag zigZag = zz.newInstance(settings)
// Calculate ATR %
float atr = zz.calcATR(14)
float atrPct = zz.calcATRPct(atr, atr )
// Update
zigZag := zz.update(zigZag, atr, atrPct)
// Access pivots
int count = zz.getPivotCount(zigZag)
if count > 0
zz.Pivot last = zz.getLastPivot(zigZag)
label.new(last.point, text = str.tostring(last.atrPct, "#.##") + "%")
Parameters
ATR Length - Period for ATR calculation (default: 14)
ATR Lookback - Bars to look back for ATR % change (default: 14)
ATR % Threshold - Minimum |ATR %| to trigger pivot detection (default: 5.0)
Depth - Minimum bars between pivots (default: 10)
Use Cases
Identify reversals during volatility regime changes
Filter noise during low-volatility consolidation
Detect breakout pivots when volatility expands
Build volatility-aware trading systems
This library detects when the market's behavior is changing, not just how much price has moved.
Library

ZigZag ATRZigZag ATR Library
A volatility-adaptive ZigZag indicator that uses Average True Range (ATR) instead of fixed percentage deviation to detect pivot points. This makes the ZigZag dynamically adjust to market conditions — tighter during low volatility, wider during high volatility.
Why ATR instead of Percentage?
The standard ZigZag uses a fixed percentage threshold (e.g., 5%) to determine when price has reversed enough to form a new pivot. This approach has limitations:
A 5% move means very different things for a $10 stock vs a $500 stock
During high volatility, fixed percentages create too many pivots (noise)
During low volatility, fixed percentages may miss significant structure
ATR-based deviation solves these issues by measuring reversals in terms of actual volatility , not arbitrary percentages.
Key Features
Volatility-adaptive pivot detection using ATR × multiplier threshold
Automatic adjustment to changing market conditions
Full customization of ATR length and multiplier
Optional line extension to current price
Pivot labels showing price, volume, and price change
Clean library structure for easy integration
Settings
ATR Length — Period for ATR calculation (default: 14)
ATR Multiplier — How many ATRs price must move to confirm a new pivot (default: 2.0)
Depth — Bars required for pivot detection (default: 10)
Extend to Last Bar — Draw provisional line to current price
Display options — Toggle price, volume, and change labels
How to Use
import YourUsername/ZigZagATR/1 as zz
// Create settings
var zz.Settings settings = zz.Settings.new(
14, // ATR length
2.0, // ATR multiplier
10 // Depth
)
// Create ZigZag instance
var zz.ZigZag zigZag = zz.newInstance(settings)
// Calculate ATR and update on each bar
float atrValue = ta.atr(14)
zigZag.update(atrValue)
Exported Types
Settings — Configuration for calculation and display
Pivot — Stores pivot point data, lines, and labels
ZigZag — Main object maintaining state and pivot history
Exported Functions
newInstance(settings) — Creates a new ZigZag object
update(atrValue) — Updates the ZigZag with current ATR (call once per bar)
lastPivot() — Returns the most recent pivot point
Recommended Multiplier Values
1.0 - 1.5 → More sensitive, more pivots, better for scalping
2.0 - 2.5 → Balanced, good for swing trading (default)
3.0+ → Less sensitive, major pivots only, better for position trading
Based on TradingView's official ZigZag library, modified to use ATR-based deviation threshold. Library

Gann Sacred Geometry Hexagram Ver 1.2━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔯 GANN SACRED GEOMETRY HEXAGRAM v1.2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
A comprehensive technical analysis tool combining W.D. Gann's sacred geometry principles,
hexagram patterns, and advanced confluence scoring for high-probability trade signals.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📖 GANN THEORY BACKGROUND
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
W.D. Gann (1878-1955) believed markets move in geometric patterns and that price
and time must be in balance. His methods incorporated:
- The Square of Nine
- Geometric angles (1x1, 2x1, etc.)
- Sacred geometry and natural law
- Cycle theory and time divisions
- The principle "When time and price square, a change in trend is imminent"
This indicator applies these timeless principles with modern confluence analysis.
SACRED GEOMETRY FOUNDATION:
The hexagram (six-pointed star) is formed by two overlapping equilateral triangles:
- ▲ Upward triangle = Yang energy, bullish forces, expansion
- ▼ Downward triangle = Yin energy, bearish forces, contraction
When overlapped, they create the "Star of David" - representing perfect balance
between opposing market forces. Gann believed this geometry revealed natural
support and resistance zones where price would react.
HEXAGRAM IN MARKETS:
- 6 outer points = Major reversal zones
- Center point = Balance/equilibrium price
- Inner intersections = Secondary support/resistance
- The shape itself creates "harmonic" price levels
GANN'S SQUARE PHILOSOPHY:
"When time and price square, a change in trend is imminent."
- W.D. Gann
This indicator applies the "squaring" concept:
1. SPATIAL SQUARE: Grid cells are perfect squares in price-time space
2. TEMPORAL SQUARE: Time divisions (1/4, 1/2, 3/4) create cycle points
3. PRICE SQUARE: Price divisions (25%, 50%, 75%) mirror time divisions
4. GEOMETRIC SQUARE: All geometry radiates from perfect square centers
When price reaches a corner or edge of a square at a time cycle point,
the "squaring" of price and time creates a reversal probability zone.
PHI IN GANN GEOMETRY:
The Golden Ratio appears throughout natural phenomena and market structure.
This script uses φ in two primary ways:
1. INNER TRIANGLE SCALING:
- Outer triangles span the full cell (100%)
- Inner triangles scaled by φ⁻¹ (0.618 or 61.8%)
- This creates Fibonacci retracement levels geometrically
2. HARMONIC RESONANCE:
- φ ratio divides price space into natural harmony
- Markets tend to pause/reverse at these φ-scaled levels
- Combines Fibonacci analysis with Gann geometry
MATHEMATICAL RELATIONSHIP:
Inner Triangle Height = Outer Height × 0.618
Inner Triangle Width = Outer Width × 0.618
These create the 61.8% retracement levels automatically
within each grid cell's geometry.
GANN'S COMPLETE ANGLE SYSTEM:
Gann identified 9 primary angles that price follows. Each represents a different
relationship between price movement and time passage:
╔════════════════════════════════════════════════════════════════╗
║ ANGLE │ RATIO │ DEGREES │ MEANING ║
╠════════════════════════════════════════════════════════════════╣
║ 1x8 │ 1:8 │ 7.125° │ Very slow trend (gentle) ║
║ 1x4 │ 1:4 │ 14.036° │ Slow trend ║
║ 1x3 │ 1:3 │ 18.435° │ Moderate-slow trend ║
║ 1x2 │ 1:2 │ 26.565° │ Moderate trend ║
║ 1x1 │ 1:1 │ 45.000° │ MASTER ANGLE (most important) ║
║ 2x1 │ 2:1 │ 63.435° │ Strong trend ║
║ 3x1 │ 3:1 │ 71.565° │ Very strong trend ║
║ 4x1 │ 4:1 │ 75.964° │ Extreme trend ║
║ 8x1 │ 8:1 │ 82.875° │ Parabolic trend (unsustainable)║
╚════════════════════════════════════════════════════════════════╝
THE 1x1 ANGLE - THE MASTER:
- Most important angle in Gann theory
- Represents perfect balance: 1 unit price = 1 unit time
- When price is ABOVE 1x1 = Bullish control
- When price is BELOW 1x1 = Bearish control
- Crossing 1x1 = Major trend change signal
ANGLE FANS:
- From any pivot point, all 9 angles radiate outward
- Creates a "fan" of dynamic support/resistance
- Steeper angles (4x1, 8x1) = strong momentum resistance
- Gentler angles (1x4, 1x8) = weak support in downtrends
THE SACRED DIVISIONS OF TIME:
Gann divided all cycles into 8 equal parts, based on ancient geometry
and astrological principles:
CYCLE DIVISIONS (8ths):
┌─────────────────────────────────────────────────────┐
│ 1/8 = 12.5% │ First minor turn point │
│ 2/8 = 25.0% │ First major turn (Cardinal) │
│ 3/8 = 37.5% │ Second minor turn │
│ 4/8 = 50.0% │ MID-CYCLE (most powerful) │
│ 5/8 = 62.5% │ Third minor turn │
│ 6/8 = 75.0% │ Second major turn (Cardinal) │
│ 7/8 = 87.5% │ Fourth minor turn │
│ 8/8 = 100.0% │ CYCLE COMPLETION (reversal zone) │
└─────────────────────────────────────────────────────┘
WHY EIGHTHS?
- 8 is the number of balance in sacred geometry
- Octave divisions create harmonic resonance
- 360° circle ÷ 8 = 45° (the 1x1 master angle)
- Natural cycles show 8-fold symmetry
IN THIS SCRIPT:
When current time position is within 8% of any eighth division,
the "Gann 8ths Timing" factor activates, adding confluence points.
THE CARDINAL CROSS SYSTEM:
The Cardinal Cross divides any square into four equal quadrants,
creating a cross pattern:
100% ●━━━━━━━━━━━━━●
┃ ↑ ┃
75% ┃ SELL ZONE ┃ ← Resistance quadrant
┃ ↑ ┃
50% ●━━━━━●━━━━━━● ← EQUILIBRIUM (most important)
┃ ↓ ┃
25% ┃ BUY ZONE ┃ ← Support quadrant
┃ ↓ ┃
0% ●━━━━━━━━━━━━━●
PRICE LEVELS:
- 0% = Bottom support (grid cell low)
- 25% = Lower mid-level support
- 50% = PERFECT BALANCE - most powerful level
- 75% = Upper mid-level resistance
- 100% = Top resistance (grid cell high)
TIME DIVISIONS:
- 0% = Cycle start (grid cell left edge)
- 25% = First quarter turn
- 50% = Mid-cycle (most powerful timing)
- 75% = Third quarter turn
- 100% = Cycle completion (grid cell right edge)
CONFLUENCE MAGIC:
When BOTH price AND time align at cardinal points simultaneously:
Example: Price at 50% level + Time at 50% of cycle = Maximum power
This is the "squaring" Gann referred to.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 KEY FEATURES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Dynamic Grid System (1x1 to 7x7) - Automatically constructed from swing high to swing low
✅ Sacred Geometry Hexagrams - Overlapping triangles creating Star of David pattern
✅ Golden Ratio (φ = 1.618) Inner Triangles - Fibonacci harmony in geometry
✅ 9 Complete Gann Angles - 1x1, 2x1, 1x2, 3x1, 1x3, 4x1, 1x4, 8x1, 1x8
✅ Cardinal Cross Levels - 0%, 25%, 50%, 75%, 100% price divisions
✅ Gann 8ths Timing Cycles - 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8 time divisions
✅ Price-Time Square Balance - Gann's principle of harmonious price-time relationship
✅ Advanced Confluence Scoring - Multi-factor signal validation (8-30 score range)
✅ Optimized Geometry Display - Shows full detail only near current price (reduces clutter)
✅ Customizable Visual Themes - Full color and thickness control
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 HOW IT WORKS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 GRID CONSTRUCTION:
The indicator identifies the most recent significant swing high-to-low movement using
configurable pivot periods (default: 88 bars). This creates the base "square" which is
then replicated in a grid pattern both vertically (price) and horizontally (time).
📐 SACRED GEOMETRY:
Each grid cell contains:
- Outer hexagram (Star of David) formed by two overlapping triangles
- Inner φ-ratio triangles scaled by the Golden Ratio
- Gann angles radiating from the center point
- Cardinal cross levels dividing price into quarters
🔍 CONFLUENCE SCORING SYSTEM:
Signals are generated when multiple Gann principles align:
1. Cardinal Cross Levels (0-6 points) - Price at key quarter divisions
2. Gann Angle Touches (0-5 points) - Price touching dynamic support/resistance angles
3. Angle Clustering (0-6 points) - Multiple angles converging = strong zone
4. Gann 8ths Timing (0-3 points) - At critical time cycle points
5. Price-Time Square (0-4 points) - Balanced price/time movement
6. Trend Alignment (0-3 points) - Signal direction matches trend
7. Grid Boundary Timing (0-3 points) - Near cell edges = reversal zones
8. φ Triangle Touches (0-2 points) - Golden ratio support/resistance
9. Reversal Patterns (0-2 points) - Wick rejections confirming reversal
Minimum confluence score of 15 required for signal (adjustable 8-30).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙️ RECOMMENDED SETTINGS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 For Daily Charts (Swing Trading):
- Gann Number: 88
- Grid Size: 4x4
- Confluence Score: 15
- Geometry Range: 5
- Trend Filter: ON
📊 For 4H Charts (Intraday):
- Gann Number: 44
- Grid Size: 3x3
- Confluence Score: 12-13
- Geometry Range: 3-4
- Trend Filter: ON
📊 For 15M Charts (Scalping):
- Gann Number: 22
- Grid Size: 2x2
- Confluence Score: 10-12
- Geometry Range: 2-3
- Allow Counter-Trend: Consider enabling
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📚 BEST PRACTICES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ Use higher confluence scores (15+) for higher probability trades
✓ Combine with volume analysis for confirmation
✓ Respect trend filter - signals with trend are stronger
✓ Watch for signals at grid boundaries (time cycle completions)
✓ Higher scores (20+) indicate exceptional setups
✓ Use alerts to catch signals in real-time
✓ Works best on liquid markets with clear swings
EXAMPLE 1: Strong Buy Signal (Score: 18)
✓ Price touched 50% level (6 pts)
✓ 1x1 Gann angle support (5 pts)
✓ At Gann 8th cycle point (3 pts)
✓ Price-Time squared (4 pts)
= High probability long entry
EXAMPLE 2: Medium Sell Signal (Score: 15)
✓ Price at 75% level (4 pts)
✓ 2x1 angle resistance (3 pts)
✓ Trend aligned downward (3 pts)
✓ Near grid boundary (3 pts)
✓ Bearish wick rejection (2 pts)
= Valid short entry
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎨 CUSTOMIZATION OPTIONS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Structure: Gann Number (11, 22, 44, 88, 176, 352)
- Grid: Size from 1x1 to 7x7
- Geometry: Toggle squares, triangles, angles, levels
- Optimization: Show geometry only near price (performance boost)
- Thickness: All line widths adjustable (1-5)
- Colors: Full color customization for all elements
- Scoring: Adjust all tolerance and threshold parameters
- Timing: Enable/disable Gann 8ths, Price-Time Square
- Filters: Trend filter, boundary requirement, counter-trend signals
- Display: 4 signal styles (Labels, Diamonds, Circles, Stars)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ IMPORTANT NOTES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- This indicator is for educational purposes
- Not financial advice - always do your own research
- Past performance does not guarantee future results
- Use proper risk management and position sizing
- Combine with other analysis methods for best results
- Grid redraws when new swing high/low forms
- Signals appear in real-time based on confluence scoring
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📞 SUPPORT & UPDATES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Follow for updates and improvements. Feedback welcome!
Version 1.2 - January 2025
- Optimized geometry rendering
- Enhanced confluence scoring
- Improved visual clarity
- Performance optimizations
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Indicator

Library

PatternTransitionTablesPatternTransitionTables Library
🌸 Part of GoemonYae Trading System (GYTS) 🌸
🌸 --------- 1. INTRODUCTION --------- 🌸
💮 Overview
This library provides precomputed state transition tables to enable ultra-efficient, O(1) computation of Ordinal Patterns. It is designed specifically to support high-performance indicators calculating Permutation Entropy and related complexity measures.
💮 The Problem & Solution
Calculating Permutation Entropy, as introduced by Bandt and Pompe (2002), typically requires computing ordinal patterns within a sliding window at every time step. The standard successive-pattern method (Equations 2+3 in the paper) requires ≤ 4d-1 operations per update.
Unakafova and Keller (2013) demonstrated that successive ordinal patterns "overlap" significantly. By knowing the current pattern index and the relative rank (position l) of just the single new data point, the next pattern index can be determined via a precomputed look-up table. Computing l still requires d comparisons, but the table lookup itself is O(1), eliminating the need for d multiplications and d additions. This reduces total operations from ≤ 4d-1 to ≤ 2d per update (Table 4). This library contains these precomputed tables for orders d = 2 through d = 5.
🌸 --------- 2. THEORETICAL BACKGROUND --------- 🌸
💮 Permutation Entropy
Bandt, C., & Pompe, B. (2002). Permutation entropy: A natural complexity measure for time series.
doi.org
This concept quantifies the complexity of a system by comparing the order of neighbouring values rather than their magnitudes. It is robust against noise and non-linear distortions, making it ideal for financial time series analysis.
💮 Efficient Computation
Unakafova, V. A., & Keller, K. (2013). Efficiently Measuring Complexity on the Basis of Real-World Data.
doi.org
This library implements the transition function φ_d(n, l) described in Equation 5 of the paper. It maps a current pattern index (n) and the position of the new value (l) to the successor pattern, reducing the complexity of updates to constant time O(1).
🌸 --------- 3. LIBRARY FUNCTIONALITY --------- 🌸
💮 Data Structure
The library stores transition matrices as flattened 1D integer arrays. These tables are mathematically rigorous representations of the factorial number system used to enumerate permutations.
💮 Core Function: get_successor()
This is the primary interface for the library for direct pattern updates.
• Input: The current pattern index and the rank position of the incoming price data.
• Process: Routes the request to the specific transition table for the chosen order (d=2 to d=5).
• Output: The integer index of the next ordinal pattern.
💮 Table Access: get_table()
This function returns the entire flattened transition table for a specified dimension. This enables local caching of the table (e.g. in an indicator's init() method), avoiding the overhead of repeated library calls during the calculation loop.
💮 Supported Orders & Terminology
The parameter d is the order of ordinal patterns (following Bandt & Pompe 2002). Each pattern of order d contains (d+1) data points, yielding (d+1)! unique patterns:
• d=2: 3 points → 6 unique patterns, 3 successor positions
• d=3: 4 points → 24 unique patterns, 4 successor positions
• d=4: 5 points → 120 unique patterns, 5 successor positions
• d=5: 6 points → 720 unique patterns, 6 successor positions
Note: d=6 is not implemented. The resulting code size (approx. 191k tokens) exceeds the Pine Script limit of 100k tokens (as of 2025-12). Library

Symmetrical Geometric MandalaSymmetrical Geometric Mandala
Overview
The Symmetrical Geometric Mandala is an advanced geometric trading tool that applies phi (φ) harmonic relationships to price-time analysis. This indicator automatically detects swing ranges and constructs a scale-invariant geometric framework based on the square root of phi (√φ), revealing natural support/resistance zones and harmonic price-time balance points.
Core Concept
Traditional technical analysis often treats price and time as separate dimensions. This indicator harmonizes them using the mathematical constant √φ (approximately 1.272), creating a geometric "squaring" of price and time that remains proportionally consistent across different chart scales.
The Mathematics
When you select a price range (from swing low to swing high or vice versa), the indicator calculates:
PBR (Price-to-Bar Ratio) = Range / Number of Bars
Harmonic PBR = PBR × √φ (1.272019649514069)
Phi Extension = Range × φ (1.618033988749895)
The Harmonic PBR is the critical value - this is the chart scaling factor that creates perfect geometric harmony between price and time for your selected range.
Visual Components
1. Horizontal Boundary Lines
Two horizontal lines extend from the selected range at a distance of Range × φ (golden ratio extension):
Upper line: Extended above the swing high (for uplegs) or swing low (for downlegs)
Lower line: Extended below the swing low (for uplegs) or swing high (for downlegs)
These lines mark the natural harmonic boundaries of the price movement.
2. Rectangle Diagonal Lines
Two diagonal lines that create a "rectangle" effect, connecting:
Overlap points on horizontal boundaries to swing extremes
These lines go in the opposite direction of the price leg (creating the symmetrical mandala pattern)
When extended, they reveal future geometric support/resistance zones
3. Phi Harmonic Circles (Optional)
Two precisely calculated circles (drawn as smooth polylines):
Circle A: Centered at the first swing extreme (Nodal A)
Circle B: Centered at the second swing extreme (Nodal B)
Radius = Range × φ, causing them to perfectly touch the horizontal boundary lines
These circles visualize the geometric harmony and create a mandala-like pattern that reveals natural price zones.
How to Use
Step 1: Select Your Range
Set the Start Date at your swing low or swing high
Set the End Date at the opposite extreme
The indicator automatically detects whether it's an upleg or downleg
Step 2: Read the Harmonic PBR
Check the highlighted yellow row in the table: "PBR × √φ"
This is your chart scaling value
Step 3: Apply Chart Scaling (Optional)
For perfect geometric visualization:
Right-click on your chart's price axis
Select "Scale price chart only"
Enter the PBR × √φ value
The geometry will now display in perfect harmonic proportion
Step 4: Interpret the Geometry
Horizontal lines: Key support/resistance zones at phi extensions
Diagonal lines: Dynamic trend channels and future price-time balance points
Circle intersections: Natural harmonic turning points
Central diamond area: Core price-time equilibrium zone
Key Features
✅ Automatic swing detection - identifies upleg/downleg automatically
✅ Scale-invariant geometry - maintains proportions across timeframes
✅ Phi harmonic calculations - based on golden ratio mathematics
✅ Professional color scheme - clean, non-intrusive visuals
✅ Customizable display - toggle circles, lines, and table independently
✅ Smooth circle rendering - adjustable segments (16-360) for optimal smoothness
Settings
Show Horizontal Boundary Lines: Display phi extension levels
Show Rectangle Diagonal Lines: Display the geometric framework
Show Phi Harmonic Circles: Display circular geometry (optional)
Circle Smoothness: Adjust polyline segments (default: 96)
Colors: Fully customizable color scheme for all elements
Theory Background
This indicator draws inspiration from:
W.D. Gann's price-time squaring techniques
Bradley Cowan's geometric market analysis
Phi/golden ratio harmonic theory
Mathematical constants in market structure
Unlike traditional Fibonacci retracements, this tool uses √φ instead of φ as the primary scaling constant, creating a unique geometric relationship that "squares" price movement with time passage.
Best Practices
Use on significant swings - Works best on major swing highs/lows
Multiple timeframe analysis - Apply to different timeframes for confluence
Combine with other tools - Use alongside support/resistance and trend analysis
Respect the geometry - Pay attention when price interacts with geometric elements
Chart scaling optional - The geometry works at any scale, but scaling enhances visualization
Notes
The indicator draws geometry from left to right (from Nodal A to Nodal B)
All lines extend infinitely for future projections
The table shows real-time calculations for the selected range
Date range selection uses confirm dialogs to prevent accidental changes
Indicator

3D Cube Projection - √3 Diagonal3D Cube Projection - √3 Diagonal
OVERVIEW
This indicator implements Bradley F. Cowan's cube projection methodology from his "Four Dimensional Stock Market Structures & Cycles" work. It visualizes a 3D cube projected onto the 2D price-time chart, using the √3 (square root of 3) body diagonal as the primary analytical tool for identifying market structure and potential cycle termination points.
METHODOLOGY
The cube is constructed by selecting two pivot points (A and E) which form the body diagonal - the longest diagonal running through the cube's interior from one corner to the diagonally opposite corner. According to Cowan's geometric approach:
- Point A = Starting pivot (low or high)
- Point E = Ending pivot (opposite extreme)
- Body Diagonal (A→E) = √3 × cube side length
- Face Diagonal (A→C) = √2 × cube side length
The script calculates the cube dimensions by:
1. Measuring the total price range from A to E
2. Dividing by √3 to determine the cube side length in price
3. Distributing the time component across three equal segments
4. Projecting the 3D structure onto the 2D chart plane
FEATURES
✓ Interactive date selection for points A and E
✓ Automatic UPLEG/DOWNLEG detection
✓ All 8 cube vertices labeled (A-H)
✓ All 6 cube faces with independent color/opacity controls
✓ √3 body diagonal (red line by default)
✓ √2 face diagonal (orange line by default)
✓ Customizable cube lines, fills, and labels
✓ Information table showing key measurements
VISUAL CUSTOMIZATION
- Front & Back faces: Box fills for the two square faces
- Side faces: Left and right vertical faces
- Top & Bottom faces: Horizontal connecting faces
- Each group has independent color and opacity settings
- Label size and transparency fully adjustable
- Cube line styles (solid, dashed, dotted) for depth perception
IMPORTANT LIMITATIONS & DISCLOSURES
This indicator works within the inherent constraints of projecting 3D geometry onto a 2D price-time chart:
⚠️ VISUAL APPROXIMATION: This is a visual projection tool, not a mathematically perfect 3D cube. True 3D geometry cannot be accurately represented on a 2D plane without distortion.
⚠️ TIME DISTRIBUTION: The script divides the time axis into three equal segments (total bars ÷ 3) for practical visualization. This is an approximation that prioritizes visual coherence over strict geometric accuracy.
⚠️ UNIT SCALING: Price and time use different units (dollars vs. bars), making true isometric projection impossible. The cube appears proportional on screen but the dimensions are not directly comparable.
⚠️ 2D CONSTRAINT: We only have X (time) and Y (price) axes available. The Z-axis (depth) is simulated through visual projection techniques (line styles, shading).
INTENDED USE
This tool is designed for traders and analysts who study Bradley Cowan's geometric market analysis methods. It helps visualize:
- Market structure in geometric terms
- Potential support/resistance zones at cube edges
- Cycle timing relationships using √2 and √3 ratios
- Harmonic price-time relationships
The cube projection should be used as one component of a comprehensive analysis approach, combined with other technical tools and fundamental analysis.
MATHEMATICAL FOUNDATION
While the visual representation involves approximations, the core √3 relationship is mathematically sound:
- For any cube, the body diagonal = √3 × side length
- The face diagonal = √2 × side length
- These ratios are preserved in the price dimension calculations
HOW TO USE
1. Select your starting date (Point A) - typically a significant low or high
2. Select your ending date (Point E) - the opposite extreme pivot
3. The indicator automatically constructs the cube geometry
4. Analyze the cube edges, diagonals, and faces for market structure insights
5. Adjust colors and opacity to suit your chart aesthetic
TECHNICAL NOTES
- Works on all timeframes and instruments
- Best viewed on charts with sufficient historical data
- Cube updates in real-time as new bars form
- Range selection is marked with vertical lines and shading
- Calculator table shows Point A, Point E, side length, and bar measurements
ACKNOWLEDGMENT
This indicator is based on the geometric market analysis principles developed by Bradley F. Cowan. Users are encouraged to study Cowan's original works for deeper understanding of the theoretical framework.
DISCLAIMER
This indicator is for educational and analytical purposes only. It does not constitute financial advice. Past performance does not guarantee future results. Always conduct your own research and risk management before making trading decisions.
Indicator

DynLenLibLibrary "DynLenLib"
sum_dyn(src, len)
Parameters:
src (float)
len (int)
lag_dyn(src, len)
Parameters:
src (float)
len (int)
highest_dyn(src, len)
Parameters:
src (float)
len (int)
lowest_dyn(src, len)
Parameters:
src (float)
len (int)
var_dyn(src, len)
Parameters:
src (float)
len (int)
stdev_dyn(src, len)
Parameters:
src (float)
len (int)
hl2()
hlc3()
ohlc4()
sma_dyn(src, len)
Parameters:
src (float)
len (int)
ema_dyn(src, len)
Parameters:
src (float)
len (int)
rma_dyn(src, len)
Parameters:
src (float)
len (int)
smma_dyn(src, len)
Parameters:
src (float)
len (int)
wma_dyn(src, len)
Parameters:
src (float)
len (int)
vwma_dyn(price, vol, len)
Parameters:
price (float)
vol (float)
len (int)
hma_dyn(src, len)
Parameters:
src (float)
len (int)
dema_dyn(src, len)
Parameters:
src (float)
len (int)
tema_dyn(src, len)
Parameters:
src (float)
len (int)
kama_dyn(src, erLen, fastLen, slowLen)
Parameters:
src (float)
erLen (int)
fastLen (int)
slowLen (int)
mcginley_dyn(src, len)
Parameters:
src (float)
len (int)
median_price()
true_range()
atr_dyn(len)
Parameters:
len (int)
bbands_dyn(src, len, mult)
Parameters:
src (float)
len (int)
mult (float)
bb_percent_b(src, len, mult)
Parameters:
src (float)
len (int)
mult (float)
bb_bandwidth(src, len, mult)
Parameters:
src (float)
len (int)
mult (float)
keltner_dyn(src, lenEMA, lenATR, multATR)
Parameters:
src (float)
lenEMA (int)
lenATR (int)
multATR (float)
donchian_dyn(len)
Parameters:
len (int)
choppiness_index(len)
Parameters:
len (int)
vol_stop(lenATR, mult)
Parameters:
lenATR (int)
mult (float)
roc_dyn(src, len)
Parameters:
src (float)
len (int)
rsi_dyn(src, len)
Parameters:
src (float)
len (int)
stoch_dyn(kLen, dLen, smoothK)
Parameters:
kLen (int)
dLen (int)
smoothK (int)
stoch_rsi_dyn(rsiLen, stochLen, kSmooth, dLen)
Parameters:
rsiLen (int)
stochLen (int)
kSmooth (int)
dLen (int)
cci_dyn(src, len)
Parameters:
src (float)
len (int)
cmo_dyn(src, len)
Parameters:
src (float)
len (int)
trix_dyn(len)
Parameters:
len (int)
tsi_dyn(shortLen, longLen)
Parameters:
shortLen (int)
longLen (int)
ultimate_osc(len1, len2, len3)
Parameters:
len1 (int)
len2 (int)
len3 (int)
dpo_dyn(src, len)
Parameters:
src (float)
len (int)
willr_dyn(len)
Parameters:
len (int)
macd_dyn(src, fastLen, slowLen, sigLen)
Parameters:
src (float)
fastLen (int)
slowLen (int)
sigLen (int)
ppo_dyn(src, fastLen, slowLen, sigLen)
Parameters:
src (float)
fastLen (int)
slowLen (int)
sigLen (int)
aroon_dyn(len)
Parameters:
len (int)
dmi_adx_dyn(diLen, adxLen)
Parameters:
diLen (int)
adxLen (int)
vortex_dyn(len)
Parameters:
len (int)
coppock_dyn(rocLen1, rocLen2, wmaLen)
Parameters:
rocLen1 (int)
rocLen2 (int)
wmaLen (int)
rvi_dyn(len)
Parameters:
len (int)
price_osc_dyn(src, fastLen, slowLen)
Parameters:
src (float)
fastLen (int)
slowLen (int)
rci_dyn(src, len)
Parameters:
src (float)
len (int)
obv()
pvt()
cmf_dyn(len)
Parameters:
len (int)
adl()
chaikin_osc_dyn(fastLen, slowLen)
Parameters:
fastLen (int)
slowLen (int)
mfi_dyn(len)
Parameters:
len (int)
volume_osc_dyn(fastLen, slowLen)
Parameters:
fastLen (int)
slowLen (int)
up_down_volume()
cvd()
supertrend_dyn(atrLen, mult)
Parameters:
atrLen (int)
mult (float)
envelopes_dyn(src, len, pct)
Parameters:
src (float)
len (int)
pct (float)
linreg_line_slope(src, len)
Parameters:
src (float)
len (int)
lsma_dyn(src, len)
Parameters:
src (float)
len (int)
corrcoef_dyn(a, b, len)
Parameters:
a (float)
b (float)
len (int)
psar(step, maxStep)
Parameters:
step (float)
maxStep (float)
pivots_standard()
williams_alligator(src, jawLen, teethLen, lipsLen)
Parameters:
src (float)
jawLen (int)
teethLen (int)
lipsLen (int)
twap_dyn(src, len)
Parameters:
src (float)
len (int)
vwap_anchored(price, volume, reset)
Parameters:
price (float)
volume (float)
reset (bool)
performance_pct(len)
Parameters:
len (int) Library
