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
Market Geometry
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.
Pine Script® 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.
Pine Script® 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.
Pine Script® 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.
Pine Script® 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.
Pine Script® 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.
Pine Script® 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
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Pine Script® indicator
SlopeUtilsLibrary "SlopeUtils"
calcSlope(src, atr_series, length)
Calculates a normalized slope based on price change relative to ATR.
Parameters:
src (float) : (series float) The source input (e.g., close).
atr_series (float) : (series float) The ATR value for normalization.
length (simple int) : (simple int) The lookback period for the slope calculation.
Returns: (float) The normalized slope value.
Pine Script® 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).
Pine Script® 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
Pine Script® 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.
Pine Script® 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)
Pine Script® library
PubLibPivotLibrary "PubLibPivot"
Pivot detection library for harmonic pattern analysis - Fractal and ZigZag methods with validation and utility functions
fractalPivotHigh(depth)
Fractal pivot high condition
Parameters:
depth (int)
Returns: bool
fractalPivotLow(depth)
Fractal pivot low condition
Parameters:
depth (int)
Returns: bool
fractalPivotHighPrice(depth, occurrence)
Get fractal pivot high price
Parameters:
depth (int)
occurrence (simple int)
Returns: float
fractalPivotLowPrice(depth, occurrence)
Get fractal pivot low price
Parameters:
depth (int)
occurrence (simple int)
Returns: float
fractalPivotHighBarIndex(depth, occurrence)
Get fractal pivot high bar index
Parameters:
depth (int)
occurrence (simple int)
Returns: int
fractalPivotLowBarIndex(depth, occurrence)
Get fractal pivot low bar index
Parameters:
depth (int)
occurrence (simple int)
Returns: int
zigzagPivotHigh(deviation, backstep, useATR, atrLength)
ZigZag pivot high condition
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
Returns: bool
zigzagPivotLow(deviation, backstep, useATR, atrLength)
ZigZag pivot low condition
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
Returns: bool
zigzagPivotHighPrice(deviation, backstep, useATR, atrLength, occurrence)
Get ZigZag pivot high price
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
occurrence (simple int)
Returns: float
zigzagPivotLowPrice(deviation, backstep, useATR, atrLength, occurrence)
Get ZigZag pivot low price
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
occurrence (simple int)
Returns: float
zigzagPivotHighBarIndex(deviation, backstep, useATR, atrLength, occurrence)
Get ZigZag pivot high bar index
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
occurrence (simple int)
Returns: int
zigzagPivotLowBarIndex(deviation, backstep, useATR, atrLength, occurrence)
Get ZigZag pivot low bar index
Parameters:
deviation (float)
backstep (int)
useATR (bool)
atrLength (simple int)
occurrence (simple int)
Returns: int
isValidPivotVolume(pivotPrice, pivotBarIndex, minVolumeRatio, volumeLength)
Validate pivot quality based on volume
Parameters:
pivotPrice (float)
pivotBarIndex (int)
minVolumeRatio (float)
volumeLength (int)
Returns: bool
isValidPivotATR(pivotPrice, lastPivotPrice, minATRMultiplier, atrLength)
Validate pivot based on minimum ATR movement
Parameters:
pivotPrice (float)
lastPivotPrice (float)
minATRMultiplier (float)
atrLength (simple int)
Returns: bool
isValidPivotTime(pivotBarIndex, lastPivotBarIndex, minBars)
Validate pivot based on minimum time between pivots
Parameters:
pivotBarIndex (int)
lastPivotBarIndex (int)
minBars (int)
Returns: bool
isPivotConfirmed(pivotBarIndex, depth)
Check if pivot is not repainting (confirmed)
Parameters:
pivotBarIndex (int)
depth (int)
Returns: bool
addPivotToArray(pivotArray, barArray, pivotPrice, pivotBarIndex, maxSize)
Add pivot to array with validation
Parameters:
pivotArray (array)
barArray (array)
pivotPrice (float)
pivotBarIndex (int)
maxSize (int)
Returns: array - updated pivot array
getPivotFromArray(pivotArray, barArray, index)
Get pivot from array by index
Parameters:
pivotArray (array)
barArray (array)
index (int)
Returns: tuple - (price, bar_index)
getPivotsInRange(pivotArray, barArray, startIndex, count)
Get all pivots in range
Parameters:
pivotArray (array)
barArray (array)
startIndex (int)
count (int)
Returns: tuple, array> - (prices, bar_indices)
pivotDistance(barIndex1, barIndex2)
Calculate distance between two pivots in bars
Parameters:
barIndex1 (int)
barIndex2 (int)
Returns: int - distance in bars
pivotPriceRatio(price1, price2)
Calculate price ratio between two pivots
Parameters:
price1 (float)
price2 (float)
Returns: float - price ratio
pivotRetracementRatio(startPrice, endPrice, currentPrice)
Calculate retracement ratio
Parameters:
startPrice (float)
endPrice (float)
currentPrice (float)
Returns: float - retracement ratio (0-1)
pivotExtensionRatio(startPrice, endPrice, currentPrice)
Calculate extension ratio
Parameters:
startPrice (float)
endPrice (float)
currentPrice (float)
Returns: float - extension ratio (>1 for extension)
isInFibZone(startPrice, endPrice, currentPrice, fibLevel, tolerance)
Check if price is in Fibonacci retracement zone
Parameters:
startPrice (float)
endPrice (float)
currentPrice (float)
fibLevel (float)
tolerance (float)
Returns: bool - true if in zone
getPivotType(pivotPrice, pivotBarIndex, lookback)
Get pivot type (high/low) based on surrounding prices
Parameters:
pivotPrice (float)
pivotBarIndex (int)
lookback (int)
Returns: string - "high", "low", or "unknown"
calculatePivotStrength(pivotPrice, pivotBarIndex, lookback)
Calculate pivot strength based on volume and price action
Parameters:
pivotPrice (float)
pivotBarIndex (int)
lookback (int)
Returns: float - strength score (0-100)
Pine Script® library
XABCD_HarmonicsLibrary for detecting harmonic patterns using ZigZag pivots or custom swing points. Supports Butterfly, Gartley, Bat, and Crab patterns with automatic Fibonacci ratio validation and optional D-point projection using extremes. Returns detailed PatternResult including structure points and target projection. Ideal for technical analysis, algorithmic detection, or overlay visualizations.
Pine Script® library
juan_dibujosLibrary "juan_dibujos"
extend_line(lineId, labelId)
: Extend specific line with its label
Parameters:
lineId (line)
labelId (label)
update_line_coordinates(lineId, labelId, x1, y1, x2, y2)
: Update specific line coordinates with its label
Parameters:
lineId (line)
labelId (label)
x1 (int)
y1 (float)
x2 (int)
y2 (float)
update_label_coordinates(labelId, value)
: Update coordinates of a label
Parameters:
labelId (label)
value (float)
delete_line(lineId, labelId)
: Delete specific line with its label
Parameters:
lineId (line)
labelId (label)
update_box_coordinates(boxId, labelId, left, top, right, bottom)
: Update specific box coordinates with its label
Parameters:
boxId (box)
labelId (label)
left (int)
top (float)
right (int)
bottom (float)
delete_box(boxId, labelId)
: Delete specific box with its label
Parameters:
boxId (box)
labelId (label)
Pine Script® library
DrawZigZag🟩 OVERVIEW
This library draws zigzag lines for existing pivots. It is designed to be simple to use. If your script creates pivots and you want to join them up while handling edge cases, this library does that quickly and efficiently. If you want your pivots created for you, choose one of the many other zigzag libraries that do that.
🟩 HOW TO USE
Pine Script libraries contain reusable code for importing into indicators. You do not need to copy any code out of here. Just import the library and call the function you want.
For example, for version 1 of this library, import it like this:
import SimpleCryptoLife/DrawZigZag/1
See the EXAMPLE USAGE sections within the library for examples of calling the functions.
For more information on libraries and incorporating them into your scripts, see the Libraries section of the Pine Script User Manual.
🟩 WHAT IT DOES
I looked at every zigzag library on TradingView, after finishing this one. They all seemed to fall into two groups in terms of functionality:
• Create the pivots themselves, using a combination of Williams-style pivots and sometimes price distance.
• Require an array of pivot information, often in a format that uses user-defined types.
My library takes a completely different approach.
Firstly, it only does the drawing. It doesn't calculate the pivots for you. This isn't laziness. There are so many ways to define pivots and that should be up to you. If you've followed my work on market structure you know what I think of Williams pivots.
Secondly, when you pass information about your pivots to the library function, you only need the minimum of pivot information -- whether it's a High or Low pivot, the price, and the bar index. Pass these as normal variables -- bools, ints, and floats -- on the fly as your pivots confirm. It is completely agnostic as to how you derive your pivots. If they are confirmed an arbitrary number of bars after they happen, that's fine.
So why even bother using it if all it does it draw some lines?
Turns out there is quite some logic needed in order to connect highs and lows in the right way, and to handle edge cases. This is the kind of thing one can happily outsource.
🟩 THE RULES
• Zigs and zags must alternate between Highs and Lows. We never connect a High to a High or a Low to a Low.
• If a candle has both a High and Low pivot confirmed on it, the first line is drawn to the end of the candle that is the opposite to the previous pivot. Then the next line goes vertically through the candle to the other end, and then after that continues normally.
• If we draw a line up from a Low to a High pivot, and another High pivot comes in higher, we *extend* the line up, and the same for lines down. Yes this is a form of repainting. It is in my opinion the only way to end up with a correct structure.
• We ignore lower highs on the way up and higher lows on the way down.
🟩 WHAT'S COOL ABOUT THIS LIBRARY
• It's simple and lightweight: no exported user-defined types, no helper methods, no matrices.
• It's really fast. In my profiling it runs at about ~50ms, and changing the options (e.g., trimming the array) doesn't make very much difference.
• You only need to call one function, which does all the calculations and draws all lines.
• There are two variations of this function though -- one simple function that just draws lines, and one slightly more advanced method that modifies an array containing the lines. If you don't know which one you want, use the simpler one.
🟩 GEEK STUFF
• There are no dependencies on other libraries.
• I tried to make the logic as clear as I could and comment it appropriately.
• In the `f_drawZigZags` function, the line variable is declared using the `var` keyword *inside* the function, for simplicity. For this reason, it persists between function calls *only* if the function is called from the global scope or a local if block. In general, if a function is called from inside a loop , or multiple times from different contexts, persistent variables inside that function are re-initialised on each call. In this case, this re-initialisation would mean that the function loses track of the previous line, resulting in incorrect drawings. This is why you cannot call the `f_drawZigZags` function from a loop (not that there's any reason to). The `m_drawZigZagsArray` does not use any internal `var` variables.
• The function itself takes a Boolean parameter `_showZigZag`, which turns the drawings on and off, so there is no need to call the function conditionally. In the examples, we do call the functions from an if block, purely as an illustration of how to increase performance by restricting the amount of code that needs to be run.
🟩 BRING ON THE FUNCTIONS
f_drawZigZags(_showZigZag, _isHighPivot, _isLowPivot, _highPivotPrice, _lowPivotPrice, _pivotIndex, _zigzagWidth, _lineStyle, _upZigColour, _downZagColour)
This function creates or extends the latest zigzag line. Takes real-time information about pivots and draws lines. It does not calculate the pivots. It must be called once per script and cannot be called from a loop.
Parameters:
_showZigZag (bool) : Whether to show the zigzag lines.
_isHighPivot (bool) : Whether the current bar confirms a high pivot. Note that pivots are confirmed after the bar in which they occur.
_isLowPivot (bool) : Whether the current bar confirms a low pivot.
_highPivotPrice (float) : The price of the high pivot that was confirmed this bar. It is NOT the high price of the current bar.
_lowPivotPrice (float) : The price of the low pivot that was confirmed this bar. It is NOT the low price of the current bar.
_pivotIndex (int) : The bar index of the pivot that was confirmed this bar. This is not an offset. It's the `bar_index` value of the pivot.
_zigzagWidth (int) : The width of the zigzag lines.
_lineStyle (string) : The style of the zigzag lines.
_upZigColour (color) : The colour of the up zigzag lines.
_downZagColour (color) : The colour of the down zigzag lines.
Returns: The function has no explicit returns. As a side effect, it draws or updates zigzag lines.
method m_drawZigZagsArray(_a_zigZagLines, _showZigZag, _isHighPivot, _isLowPivot, _highPivotPrice, _lowPivotPrice, _pivotIndex, _zigzagWidth, _lineStyle, _upZigColour, _downZagColour, _trimArray)
Namespace types: array
Parameters:
_a_zigZagLines (array)
_showZigZag (bool) : Whether to show the zigzag lines.
_isHighPivot (bool) : Whether the current bar confirms a high pivot. Note that pivots are usually confirmed after the bar in which they occur.
_isLowPivot (bool) : Whether the current bar confirms a low pivot.
_highPivotPrice (float) : The price of the high pivot that was confirmed this bar. It is NOT the high price of the current bar.
_lowPivotPrice (float) : The price of the low pivot that was confirmed this bar. It is NOT the low price of the current bar.
_pivotIndex (int) : The bar index of the pivot that was confirmed this bar. This is not an offset. It's the `bar_index` value of the pivot.
_zigzagWidth (int) : The width of the zigzag lines.
_lineStyle (string) : The style of the zigzag lines.
_upZigColour (color) : The colour of the up zigzag lines.
_downZagColour (color) : The colour of the down zigzag lines.
_trimArray (bool) : If true, the array of lines is kept to a maximum size of two lines (the line elements are not deleted). If false (the default), the array is kept to a maximum of 500 lines (the maximum number of line objects a single Pine script can display).
Returns: This function has no explicit returns but it modifies a global array of zigzag lines.
Pine Script® library
FvgObject█ OVERVIEW
This library provides a suite of methods designed to manage the visual representation and lifecycle of Fair Value Gap (FVG) objects on a Pine Script™ chart. It extends the `fvgObject` User-Defined Type (UDT) by attaching object-oriented functionalities for drawing, updating, and deleting FVG-related graphical elements. The primary goal is to encapsulate complex drawing logic, making the main indicator script cleaner and more focused on FVG detection and state management.
█ CONCEPTS
This library is built around the idea of treating each Fair Value Gap as an "object" with its own visual lifecycle on the chart. This is achieved by defining methods that operate directly on instances of the `fvgObject` UDT.
Object-Oriented Approach for FVGs
Pine Script™ v6 introduced the ability to define methods for User-Defined Types (UDTs). This library leverages this feature by attaching specific drawing and state management functions (methods) directly to the `fvgObject` type. This means that instead of calling global functions with an FVG object as a parameter, you call methods *on* the FVG object itself (e.g., `myFvg.updateDrawings(...)`). This approach promotes better code organization and a more intuitive way to interact with FVG data.
FVG Visual Lifecycle Management
The core purpose of this library is to manage the complete visual journey of an FVG on the chart. This lifecycle includes:
Initial Drawing: Creating the first visual representation of a newly detected FVG, including its main box and optionally its midline and labels.
State Updates & Partial Fills: Modifying the FVG's appearance as it gets partially filled by price. This involves drawing a "mitigated" portion of the box and adjusting the `currentTop` or `currentBottom` of the remaining FVG.
Full Mitigation & Tested State: Handling how an FVG is displayed once fully mitigated. Depending on user settings, it might be hidden, or its box might change color/style to indicate it has been "tested." Mitigation lines can also be managed (kept or deleted).
Midline Interaction: Visually tracking if the price has touched the FVG's 50% equilibrium level (midline).
Visibility Control: Dynamically showing or hiding FVG drawings based on various criteria, such as user settings (e.g., hide mitigated FVGs, timeframe-specific visibility) or external filters (e.g., proximity to current price).
Deletion: Cleaning up all drawing objects associated with an FVG when it's no longer needed or when settings dictate its removal.
Centralized Drawing Logic
By encapsulating all drawing-related operations within the methods of this library, the main indicator script is significantly simplified. The main script can focus on detecting FVGs and managing their state (e.g., in arrays), while delegating the complex task of rendering and updating them on the chart to the methods herein.
Interaction with `fvgObject` and `drawSettings` UDTs
All methods within this library operate on an instance of the `fvgObject` UDT. This `fvgObject` holds not only the FVG's price/time data and state (like `isMitigated`, `currentTop`) but also the IDs of its associated drawing elements (e.g., `boxId`, `midLineId`).
The appearance of these drawings (colors, styles, visibility, etc.) is dictated by a `drawSettings` UDT instance, which is passed as a parameter to most drawing-related methods. This `drawSettings` object is typically populated from user inputs in the main script, allowing for extensive customization.
Stateful Drawing Object Management
The library's methods manage Pine Script™ drawing objects (boxes, lines, labels) by storing their IDs within the `fvgObject` itself (e.g., `fvgObject.boxId`, `fvgObject.mitigatedBoxId`, etc.). Methods like `draw()` create these objects and store their IDs, while methods like `updateDrawings()` modify them, and `deleteDrawings()` removes them using these stored IDs.
Drawing Optimization
The `updateDrawings()` method, which is the most comprehensive drawing management function, incorporates optimization logic. It uses `prev_*` fields within the `fvgObject` (e.g., `prevIsMitigated`, `prevCurrentTop`) to store the FVG's state from the previous bar. By comparing the current state with the previous state, and also considering changes in visibility or relevant drawing settings, it can avoid redundant and performance-intensive drawing operations if nothing visually significant has changed for that FVG.
█ METHOD USAGE AND WORKFLOW
The methods in this library are designed to be called in a logical sequence as an FVG progresses through its lifecycle. A crucial prerequisite for all visual methods in this library is a properly populated `drawSettings` UDT instance, which dictates every aspect of an FVG's appearance, from colors and styles to visibility and labels. This `settings` object must be carefully prepared in the main indicator script, typically based on user inputs, before being passed to these methods.
Here’s a typical workflow within a main indicator script:
1. FVG Instance Creation (External to this library)
An `fvgObject` instance is typically created by functions in another library (e.g., `FvgCalculations`) when a new FVG pattern is identified. This object will have its core properties (top, bottom, startTime, isBullish, tfType) initialized.
2. Initial Drawing (`draw` method)
Once a new `fvgObject` is created and its initial visibility is determined:
Call the `myFvg.draw(settings)` method on the new FVG object.
`settings` is an instance of the `drawSettings` UDT, containing all relevant visual configurations.
This method draws the primary FVG box, its midline (if enabled in `settings`), and any initial labels. It also initializes the `currentTop` and `currentBottom` fields of the `fvgObject` if they are `na`, and stores the IDs of the created drawing objects within the `fvgObject`.
3. Per-Bar State Updates & Interaction Checks
On each subsequent bar, for every active `fvgObject`:
Interaction Check (External Logic): It's common to first use logic (e.g., from `FvgCalculations`' `fvgInteractionCheck` function) to determine if the current bar's price interacts with the FVG.
State Field Updates (External Logic): Before calling the `FvgObjectLib` methods below, ensure that your `fvgObject`'s state fields (such as `isMitigated`, `currentTop`, `currentBottom`, `isMidlineTouched`) are updated using the current bar's price data and relevant functions from other libraries (e.g., `FvgCalculations`' `checkMitigation`, `checkPartialMitigation`, etc.). This library's methods render the FVG based on these pre-updated state fields.
If interaction occurs and the FVG is not yet fully mitigated:
Full Mitigation Update (`updateMitigation` method): Call `myFvg.updateMitigation(high, low)`. This method updates `myFvg.isMitigated` and `myFvg.mitigationTime` if full mitigation occurs, based on the interaction determined by external logic.
Partial Fill Update (`updatePartialFill` method): If not fully mitigated, call `myFvg.updatePartialFill(high, low, settings)`. This method updates `myFvg.currentTop` or `myFvg.currentBottom` and adjusts drawings to show the filled portion, again based on prior interaction checks and fill level calculations.
Midline Touch Check (`checkMidlineTouch` method): Call `myFvg.checkMidlineTouch(high, low)`. This method updates `myFvg.isMidlineTouched` if the price touches the FVG's 50% level.
4. Comprehensive Visual Update (`updateDrawings` method)
After the FVG's state fields have been potentially updated by external logic and the methods in step 3:
Call `myFvg.updateDrawings(isVisibleNow, settings)` on each FVG object.
`isVisibleNow` is a boolean indicating if the FVG should currently be visible.
`settings` is the `drawSettings` UDT instance.
This method synchronizes the FVG's visual appearance with its current state and settings, managing all drawing elements (boxes, lines, labels), their styles, and visibility. It efficiently skips redundant drawing operations if the FVG's state or visibility has not changed, thanks to its internal optimization using `prev_*` fields, which are also updated by this method.
5. Deleting Drawings (`deleteDrawings` method)
When an FVG object is no longer tracked:
Call `myFvg.deleteDrawings(deleteTestedToo)`.
This method removes all drawing objects associated with that `fvgObject`.
This workflow ensures that FVG visuals are accurately maintained throughout their existence on the chart.
█ NOTES
Dependencies: This library relies on `FvgTypes` for `fvgObject` and `drawSettings` definitions, and its methods (`updateMitigation`, `updatePartialFill`) internally call functions from `FvgCalculations`.
Drawing Object Management: Be mindful of TradingView's limits on drawing objects per script. The main script should manage the number of active FVG objects.
Performance and `updateDrawings()`: The `updateDrawings()` method is comprehensive. Its internal optimization (checking `hasStateChanged` based on `prev_*` fields) is crucial for performance. Call it judiciously.
Role of `settings.currentTime`: The `currentTime` field in `drawSettings` is key for positioning time-dependent elements like labels and the right edge of non-extended drawings.
Mutability of `fvgObject` Instances: Methods in this library directly modify the `fvgObject` instance they are called upon (e.g., its state fields and drawing IDs).
Drawing ID Checks: Methods generally check if drawing IDs are `na` before acting on them, preventing runtime errors.
█ EXPORTED FUNCTIONS
method draw(this, settings)
Draws the initial visual representation of the FVG object on the chart. This includes the main FVG box, its midline (if enabled), and a label
(if enabled for the specific timeframe). This method is typically invoked
immediately after an FVG is first detected and its initial properties are set. It uses drawing settings to customize the appearance based on the FVG's timeframe type.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance to be drawn. Core properties (top, bottom,
startTime, isBullish, tfType) should be pre-initialized. This method will
initialize boxId, midLineId, boxLabelId (if applicable), and
currentTop/currentBottom (if currently na) on this object.
settings (drawSettings type from no1x/FvgTypes/1) : A drawSettings object providing all visual parameters. Reads display settings (colors, styles, visibility for boxes, midlines, labels,
box extension) relevant to this.tfType. settings.currentTime is used for
positioning labels and the right boundary of non-extended boxes.
method updateMitigation(this, highVal, lowVal)
Checks if the FVG has been fully mitigated by the current bar's price action.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance. Reads this.isMitigated, this.isVisible,
this.isBullish, this.top, this.bottom. Updates this.isMitigated and
this.mitigationTime if full mitigation occurs.
highVal (float) : The high price of the current bar, used for mitigation check.
lowVal (float) : The low price of the current bar, used for mitigation check.
method updatePartialFill(this, highVal, lowVal, settings)
Checks for and processes partial fills of the FVG.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance. Reads this.isMitigated, this.isVisible,
this.isBullish, this.currentTop, this.currentBottom, original this.top/this.bottom,
this.startTime, this.tfType, this.isLV. Updates this.currentTop or
this.currentBottom, creates/updates this.mitigatedBoxId, and may update this.boxId's
top/bottom to reflect the filled portion.
highVal (float) : The high price of the current bar, used for partial fill check.
lowVal (float) : The low price of the current bar, used for partial fill check.
settings (drawSettings type from no1x/FvgTypes/1) : The drawing settings. Reads timeframe-specific colors for mitigated
boxes (e.g., settings.mitigatedBullBoxColor, settings.mitigatedLvBullColor),
box extension settings (settings.shouldExtendBoxes, settings.shouldExtendMtfBoxes, etc.),
and settings.currentTime to style and position the mitigatedBoxId and potentially adjust the main boxId.
method checkMidlineTouch(this, highVal, lowVal)
Checks if the FVG's midline (50% level or Equilibrium) has been touched.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance. Reads this.midLineId, this.isMidlineTouched,
this.top, this.bottom. Updates this.isMidlineTouched if a touch occurs.
highVal (float) : The high price of the current bar, used for midline touch check.
lowVal (float) : The low price of the current bar, used for midline touch check.
method deleteDrawings(this, deleteTestedToo)
Deletes all visual drawing objects associated with this FVG object.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance. Deletes drawings referenced by boxId,
mitigatedBoxId, midLineId, mitLineId, boxLabelId, mitLineLabelId,
and potentially testedBoxId, keptMitLineId. Sets these ID fields to na.
deleteTestedToo (simple bool) : If true, also deletes drawings for "tested" FVGs
(i.e., testedBoxId and keptMitLineId).
method updateDrawings(this, isVisibleNow, settings)
Manages the comprehensive update of all visual elements of an FVG object
based on its current state (e.g., active, mitigated, partially filled) and visibility. It handles the drawing, updating, or deletion of FVG boxes (main and mitigated part),
midlines, mitigation lines, and their associated labels. Visibility is determined by the isVisibleNow parameter and relevant settings
(like settings.shouldHideMitigated or timeframe-specific show flags). This method is central to the FVG's visual lifecycle and includes optimization
to avoid redundant drawing operations if the FVG's relevant state or appearance
settings have not changed since the last bar. It also updates the FVG object's internal prev_* state fields for future optimization checks.
Namespace types: types.fvgObject
Parameters:
this (fvgObject type from no1x/FvgTypes/1) : The FVG object instance to update. Reads most state fields (e.g.,
isMitigated, currentTop, tfType, etc.) and updates all drawing ID fields
(boxId, midLineId, etc.), this.isVisible, and all this.prev_* state fields.
isVisibleNow (bool) : A flag indicating whether the FVG should be currently visible. Typically determined by external logic (e.g., visual range filter). Affects
whether active FVG drawings are created/updated or deleted by this method.
settings (drawSettings type from no1x/FvgTypes/1) : A fully populated drawSettings object. This method extensively
reads its fields (colors, styles, visibility toggles, timeframe strings, etc.)
to render FVG components according to this.tfType and current state. settings.currentTime is critical for positioning elements like labels and extending drawings.
Pine Script® library
HexworksSharedUtilitiesLibrary "HexworksSharedUtilities"
Shared global utilities that can be used for
- creating bounded queues from primitives
- checking visibility of objects having Bounds on both (x, y) axes
- checking if a line is too long
method offer(history, value)
Namespace types: FloatHistory
Parameters:
history (FloatHistory)
value (simple float)
method offer(history, value)
Namespace types: IntHistory
Parameters:
history (IntHistory)
value (simple int)
method offer(history, value)
Namespace types: StringHistory
Parameters:
history (StringHistory)
value (simple string)
method offer(history, value)
Namespace types: BoolHistory
Parameters:
history (BoolHistory)
value (simple bool)
method toString(point)
Namespace types: chart.point
Parameters:
point (chart.point)
method toString(num)
Namespace types: simple float, input float, const float
Parameters:
num (simple float)
method toString(num)
Namespace types: simple int, input int, const int
Parameters:
num (simple int)
method toString(value)
Namespace types: simple bool, input bool, const bool
Parameters:
value (simple bool)
method toString(l)
Namespace types: series line
Parameters:
l (line)
method isLineTooLong(fromPoint, toPoint)
Namespace types: chart.point
Parameters:
fromPoint (chart.point)
toPoint (chart.point)
method isTooLong(l)
Namespace types: series line
Parameters:
l (line)
createVisibilityChecker()
method update(v)
Namespace types: VisibilityChecker
Parameters:
v (VisibilityChecker)
method canDraw(v)
Namespace types: VisibilityChecker
Parameters:
v (VisibilityChecker)
method isVisible(v, b)
Namespace types: VisibilityChecker
Parameters:
v (VisibilityChecker)
b (Bounds)
FloatHistory
Fields:
history (array)
maxLength (series int)
IntHistory
Fields:
history (array)
maxLength (series int)
StringHistory
Fields:
history (array)
maxLength (series int)
BoolHistory
Fields:
history (array)
maxLength (series int)
Bounds
Fields:
startIdx (series int)
endIdx (series int)
highValue (series float)
lowValue (series float)
VisibilityChecker
Fields:
leftVisibleBarIdx (series int)
rightVisibleBarIdx (series int)
maxDrawDistance (series int)
updatedAt (series int)
visibleHighest (series float)
visibleLowest (series float)
Pine Script® library
reversalchartpatternsLibrary "reversalchartpatterns"
User Defined Types and Methods for reversal chart patterns - Double Top, Double Bottom, Triple Top, Triple Bottom, Cup and Handle, Inverted Cup and Handle, Head and Shoulders, Inverse Head and Shoulders
method delete(this)
Deletes the drawing components of ReversalChartPatternDrawing object
Namespace types: ReversalChartPatternDrawing
Parameters:
this (ReversalChartPatternDrawing) : ReversalChartPatternDrawing object
Returns: current ReversalChartPatternDrawing object
method delete(this)
Deletes the drawing components of ReversalChartPattern object. In turn calls the delete of ReversalChartPatternDrawing
Namespace types: ReversalChartPattern
Parameters:
this (ReversalChartPattern) : ReversalChartPattern object
Returns: current ReversalChartPattern object
method lpush(this, obj, limit, deleteOld)
Array push with limited number of items in the array. Old items are deleted when new one comes and exceeds the limit
Namespace types: array
Parameters:
this (array) : array object
obj (ReversalChartPattern) : ReversalChartPattern object which need to be pushed to the array
limit (int) : max items on the array. Default is 10
deleteOld (bool) : If set to true, also deletes the drawing objects. If not, the drawing objects are kept but the pattern object is removed from array. Default is false.
Returns: current ReversalChartPattern object
method draw(this)
Draws the components of ReversalChartPatternDrawing
Namespace types: ReversalChartPatternDrawing
Parameters:
this (ReversalChartPatternDrawing) : ReversalChartPatternDrawing object
Returns: current ReversalChartPatternDrawing object
method draw(this)
Draws the components of ReversalChartPatternDrawing within the ReversalChartPattern object.
Namespace types: ReversalChartPattern
Parameters:
this (ReversalChartPattern) : ReversalChartPattern object
Returns: current ReversalChartPattern object
method scan(zigzag, patterns, errorPercent, shoulderStart, shoulderEnd, allowedPatterns, offset)
Scans zigzag for ReversalChartPattern occurences
Namespace types: zg.Zigzag
Parameters:
zigzag (Zigzag type from Trendoscope/Zigzag/11) : ZigzagTypes.Zigzag object having array of zigzag pivots and other information on each pivots
patterns (array) : Existing patterns array. Used for validating duplicates
errorPercent (float) : Error threshold for considering ratios. Default is 13
shoulderStart (float) : Starting range of shoulder ratio. Used for identifying shoulders, handles and necklines
shoulderEnd (float) : Ending range of shoulder ratio. Used for identifying shoulders, handles and necklines
allowedPatterns (array) : array of int containing allowed pattern types
offset (int) : Offset of zigzag to consider only confirmed pivots
Returns: int pattern type
method createPattern(zigzag, patternType, patternColor, properties, offset)
Create Pattern from ZigzagTypes.Zigzag object
Namespace types: zg.Zigzag
Parameters:
zigzag (Zigzag type from Trendoscope/Zigzag/11) : ZigzagTypes.Zigzag object having array of zigzag pivots and other information on each pivots
patternType (int) : Type of pattern being created. 1 - Double Tap, 2 - Triple Tap, 3 - Cup and Handle, 4 - Head and Shoulders
patternColor (color) : Color in which the patterns are drawn
properties (ReversalChartTradeProperties)
offset (int)
Returns: ReversalChartPattern object created
method getName(this)
get pattern name of ReversalChartPattern object
Namespace types: ReversalChartPattern
Parameters:
this (ReversalChartPattern) : ReversalChartPattern object
Returns: string name of the pattern
method getDescription(this)
get consolidated description of ReversalChartPattern object
Namespace types: ReversalChartPattern
Parameters:
this (ReversalChartPattern) : ReversalChartPattern object
Returns: string consolidated description
method init(this)
initializes the ReversalChartPattern object and creates sub object types
Namespace types: ReversalChartPattern
Parameters:
this (ReversalChartPattern) : ReversalChartPattern object
Returns: ReversalChartPattern current object
ReversalChartPatternDrawing
Type which holds the drawing objects for Reversal Chart Pattern Types
Fields:
patternLines (array type from Trendoscope/Drawing/2) : array of Line objects representing pattern
entry (Line type from Trendoscope/Drawing/2) : Entry price Line
targets (array type from Trendoscope/Drawing/2)
stop (Line type from Trendoscope/Drawing/2) : Stop price Line
patternLabel (Label type from Trendoscope/Drawing/2)
ReversalChartTradeProperties
Trade properties of ReversalChartPattern
Fields:
riskAdjustment (series float) : Risk Adjustment for calculation of stop
useFixedTarget (series bool) : Boolean flag saying use fixed target type wherever possible. If fixed target type is not possible, then risk reward/fib ratios are used for calculation of targets
variableTargetType (series int) : Integer value which defines whether to use fib based targets or risk reward based targets. 1 - Risk Reward, 2 - Fib Ratios
variableTargetRatios (array) : Risk reward or Fib Ratios to be used for calculation of targets when fixed target is not possible or not enabled
entryPivotForWm (series int) : which Pivot should be considered as entry point for WM patterns. 0 refers to the latest breakout pivot where as 5 refers to initial pivot of the pattern
ReversalChartPattern
Reversal Chart Pattern master type which holds the pattern components, drawings and trade details
Fields:
pivots (array type from Trendoscope/Zigzag/11) : Array of Zigzag Pivots forming the pattern
patternType (series int) : Defines the main type of pattern 1 - Double Tap, 1 - Triple Tap, 3 - Cup and Handle, 4 - Head and Shoulders, 5- W/M Patterns, 6 - Full Trend, 7 - Half Trend
patternColor (series color) : Color in which the pattern will be drawn on chart
properties (ReversalChartTradeProperties)
drawing (ReversalChartPatternDrawing) : ReversalChartPatternDrawing object which holds the drawing components
trade (Trade type from Trendoscope/TradeTracker/1) : TradeTracker.Trade object holding trade components
Pine Script® library
projectiontrackingLibrary "projectiontracking"
Library contains few data structures and methods for tracking harmonic patterns and projections via pinescript.
method erase(this)
erase Harmonic Projection Drawing
Namespace types: HarmonicProjectionDrawing
Parameters:
this (HarmonicProjectionDrawing) : HarmonicProjectionDrawing object
Returns: void
method erase(this)
erase HarmonicProjection
Namespace types: HarmonicProjection
Parameters:
this (HarmonicProjection) : HarmonicProjection object
Returns: void
method draw(this)
draw HarmonicProjection
Namespace types: HarmonicProjection
Parameters:
this (HarmonicProjection) : HarmonicProjection object
Returns: HarmonicProjection object
method getRanges(projectionPrzRanges, dir)
Convert PRZRange to Projection ranges
Namespace types: array
Parameters:
projectionPrzRanges (array type from Trendoscope/HarmonicMapLib/1) : array of PrzRange objects
dir (int) : Projection direction
Returns: array
ProjectionRange
Harmonic Projection Range
Fields:
patterns (array) : array of pattern names
start (series float) : Start Range
end (series float) : End Range
status (series int) : Projection Status
ProjectionProperties
Harmonic Projection Properties
Fields:
fillMajorTriangles (series bool) : Use linefill for major triangles
fillMinorTriangles (series bool) : Use linefill for minor triangles
majorFillTransparency (series int) : transparency of major triangles
minorFillTransparency (series int) : transparency of minor triangles
showXABC (series bool) : Show XABC labels
lblSizePivots (series string) : Pivot labels size
showRatios (series bool) : Show ratio labels
useLogScaleForScan (series bool) : Log scale is used for scanning projections
activateOnB (series bool) : Activate projections on reaching B
activationRatio (series float) : Use activation ratio for activation
confirmationRatio (series float) : Confirmation ratio of projection before removal
HarmonicProjectionDrawing
Harmonic Projection Projection drawing objects
Fields:
xa (series line) : line xa
ab (series line) : line ab
bc (series line) : line bc
xb (series line) : line xb
ac (series line) : line ac
x (series label) : Pivot label x
a (series label) : Pivot label a
b (series label) : Pivot label b
c (series label) : Pivot label c
xabRatio (series label) : Label XAB Ratio
abcRatio (series label) : Label ABC Ratio
HarmonicProjection
Harmonic Projection Projection object
Fields:
patternId (series int) : id of the pattern
dir (series int) : projection direction
x (chart.point) : Pivot X
a (chart.point) : Pivot A
b (chart.point) : Pivot B
c (chart.point) : Pivot C
patternColor (series color) : Color in which pattern is displayed
przRange (PrzRange type from Trendoscope/HarmonicMapLib/1) : PRZ Range
activationPrice (series float) : Projection activation price
reversalPrice (series float) : Projection reversal price
status (series int) : Projection status
properties (ProjectionProperties) : Projection properties
projectionRanges (array) : array of Projection Ranges
initialD (series float) : Initial D pivot
d (chart.point) : Pivot D
drawing (HarmonicProjectionDrawing) : HarmonicProjectionDrawing Object
Pine Script® library
HarmonicMapLibLibrary "HarmonicMapLib"
Harmonic Pattern Library implementation utilising maps
method tostring(this)
convert Range value to string
Namespace types: Range
Parameters:
this (Range) : Range value
Returns: converted string representation
method tostring(this)
convert array of Range value to string
Namespace types: array
Parameters:
this (array) : array object
Returns: converted string representation
method tostring(this)
convert map of string to Range value to string
Namespace types: map
Parameters:
this (map) : map object
Returns: converted string representation
method tostring(this)
convert RatioMap to string
Namespace types: RatioMap
Parameters:
this (RatioMap) : RatioMap object
Returns: converted string representation
method tostring(this)
convert array of RatioMap to string
Namespace types: array
Parameters:
this (array) : array object
Returns: converted string representation
method tostring(this)
convert map of string to RatioMap to string
Namespace types: map
Parameters:
this (map) : map object
Returns: converted string representation
method tostring(this)
convert map of string to bool to string
Namespace types: map
Parameters:
this (map) : map object
Returns: converted string representation
method tostring(this)
convert PrzRange to string
Namespace types: PrzRange
Parameters:
this (PrzRange) : PrzRange object
Returns: converted string representation
method tostring(this)
convert array of PrzRange to string
Namespace types: array
Parameters:
this (array) : array object
Returns: converted string representation
getHarmonicMap()
Creates the RatioMap for harmonic patterns
Returns: map haronic ratio rules for all patterns
method evaluate(patternsMap, pattern, ratioRange, properties, ratioValue)
evaluates harmonic ratio range
Namespace types: map
Parameters:
patternsMap (map) : parameter containing valid pattern names
pattern (string) : Pattern type to be evaluated
ratioRange (Range) : ratio range to be checked
properties (ScanProperties) : Scan Properties
ratioValue (float)
Returns: void
method evaluate(przRange, pattern, ratioRange, priceRange, properties)
Evaluate PRZ ranges
Namespace types: map
Parameters:
przRange (map)
pattern (string) : Pattern name
ratioRange (Range) : Range of ratio for the pattern
priceRange (Range) : Price range based on ratio
properties (ScanProperties) : ScanProperties object
Returns: void
method scanRatio(currentPatterns, rules, properties, ratioName, ratioValue)
Scan for particular named ratio of harmonic pattern to filter valid patterns
Namespace types: map
Parameters:
currentPatterns (map) : Current valid patterns map
rules (map) : map Harmonic ratio rules
properties (ScanProperties) : ScanProperties object
ratioName (string) : Specific ratio name
ratioValue (float) : ratio value to be checked
Returns: updated currentPatterns object
method scanPatterns(patterns, x, a, b, c, d, properties)
Scan for patterns based on X, A, B, C, D values
Namespace types: map
Parameters:
patterns (map) : List of allowed patterns
x (float) : X coordinate
a (float) : A coordinate
b (float) : B coordinate
c (float) : C coordinate
d (float) : D coordinate
properties (ScanProperties) : ScanProperties object. If na, default values are initialised
Returns: updated valid patterns map
method scanProjections(patterns, x, a, b, c, properties)
Scan for projections based on X, A, B, C values
Namespace types: map
Parameters:
patterns (map) : List of allowed patterns
x (float) : X coordinate
a (float) : A coordinate
b (float) : B coordinate
c (float) : C coordinate
properties (ScanProperties) : ScanProperties object. If na, default values are initialised
Returns: updated valid projections map
method merge(this, other)
merge two ranges into one
Namespace types: Range
Parameters:
this (Range) : first range
other (Range) : second range
Returns: combined range
method union(this, other)
union of two ranges into one
Namespace types: Range
Parameters:
this (Range) : first range
other (Range) : second range
Returns: union range
method overlaps(this, other)
checks if two ranges intersect
Namespace types: Range
Parameters:
this (Range) : first range
other (Range) : second range
Returns: true if intersects, false otherwise
method consolidate(this)
Consolidate ranges into PRZ
Namespace types: map
Parameters:
this (map) : map of Ranges
Returns: consolidated PRZ
method consolidateMany(this)
Consolidate ranges into multiple PRZ ranges
Namespace types: map
Parameters:
this (map) : map of Ranges
Returns: consolidated array of PRZ ranges
method getRange(currentPatterns, x, a, b, c, properties)
Get D range based on X, A, B, C coordinates for the current patterns
Namespace types: map
Parameters:
currentPatterns (map) : List of valid patterns
x (float) : X coordinate
a (float) : A coordinate
b (float) : B coordinate
c (float) : C coordinate
properties (ScanProperties) : ScanProperties object. If na, default values are initialised
Returns: map of D ranges
method getPrzRange(currentPatterns, x, a, b, c, properties)
Get PRZ range based on X, A, B, C coordinates for the current patterns
Namespace types: map
Parameters:
currentPatterns (map) : List of valid patterns
x (float) : X coordinate
a (float) : A coordinate
b (float) : B coordinate
c (float) : C coordinate
properties (ScanProperties) : ScanProperties object. If na, default values are initialised
Returns: PRZRange for the pattern
method getProjectionRanges(currentPatterns, x, a, b, c, properties)
Get projection range based on X, A, B, C coordinates for the current patterns
Namespace types: map
Parameters:
currentPatterns (map) : List of valid patterns
x (float) : X coordinate
a (float) : A coordinate
b (float) : B coordinate
c (float) : C coordinate
properties (ScanProperties) : ScanProperties object. If na, default values are initialised
Returns: array of projection ranges
Range
Collection of range values
Fields:
values (array) : array of float values
RatioMap
ratio map for pattern
Fields:
ratioMap (map) : map of string to Range (array of float)
ScanProperties
Pattern Scanning properties
Fields:
strictMode (series bool) : strict scanning mode will check for overflows
logScale (series bool) : scan ratios in log scale
errorMin (series float) : min error threshold
errorMax (series float)
mintick (series float) : minimum tick value of price
PrzRange
Potential reversal zone range
Fields:
patterns (array) : array of pattern names for the given XABCD combination
prz (Range) : PRZ range
Pine Script® library
drawingutilsLibrary "drawingutils"
methods used in my scripts for some basic and customized drawings and arrays.
method line(this, p1, p2, lineColor, style, width, xloc, extend)
Draws line and adds to the array
Namespace types: array
Parameters:
this (array) : array to which the created line needs to be added
p1 (chart.point) : point1 of the line
p2 (chart.point) : point2 of the line
lineColor (color) : line color
style (string) : line style
width (int) : line width
xloc (string) : xloc.bar_index or xloc.bar_time
extend (string) : default is extend.none
Returns: line created
method label(this, p, txt, tooltip, xloc, yloc, color, style, textcolor, size, textalign)
Draws label and adds to the array
Namespace types: array
Parameters:
this (array) : array to which the created label needs to be added
p (chart.point) : point at which the label needs to be drawn
txt (string) : label text
tooltip (string) : tooltip text
xloc (string) : xloc value - xloc.bar_index or xloc.bar_time
yloc (string) : y location of the label
color (color) : label color
style (string) : label style
textcolor (color) : label text color
size (string) : Size of the label
textalign (string) : text alignment
Returns: label created
method linefill(this, ln1, ln2, fillColor, transparency)
Draws linefill and adds to array
Namespace types: array
Parameters:
this (array) : array to which the created linefill needs to be added
ln1 (line) : line1 of the fill
ln2 (line) : line2 of the fill
fillColor (color) : fill Color
transparency (int) : fill transparency
Returns: linefill created
draw_labelled_line(target, lblText, linecolor, labelcolor, index, highlight, linesArray, labelsArray, highlightSize, tinySize, yloc, textalign)
Draws labelled line
Parameters:
target (float) : target price
lblText (string) : label text
linecolor (color) : line color
labelcolor (color) : label color
index (int) : index to calculate the distance offset
highlight (bool) : highlight true/false
linesArray (array) : array of lines where the created line is added
labelsArray (array) : array of labels where the created label is added
highlightSize (string) : Size of highlighted text
tinySize (string) : size of non highlighted text
yloc (string) : y location
textalign (string) : text alignment
Returns: void
draw_labelled_box(y1, y2, labelColor, labelText, index, boxArray, labelArray, borderColor, borderStyle, borderWidth, textAlign, highlight, highLightLabel)
Draws custom labelled box
Parameters:
y1 (float) : price 1 of the box
y2 (float) : price 2 of the box
labelColor (color) : label color
labelText (string) : label text
index (int) : index to calculate the offset distance
boxArray (array) : box array to which the box needs to be added
labelArray (array) : label array to which the label needs to be added
borderColor (color) : border color
borderStyle (string) : border style
borderWidth (int) : border width
textAlign (string) : text align of the label
highlight (bool) : highlight label text
highLightLabel (bool) : highlight label size
Returns: void
Pine Script® library






















