OptiPine: High-Performance Caching and Data PipelinesOptiPine is a high performance architecture library for Pine Script™, built for algorithms that push beyond ordinary indicator workloads. It turns caching, sparse updates, reusable storage and workload-aware data structures into practical APIs that stay small at the call site.
In a small indicator, optimization is often optional. In a rendering engine, machine learning library, simulation, dashboard or object system, it can determine whether a feature runs at all. The problem is rarely one slow formula. It is the thousands of unnecessary operations around it: recalculating unchanged results, shifting rolling arrays, scanning large collections for a few changes, and moving stored objects when one disappears.
OptiPine attacks that layer with techniques used in projects such as Pine3D and NeuraLib . The idea is simple: do less work, move less data, and let the representation follow the workload.
Compared with conventional Pine implementations of the same task, OptiPine's optimized paths commonly ran 15% to 40% faster . Sparse updates and indexed lookups exceeded 90% when the alternative scanned or searched the full collection.
Most users can stay entirely within the high-level API. A Memo cache with several dependencies looks like this:
// Pseudocode: trendRegime and volatilityRegime are floats;
// rebuildModel() is a pure calculation.
var op.FloatMemo model = op.floatMemo()
if model.staleOn(trendRegime, volatilityRegime)
model.store(rebuildModel(trendRegime, volatilityRegime))
float result = model.get()
// Output: rebuildModel() runs once, then only when either regime changes.
Memo owns the previous dependencies, first-run state, validity and cached result. The caller only declares what the result depends on.
----------------------------------------------------------------------------------------------------------------
🔷 DO NOT CALCULATE THE SAME THING TWICE
The fastest expensive calculation is the one that never needed to run. Models, simulations and generated geometry often remain valid across many script executions.
Memo is the direct choice when the cached result is an int, float, bool, string or color. staleOn() checks up to four floats, two integers, one Boolean and one string; store() saves a rebuilt value, and get() returns it.
Many models respond to regimes rather than every tiny change in raw data. Round the inputs into meaningful regimes, pass them to staleOn() , and the model runs only when a regime changes.
In practice: Memo is useful for scenario models, parameter sweeps, numerical solvers and other expensive pure calculations that reduce to one primitive result. If its dependencies repeat on nine out of ten executions, it avoids roughly 90% of those model runs.
For collections or a variable dependency list, use Memo's explicit begin() , dependencies.watch*() and miss() lifecycle.
Keep guarded work pure: Stateful ta.* and similar history-dependent calls must remain outside Memo and Watch guards. Compute them every bar, then pass their results into the guarded calculation.
🔸 WATCH: CHANGE DETECTION WITHOUT RESULT STORAGE
Watch is the lighter choice when the caller already owns the result. Several consumers can observe the same producer independently by giving each its own Watch. changed() returns true on the first observation and whenever one scalar, primitive array or OptiPine row ring changes. Row rings expose an internal revision, so checking them is O(1).
For a single source, the dependency check should take less attention than the calculation it protects. Here another component supplies one caller-owned feature array:
// Pseudocode: getFeatureSnapshot() supplies an array.
array features = getFeatureSnapshot()
var op.Watch featureWatch = op.watch()
var float modelScore = na
if featureWatch.changed(features)
modelScore := evaluateModel(features)
// Output: modelScore is rebuilt only when the features array changes.
Because OptiPine does not own features , it compares the array with a retained snapshot and rewrites that snapshot only after a change. Supported row rings use their internal revision instead. The call stays the same, and this compare-first array pattern measured roughly 35% to 60% faster than rewriting the snapshot every time.
The array comparison is still O(N), so use it when the avoided calculation costs more than the comparison. If the producer already provides one reliable change flag, use the flag directly.
For several dependencies, use an explicit pass. begin() starts the comparison, the typed watch*() methods add dependencies, and finish() returns true if the completed set changed. A Watch remembers dependencies; it does not store the result.
// Pseudocode dependencies: int length, float multiplier,
// and array features.
var op.Watch settingsWatch = op.watch()
var float result = na
settingsWatch.begin()
settingsWatch.watchInt(length)
settingsWatch.watchFloat(multiplier)
settingsWatch.watchFloats(features)
bool dependenciesChanged = settingsWatch.finish()
if dependenciesChanged
result := rebuild(length, multiplier, features)
// Output: result is rebuilt when any observed dependency changes.
Construct the Watch once with var , then run begin() and finish() on every comparison pass. For one dependency, changed(source) is the shorter path.
In practice: Watch fits module boundaries: a model can observe a feature array, a renderer can observe a managed ring, or a cache can observe several mixed settings without duplicating the producer's change logic.
CadenceGate limits how often work may run. due() is periodic; dueWhenChanged() also requires a producer revision and remembers changes until the cadence opens. Use it for intentionally delayed work such as periodic model fitting, not results that must update immediately.
----------------------------------------------------------------------------------------------------------------
🔷 ROLLING HISTORY WITHOUT SHIFTING IT
Rolling histories often perform work that adds nothing to the result. If an array keeps the latest 200 events, removing the oldest one and shifting the other 199 entries is unnecessary.
FloatRowRing and IntRowRing keep fixed-width rows in reusable storage. Once full, the next row overwrites the oldest physical slot while reads remain chronological.
var op.FloatRowRing history = op.floatRowRing(200, 3)
float atr14 = ta.atr(14)
if barstate.isconfirmed
history.push(array.from(close, volume, atr14))
float oldestPrice = history.at(0, 0)
float latestPrice = history.newestAt(0, 0)
// Output: after a confirmed push, these are the oldest and newest retained closes.
A push costs O(width), or O(1) through pushValue() for a width-one ring. Rings also provide chronological windows and gathered rows. When several producers can mutate a ring, a separate consumer can detect its revision with Watch.changed(ring) in O(1).
In practice: Row rings fit pivots, completed trades, sampled features and other fixed event histories.
Performance: A full ring overwrites one row instead of shifting every retained row. Its chronological output uses at most two native contiguous copies, which measured 90% faster than rebuilding a 512-cell, width-four output row by row.
Use RingCursor when several caller-owned arrays need the same circular layout. Ordinary series history such as close should remain native Pine.
----------------------------------------------------------------------------------------------------------------
🔷 KEEP DYNAMIC OBJECTS STABLE
Dynamic objects become surprisingly expensive when identity is tied to array position. If one object is removed from several parallel arrays, every later entry shifts, every synchronized payload array needs the same removal, and every external reference to those positions becomes fragile.
StablePool is not the zone storage itself. It keeps one association: an object ID supplied by the script points to a reusable array slot. The ID answers "which zone is this?" while the slot answers "where is this zone's data stored?"
The example has three different logical zones named A, B and C. Their IDs, 1001, 1002 and 1003, are arbitrary unique values chosen for readability. Real IDs may come from a pivot bar, timestamp, order number or incrementing counter.
const int ZONE_A_ID = 1001
const int ZONE_B_ID = 1002
const int ZONE_C_ID = 1003
var op.StablePool zonePool = op.stablePool()
// This example never has more than two active zones.
var array prices = array.new(2, na)
if barstate.isfirst
// A receives slot 0. B receives slot 1.
= zonePool.acquire(ZONE_A_ID)
= zonePool.acquire(ZONE_B_ID)
prices.set(slotA, 100.0)
prices.set(slotB, 200.0)
// Zone A no longer exists. Its slot becomes available.
zonePool.release(ZONE_A_ID)
// C is a new zone with a new identity, but it can reuse A's old slot.
= zonePool.acquire(ZONE_C_ID)
prices.set(slotC, 300.0)
// Output: B keeps slot 1. C has ID 1003 but reuses A's released slot 0.
// prices is .
Why C needs a new ID: C is a different zone, even though it occupies the same array position A once used. Reusing 1001 would describe A returning, not a new zone C. IDs preserve object identity; slots are only reusable storage addresses.
Several fields, one slot: In production, the same slot usually addresses every field belonging to the object. Continuing the A, B and C lifecycle with four parallel arrays:
const int ZONE_A_ID = 1001
const int ZONE_B_ID = 1002
const int ZONE_C_ID = 1003
var op.StablePool zonePool = op.stablePool()
var array zonePrices = array.new()
var array zoneTimes = array.new()
var array zoneStrengths = array.new()
var array zoneColors = array.new()
if barstate.isfirst
= zonePool.acquire(ZONE_A_ID)
= zonePool.acquire(ZONE_B_ID)
// Grow every payload array to cover the allocated slots.
int required = zonePool.slotCount()
op.ensureSizeFloat(zonePrices, required, na)
op.ensureSizeInt(zoneTimes, required, na)
op.ensureSizeFloat(zoneStrengths, required, na)
op.ensureSizeColor(zoneColors, required, na)
zonePrices.set(slotA, 100.0)
zoneTimes.set(slotA, 10)
zoneStrengths.set(slotA, 0.40)
zoneColors.set(slotA, color.blue)
zonePrices.set(slotB, 200.0)
zoneTimes.set(slotB, 20)
zoneStrengths.set(slotB, 0.80)
zoneColors.set(slotB, color.red)
zonePool.release(ZONE_A_ID)
= zonePool.acquire(ZONE_C_ID)
// C reuses A's slot, so every field at that slot must be overwritten.
zonePrices.set(slotC, 300.0)
zoneTimes.set(slotC, 30)
zoneStrengths.set(slotC, 0.60)
zoneColors.set(slotC, color.lime)
// Output: B keeps slot 1 in every array. C owns slot 0 in every array.
// Nothing is removed or shifted.
acquire(id) returns the slot and whether the ID was newly added. Calling it again for an active ID returns the same slot. release(id) frees the slot, but does not erase its array data, so every field must be overwritten when that slot is reused.
The example preallocates two values because it has at most two active zones. A dynamic script can grow its payload arrays with ensureSize*() whenever acquire() reports a new ID. zonePool.slots() returns the currently active slots as a read-only view.
In practice: One zone slot can index its price, time, color, strength and line across several arrays. In the complete example later, the pivot bar and event type form each zone ID. Releasing one zone frees its slot without shifting other zones or breaking saved positions.
Performance: StablePool is independent of payload layout: its slots can index parallel arrays or one array of UDTs. acquire() , release() and find() are O(1), and releasing an object never shifts caller-owned payloads.
For a few fixed objects, manual indices are simpler. StablePool becomes useful when IDs appear and disappear over time, several payload arrays share the same slots, or other parts of the script retain those positions.
SlotCache is the frame-based alternative. Call begin() , acquire every active key, then call finish() ; previously active keys that were not touched are retired automatically.
----------------------------------------------------------------------------------------------------------------
🔷 UPDATE ONLY WHAT CHANGED
Large state does not imply large change. A dashboard may contain 10,000 cells while only a few change on one bar, or a large object system may need to refresh only a handful of entries.
A conventional dirty-flag array must be cleared and scanned in full. DirtySet stores only the changed indices, removes duplicate marks and begins a new cycle without clearing the entire universe. It is a work list, not payload storage or an ID-to-slot map.
Here StablePool resolves zoneId , the arrays store zone data, and DirtySet schedules the slots that need rebuilding. The event values are pseudocode:
int MAX_ZONES = 50000
var op.StablePool zones = op.stablePool()
var op.DirtySet dirtySlots = op.dirtySet(MAX_ZONES)
var array tops = array.new()
var array bottoms = array.new()
var array midpoints = array.new()
// Start this bar's sparse-work cycle.
dirtySlots.begin()
if zoneGeometryChanged
// StablePool converts the logical ID into a reusable physical slot.
= zones.acquire(zoneId)
if created
op.ensureSizeFloat(tops, zoneSlot + 1, na)
op.ensureSizeFloat(bottoms, zoneSlot + 1, na)
op.ensureSizeFloat(midpoints, zoneSlot + 1, na)
tops.set(zoneSlot, newTop)
bottoms.set(zoneSlot, newBottom)
dirtySlots.mark(zoneSlot)
if zoneStyleChanged
int styleSlot = zones.find(zoneId)
if styleSlot >= 0
dirtySlots.mark(styleSlot) // A second mark of the same slot is ignored.
// Process only the distinct physical slots marked during this bar.
for dirtySlot in dirtySlots.values()
float midpoint = (tops.get(dirtySlot) + bottoms.get(dirtySlot)) * 0.5
midpoints.set(dirtySlot, midpoint)
redrawZone(zones.keyAt(dirtySlot), midpoint)
// Output: one zone is rebuilt once even if geometry and style both mark it.
Repeated marks are deduplicated, and unmarked zones are never visited. Work scales with the number of changed slots, not the size of the collection. If the natural address is already a dense index, mark it directly without StablePool.
In practice: Several producers can mark work, then one consumer updates each affected cell, drawing or record once. With 1% of entries changed, this measured 93% faster than clearing and scanning the full universe.
----------------------------------------------------------------------------------------------------------------
🔷 KEYED LOOKUP WITHOUT GUESSWORK
Keyed lookup appears throughout object systems, caches and grouped data, but no structure fits every key set. Distribution, rebuild frequency and query volume change the best choice. OptiPine sees the completed keys at build() , then selects the lookup shape that fits them.
🔸 TYPED STORES: ONE VALUE PER KEY
A typed store maps each integer key to one primitive value. build() pairs entries at matching positions in the key and value arrays. Consecutive IDs allow direct addressing:
var op.IntFloatStore scores = op.intFloatStore()
if barstate.isfirst
// Four entries are shown for readability; both arrays may be much larger.
scores.build(
array.from(410, 411, 412, 413),
array.from(0.80, 0.30, 0.95, 0.50))
float selected = scores.get(412)
// Output: integer key 412 resolves to float value 0.95.
Lookup is one-way: get(412) returns 0.95 , but values may repeat, so get(0.95) has no general meaning.
What automatic mode chooses:
Consecutive ascending keys: Direct arithmetic indexing.
Compact key ranges: A dense lookup table.
Other unordered keys: A native map when within Pine's map limit.
Ascending sparse keys: Binary search, or a map within that limit when expectedQueries justifies its build cost.
Linear lookup remains available for unusual workloads that rebuild far more often than they query. Automatic mode only selects it for non-empty stores when linearMaxEntries is deliberately configured.
The same API avoids hashing when direct addressing fits, uses a map when it pays, and remains usable beyond Pine's map capacity. Automatic mode is the normal default. Use op.indexConfigDynamic() when future query volume is unknown and the store may need to promote itself later.
build(keys, values, expectedQueries) accepts two same-length arrays. The optional hint tells OptiPine how many lookups to expect before the next build. Stores support int, float, bool, string and color values. Use one IntIndex for several payload fields, or IntBuckets when a key owns several integers.
In practice: Batch-build IDs to scores, states or metadata, then query them without committing to a representation. Direct integer addressing measured 21% faster than a map, while a map measured 91% faster than repeated linear lookup with 32 entries.
🔸 INTBUCKETS: ONE KEY TO MANY INTEGER VALUES
A Store returns one value for each key. IntBuckets returns a group of integers, usually object IDs or physical slots. Repeating a key adds another member instead of replacing the previous one.
var op.IntBuckets cellMembers = op.intBuckets()
var array matches = array.new()
if barstate.isfirst
// Six (cell, object slot) pairs. Cell 7 appears three times.
array cellKeys = array.from(7, 2, 7, 5, 2, 7)
array objectSlots = array.from(101, 205, 412, 990, 777, 888)
cellMembers.buildFromPairs(cellKeys, objectSlots)
// Read cell 7's group from flat storage. matches is only demo output.
= cellMembers.rangeByKey(7)
if count > 0
for position = start to start + count - 1
matches.push(cellMembers.valueAt(position))
// Output: matches contains , the object slots assigned to cell 7.
What happens: Each key is paired with the slot at the same array position. Cell 7 appears three times, so its group contains 101, 412 and 888. rangeByKey() returns where that group starts and how many values it contains. A missing key returns a count of 0.
Lifecycle: buildFromPairs() replaces all previous groups. Use buildBegin() , add() and buildFinish() only when pairs arrive one at a time.
In practice: A price cell can own several zone slots, a graph node can own several neighbors, or a category can own several record IDs. One query visits only that group.
Why use it: A native map stores one value per key, and Pine does not allow an array directly as that value. Giving one key several values therefore requires a small wrapper UDT containing an array. IntBuckets provides that relationship directly, packing every group into shared contiguous storage. It suits batch rebuilds followed by repeated traversal, while the wrapper approach is more convenient when individual groups change constantly. In the tested 64-key traversal workload, IntBuckets averaged 19% faster across four runs.
----------------------------------------------------------------------------------------------------------------
🔷 REUSE STATE INSTEAD OF REBUILDING IT
IntDoubleBuffer and FloatDoubleBuffer retain current and previous arrays. swap() exchanges their references in O(1), preserves the old result and clears the new current buffer for reuse. That clear still costs O(N).
This is useful when one pass must remain readable while the next is built. In this small search, node n has children 2n and 2n + 1 . Each pass reads the active level and writes the next one:
var op.IntDoubleBuffer searchFrontier = op.intDoubleBuffer()
if barstate.isfirst
searchFrontier.current.push(1)
for depth = 1 to 3
= searchFrontier.swap()
for nodeId in activeFrontier
nextFrontier.push(nodeId * 2)
nextFrontier.push(nodeId * 2 + 1)
// Output: current contains .
// previous contains .
What happens: swap() makes the completed level available as activeFrontier and returns the other retained array, already empty, as nextFrontier . No level is copied and no replacement array is created. The same pattern supports graph searches, flood fills, iterative clustering and simulations. Use swapSized() when every pass needs a fixed-size output.
A var array can also be reused. The ensureSize*() , resize*() and refill*() families modify existing storage, while sameExact*() compares primitive arrays without Pine's float-comparison rounding.
Revision handles caller-owned state that OptiPine cannot observe. The producer calls bump() after a change; each consumer compares its own saved token with changedSince() instead of keeping a snapshot.
----------------------------------------------------------------------------------------------------------------
🔷 WEIGHTED SELECTION FOR STATIC AND DYNAMIC SYSTEMS
Weighted selection chooses entries in proportion to their weights. It is useful in simulations, randomized search and priority sampling.
WeightedSampler is the high-level interface. Set weights, then supply a fraction to select a slot. The sampler does not generate randomness; use math.random() or a repeatable fraction sequence:
var op.WeightedSampler sampler = op.weightedSampler(512)
if barstate.isfirst
sampler.setWeight(10, 0.25)
sampler.setWeight(11, 0.80)
sampler.setWeight(12, 0.10)
float fraction = 0.50
int selected = sampler.sample(fraction)
// Output: selected is 11 for the supplied fraction of 0.50.
The default cumulative prefix suits stable weights. Pass op.weightConfigSparseUpdates() and the sampler can move to an update-friendly Fenwick tree as the workload changes. sample() stays the same. Use WeightedIndex for circular ranges or explicit policy control.
In practice: Each slot can represent a candidate model, simulation outcome or work item. Update its weight when its score changes, then sample repeatedly through the same interface.
----------------------------------------------------------------------------------------------------------------
🔷 THREE LEVELS OF CONTROL
OptiPine is layered so high-level code describes the problem rather than the mechanism. Start with Tier 1 and move deeper only when the workload requires more control:
Tier 1, Quick: Ready-to-use APIs with automatic defaults, including Watch, Memo, CadenceGate, typed stores, StablePool, DirtySet, row rings, double buffers and WeightedSampler.
Tier 2, Composable: Explicit lifecycles, configuration and representation policies through IntIndex, IntBuckets, SlotCache, RingCursor and Revision.
Tier 3, Expert: Physical addressing, unchecked operations and scoped raw mutation for measured hot paths. Ordinary read-only views are not Tier 3.
Editor warnings: Methods such as get() , set() , push() and clear() intentionally match Pine's collection vocabulary. Any shadowing-method warning is cosmetic; the receiver's type determines which method runs.
----------------------------------------------------------------------------------------------------------------
🔷 COMPLETE, COPY-PASTE EXAMPLES
The fragments above isolate one idea at a time. These two copy-paste indicators combine them in practical workflows, using native Pine where it is simpler and OptiPine where it removes real work.
🔸 Complete example 1: high-level cached stress model
What it does: The indicator plots a probability-weighted downside estimate for the current trend and volatility regime, while exposing both regime values in the Data Window.
The EMA and ATR calculations run normally on every bar. Their rounded regimes change less often, so Memo recalculates the 401-scenario model only when one of those regimes changes and serves the cached result between changes.
//@version=6
indicator("OptiPine - Cached Regime Stress", overlay = false)
import Alien_Algorithms/OptiPine/1 as op
// Test 401 possible moves, giving more weight to common moves.
// This function is pure: its result depends only on its inputs.
estimateDownside(float trendInAtr, float atrPercent) =>
float result = na
if not na(trendInAtr) and not na(atrPercent) and atrPercent > 0
float weightedDownside = 0.0
float totalWeight = 0.0
for scenario = -200 to 200
float standardShock = scenario / 40.0
float weight = math.exp(-0.5 * standardShock * standardShock)
float projectedMove = (trendInAtr + standardShock) * atrPercent
float downside = math.max(-projectedMove, 0.0)
weightedDownside += downside * weight
totalWeight += weight
result := totalWeight > 0 ? weightedDownside / totalWeight : na
result
// Stateful Pine calculations stay outside the Memo guard.
float ema20 = ta.ema(close, 20)
float ema50 = ta.ema(close, 50)
float atr14 = ta.atr(14)
float trendInAtr = atr14 > 0 ? (ema20 - ema50) / atr14 : na
float atrPercent = close > 0 ? atr14 / close * 100.0 : na
// Quantization makes the dependencies describe a regime, not every tick.
float trendRegime = math.round(
math.max(-3.0, math.min(3.0, trendInAtr)) * 10.0) / 10.0
float volatilityRegime = math.round(atrPercent * 4.0) / 4.0
var op.FloatMemo downsideStress = op.floatMemo()
if downsideStress.staleOn(trendRegime, volatilityRegime)
downsideStress.store(
estimateDownside(trendRegime, volatilityRegime))
float stress = downsideStress.get()
plot(stress, "Expected downside (%)", color.orange, linewidth = 2)
plot(trendRegime, "Trend regime (ATR units)", display = display.data_window)
plot(volatilityRegime, "Volatility regime (%)", display = display.data_window)
🔸 Complete example 2: advanced zone-cluster engine
What it does: The indicator draws recent pivot levels, thickens those near the current price, plots the strongest price cluster and reports its key statistics in the Data Window.
StablePool preserves drawing slots, the ring tracks retirement order, DirtySet queues redraws, IntBuckets forms price clusters and IntFloatStore looks up their strength.
Relevant benchmarks: These are component results, not a total for this 32-zone indicator. In larger matching workloads, DirtySet saved 93% at 1% dirty and IntBuckets averaged 19% with 64 keys. For typed lookup, direct addressing saved 21% over a map on compact keys, while a map saved 91% over linear search at 32 entries. Automatic mode selects the representation.
StablePool and the ring manage recycling. The script still scans live zones for proximity changes, then DirtySet avoids unnecessary drawing updates.
//@version=6
indicator("OptiPine - Zone Cluster Engine", overlay = true, max_lines_count = 100)
import Alien_Algorithms/OptiPine/1 as op
int pivotLength = input.int(5, "Pivot length", minval = 1)
int maxZones = input.int(32, "Maximum zones", minval = 4, maxval = 100)
int bucketTicks = input.int(25, "Cluster size in ticks", minval = 1)
float bucketSize = syminfo.mintick * bucketTicks
// Stateful Pine calculations remain outside every conditional rebuild.
float pivotHigh = ta.pivothigh(high, pivotLength, pivotLength)
float pivotLow = ta.pivotlow(low, pivotLength, pivotLength)
float pivotStrength = math.max(nz(volume , 1.0), 1.0)
float highlightDistance = ta.atr(14)
var op.StablePool zones = op.stablePool()
var op.IntRowRing zoneOrder = op.intRowRing(maxZones, 1)
var op.DirtySet dirtyZones = op.dirtySet(maxZones)
var array zonePrices = array.new(maxZones, na)
var array zoneStrengths = array.new(maxZones, 0.0)
var array zoneTimes = array.new(maxZones, na)
var array resistance = array.new(maxZones, false)
var array highlighted = array.new(maxZones, false)
var array zoneLines = array.new(maxZones)
var op.IntBuckets zonesByBucket = op.intBuckets()
var op.IntFloatStore strengthByBucket = op.intFloatStore()
// Retained build storage is resized and overwritten, never cleared and repopulated.
var array bucketKeyByPosition = array.new()
var array aggregateKeys = array.new()
var array aggregateStrengths = array.new()
var int strongestBucketKey = na
var float strongestBucketStrength = na
var int strongestZoneCount = 0
dirtyZones.begin()
bool topologyChanged = barstate.isfirst
// Logical pivot IDs receive stable, reusable physical drawing slots.
for event = 0 to 1
float level = event == 0 ? pivotHigh : pivotLow
if barstate.isconfirmed and not na(level)
int pivotBar = bar_index - pivotLength
int pivotTime = time
int zoneId = pivotBar * 2 + event
int slot = zones.find(zoneId)
// Only a new logical pivot enters the retirement queue.
if slot < 0
if zoneOrder.rowCount() == maxZones
int oldestId = zoneOrder.at(0, 0)
zones.release(oldestId)
= zones.acquire(zoneId)
slot := newSlot
zoneOrder.pushValue(zoneId)
zonePrices.set(slot, level)
zoneStrengths.set(slot, pivotStrength)
zoneTimes.set(slot, pivotTime)
resistance.set(slot, event == 0)
highlighted.set(slot, false)
dirtyZones.mark(slot)
topologyChanged := true
// Proximity can mark a newly created slot again; DirtySet still stores it once.
for slot in zones.slots()
bool isHighlighted = math.abs(close - zonePrices.get(slot)) <= highlightDistance
if isHighlighted != highlighted.get(slot)
highlighted.set(slot, isHighlighted)
dirtyZones.mark(slot)
// Only changed drawings cross the line API boundary.
for slot in dirtyZones.values()
float level = zonePrices.get(slot)
color baseColor = resistance.get(slot) ? color.red : color.lime
line zoneLine = zoneLines.get(slot)
if na(zoneLine)
zoneLine := line.new(zoneTimes.get(slot), level, time, level,
xloc = xloc.bar_time)
zoneLines.set(slot, zoneLine)
line.set_xy1(zoneLine, zoneTimes.get(slot), level)
line.set_xy2(zoneLine, time, level)
line.set_extend(zoneLine, extend.right)
line.set_width(zoneLine, highlighted.get(slot) ? 3 : 1)
line.set_color(zoneLine,
color.new(baseColor, highlighted.get(slot) ? 0 : 55))
// Rebuild grouped lookup only after the explicit creation event.
if topologyChanged
array liveSlots = zones.slots()
int liveCount = liveSlots.size()
op.resizeInt(bucketKeyByPosition, liveCount, 0)
if liveCount > 0
for position = 0 to liveCount - 1
int slot = liveSlots.get(position)
int bucketKey = int(math.round(zonePrices.get(slot) / bucketSize))
bucketKeyByPosition.set(position, bucketKey)
// Repeated bucket keys accumulate several physical zone slots.
zonesByBucket.buildFromPairs(bucketKeyByPosition, liveSlots)
int bucketCount = zonesByBucket.bucketCount()
op.resizeInt(aggregateKeys, bucketCount, 0)
op.resizeFloat(aggregateStrengths, bucketCount, 0.0)
strongestBucketKey := na
strongestBucketStrength := na
strongestZoneCount := 0
if bucketCount > 0
for bucketSlot = 0 to bucketCount - 1
int bucketKey = zonesByBucket.keyAt(bucketSlot)
= zonesByBucket.rangeBySlot(bucketSlot)
float totalStrength = 0.0
if count > 0
for position = start to start + count - 1
int zoneSlot = zonesByBucket.valueAt(position)
totalStrength += zoneStrengths.get(zoneSlot)
aggregateKeys.set(bucketSlot, bucketKey)
aggregateStrengths.set(bucketSlot, totalStrength)
if na(strongestBucketStrength) or totalStrength > strongestBucketStrength
strongestBucketKey := bucketKey
strongestBucketStrength := totalStrength
strongestZoneCount := count
strengthByBucket.build(aggregateKeys, aggregateStrengths)
// Query the current price cluster directly and display the strongest cluster.
int currentBucketKey = int(math.round(close / bucketSize))
float nearbyStrength = strengthByBucket.get(currentBucketKey, 0.0)
float strongestClusterPrice = na(strongestBucketKey) ?
na : strongestBucketKey * bucketSize
plot(strongestClusterPrice, "Strongest zone cluster", color.orange,
linewidth = 2, style = plot.style_stepline)
plot(nearbyStrength, "Strength near current price", display = display.data_window)
plot(strongestBucketStrength, "Strongest cluster strength",
display = display.data_window)
plot(strongestZoneCount, "Zones in strongest cluster",
display = display.data_window)
plot(dirtyZones.size(), "Drawings updated", display = display.data_window)
----------------------------------------------------------------------------------------------------------------
🔷 API REFERENCE
This is a compact index of the main public entry points.
🔸 Watch and Memo: changed(source) handles one scalar, primitive array or row ring. For several dependencies, use begin() , watch*() and finish() . Typed Memos add staleOn() , store() , get() and invalidate() .
🔸 Revision and Cadence: revision() exposes bump() , current() and changedSince() for manual change tracking. cadenceGate() provides due() and change-aware dueWhenChanged() scheduling.
🔸 Row Rings: floatRowRing() and intRowRing() provide push() , width-one pushValue() , at() , setAt() , newestAt() , chronological() and gather() .
🔸 RingCursor: Circular addressing for caller-owned arrays. Use reserve() to advance, physical() and logical() to translate positions, and newest() or oldest() to locate retained rows.
🔸 StablePool: acquire() and release() manage stable key-to-slot assignments. Lookup and traversal use find() , contains() , keyAt() , slots() and size() . Recycled slots retain their caller-owned payload until overwritten.
🔸 SlotCache: Frame-based stable allocation follows begin() , acquire() , finish() . active() , retired() and size() expose its state.
🔸 DirtySet: begin() starts a cycle; mark() , markMany() and markRange() add entries. Read the distinct work list with values() and size() .
🔸 Typed Stores: intIntStore() , intFloatStore() , intBoolStore() , intStringStore() and intColorStore() map integer keys to primitive values. Build with build() , then use get() , set() , contains() or getMany() .
🔸 IntIndex: A shared integer key-to-slot directory for custom payloads and explicit lookup policy. Build with buildBegin() , add() or addMany() and buildFinish() ; query with find() , keyAt() and findMany() . IndexConfig controls representation and duplicate policy.
🔸 IntBuckets: A one-key-to-many-integers index. Build directly with buildFromPairs() , or incrementally with buildBegin() , add() or addMany() and buildFinish() . Read groups with rangeByKey() and valueAt() .
🔸 Double Buffers: intDoubleBuffer() and floatDoubleBuffer() retain current and previous arrays. swap() exchanges them; swapSized() also sizes and refills the new current buffer.
🔸 Weighted Sampling: weightedSampler() provides weight updates, sample() , sampleMany() , probability() and total() . It maps caller-supplied fractions; it does not generate randomness. weightedIndex() adds circular ranges and explicit policy control.
🔸 Storage Utilities: ensureSize*() , resize*() , refill*() and sameExact*() handle primitive arrays. Other helpers cover flat/matrix conversion, transposition and bulk ring reads.
----------------------------------------------------------------------------------------------------------------
🔷 WHY OPTIPINE EXISTS
Pine's limits are real, but standard architecture often reaches them long before the idea itself has to. Repeating unchanged calculations, shifting rolling storage, scanning mostly untouched collections and rebuilding state all consume the same execution budget the feature needs to exist.
OptiPine reclaims that budget. Expensive models can run only when their inputs change. Large dashboards can refresh only what moved. Dynamic object systems can grow and recycle storage without reorganizing everything around them. The APIs stay approachable, while the architecture underneath is built for workloads that would normally force a Pine project to scale back.
At large scale, optimization is no longer simply about feature speed. It is the factor that dictates whether an ambitious idea can ship at all.
----------------------------------------------------------------------------------------------------------------
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
The publication diagram has been rendered natively by Pine3D .
Library

SMCNexusFactsCoreV2SMCNexusFactsCoreV2 is an open-source, non-visual Pine Script library that maintains confirmed and bounded Smart Money Concepts market facts for use by importing indicators.
The library provides a stateful market-facts engine for swing structure, BOS, CHoCH, MSS, Fair Value Gaps, Order Blocks, liquidity pools, liquidity sweeps, Premium/Discount context and EMA-based context.
It does not draw chart objects, create inputs, request other timeframes, generate alerts, transmit data, calculate trade recommendations or place orders. The importing indicator supplies all chart series and decides how the returned facts are displayed or used.
ORIGINAL CONCEPT AND PURPOSE
The library maintains one consistent, confirmed market-state model instead of calculating unrelated labels independently.
Confirmed swing points become the shared source for:
• HH, HL, LH and LL classification,
• market bias,
• Break of Structure,
• Change of Character,
• Market Structure Shift,
• buy-side and sell-side liquidity pools,
• Premium and Discount dealing ranges.
Fair Value Gaps and Order Blocks use bounded lifecycle records. The library retains only a limited number of objects for each type and direction, preventing unbounded array growth.
Visual settings are not part of this library. An importing indicator can hide or show its own presentation without changing the underlying facts maintained by Facts Core.
CONFIRMED-ONLY PROCESSING
The importing indicator explicitly tells the library whether the current bar is confirmed.
Canonical state changes occur only when confirmed data is supplied. This includes:
• new swing confirmation,
• BOS or CHoCH confirmation,
• MSS confirmation,
• creation of FVG and Order Block facts,
• zone tests and mitigation,
• liquidity-pool creation and collection,
• sweep confirmation.
The library does not use future chart data, negative visual offsets to rewrite history or hidden lookahead requests.
MARKET STRUCTURE
The stateful swing engine stores the latest and previous confirmed swing highs and lows.
It classifies confirmed swings as:
• HH — Higher High
• HL — Higher Low
• LH — Lower High
• LL — Lower Low
The structure model tracks:
• latest swing prices,
• origin bars,
• swing types,
• current market bias,
• consumed structure levels,
• latest break type and direction,
• latest MSS direction and bar.
BOS AND CHOCH
A confirmed break can require a candle close beyond the structure level, depending on the supplied configuration.
The current market bias and the direction of the broken swing determine whether the event represents continuation or a Change of Character.
The library preserves the confirmed event level, direction, origin and confirmation bar in the returned snapshot.
MARKET STRUCTURE SHIFT
MSS can require:
• a confirmed close through structure,
• a previous opposite bias,
• a displacement candle,
• a minimum ATR-based displacement.
These requirements are provided through FactsConfiguration. The library does not silently relax a missing requirement.
FAIR VALUE GAPS
The library detects bullish and bearish three-candle imbalances from caller-supplied OHLC data.
Optional ATR filtering can require a minimum imbalance size.
Each FVG fact can contain:
• direction,
• upper and lower boundaries,
• origin bar and time,
• confirmation bar,
• mitigation state,
• invalidation state,
• test count,
• fill percentage,
• latest test bar,
• origin volume,
• origin average volume,
• origin Premium/Discount location,
• bounded strength,
• displacement confirmation.
ORDER BLOCKS
Order Block facts are created from a bounded lookback and can require a confirmed BOS or MSS.
The configuration controls whether candle bodies or full candle ranges define the zone.
Each Order Block uses the same auditable lifecycle metadata as an FVG, including origin, tests, fill, mitigation, invalidation, volume, relative volume context, strength and displacement confirmation.
ZONE LIFECYCLE
A zone can be:
• available,
• tested,
• partially filled,
• mitigated,
• invalidated.
The test counter and fill percentage are updated from confirmed interaction with the stored zone boundaries.
The library does not invent missing origin metadata. If a fact cannot be associated with a valid source, the unavailable value remains unavailable.
LIQUIDITY
The library maintains bounded arrays of confirmed swing-high and swing-low liquidity references.
It derives:
• BSL — Buy-Side Liquidity,
• SSL — Sell-Side Liquidity,
• EQH — Equal Highs,
• EQL — Equal Lows.
Equal-level classification uses the supplied ATR-based tolerance rather than exact floating-point equality.
Liquidity metadata includes:
• side and type,
• level,
• origin bar,
• collection state,
• collection time,
• sweep type and level.
A pool origin is preserved only when its price is genuinely associated with the originating swing. The library does not transfer unrelated swing metadata to a new liquidity level.
LIQUIDITY SWEEPS
Depending on configuration, a sweep can require price to move beyond the stored pool and close back inside it.
The returned snapshot distinguishes BSL and SSL sweep facts. A sweep is a confirmed market fact, not a BUY or SELL recommendation.
PREMIUM AND DISCOUNT
The library can build a dealing range from confirmed swing extremes.
The returned context can contain:
• range high,
• range low,
• equilibrium,
• current Premium, Discount or Equilibrium classification.
An unavailable or invalid range remains unavailable rather than using a synthetic fallback.
EMA AND CONTEXT FACTS
The importing indicator supplies the configured fast, medium and slow EMA values together with available higher-timeframe context.
Facts Core returns bounded contextual facts such as:
• EMA trend state,
• price relation to EMA values,
• available higher-timeframe trend and bias context.
The library does not request higher-timeframe data itself. This keeps data ownership and confirmation timing inside the importing indicator.
BOUNDED STATE
The implementation uses explicit limits:
• maximum six zones for each kind and direction,
• maximum eight swing references for each side.
This prevents unlimited state growth and makes runtime behavior predictable.
PUBLIC API
Exported records:
• FactsConfiguration
• ZoneFact
• FactsState
• StructureFacts
• ZoneFacts
• LiquidityFacts
• ContextFacts
• FactsSnapshot
Exported functions:
• contractVersion()
• defaultConfiguration()
• newState()
• advance(...)
• snapshotValid(...)
TYPICAL USAGE
An importing indicator should:
1. Create one persistent FactsState.
2. Create or resolve a FactsConfiguration.
3. Supply confirmed OHLCV, ATR, EMA and available context values to advance().
4. Store the returned state.
5. Read the returned FactsSnapshot.
6. Validate the snapshot with snapshotValid().
7. Present or transport only facts that are actually available.
Conceptual example:
```pine
import AreXoN_/SMCNexusFactsCoreV2/1 as facts
var facts.FactsState state = facts.newState()
facts.FactsConfiguration configuration =
facts.defaultConfiguration()
= facts.advance(
state,
configuration,
barstate.isconfirmed,
bar_index,
time,
open,
high,
low,
close,
volume,
atr14,
emaFast,
emaMedium,
emaSlow,
higherTimeframeTrend,
higherTimeframeBias,
localContext)
state := stateNext
bool validSnapshot = facts.snapshotValid(snapshot)
```
The example is conceptual. The exact function signature in the published source is authoritative. Replace the example import with the exact path assigned by PulseWire.
WHY THE CHART IS CLEAN
This is a non-visual market-facts library. It intentionally creates no plots, labels, boxes, lines, tables or chart drawings.
The publication chart is therefore intentionally clean and contains no other indicators or unexplained visual elements. An importing indicator is responsible for visual presentation.
LIMITATIONS
• Facts are based on the chart OHLCV series supplied by the importer.
• Swing confirmation necessarily occurs after the configured right-side bars.
• The library does not provide native bid/ask data, footprint or real order flow.
• Chart volume may be broker tick volume rather than centralized exchange volume.
• It does not verify spread, slippage or broker execution.
• It does not request macroeconomic information.
• It does not produce trading signals or recommendations.
• It does not place, modify or close orders.
• It produces no visual chart output by itself.
Contract version: 1.0.0.
This library is an analytical and software-development component. It is not investment advice, a trading recommendation or an automated trading system. Library

SMCNexusTradePlanCoreV2SMCNexusTradePlanCoreV2 is an open-source, non-visual Pine Script library for deterministic candidate-plan geometry.
The library receives already-detected market facts from an importing indicator and resolves candidate Entry, protective Stop Loss, real target clusters, risk-to-reward values, confluence and fail-closed plan validity.
It does not scan the chart independently, predict future prices, generate guaranteed signals, place orders or fabricate missing levels. The importing indicator remains responsible for detecting and confirming market structure, zones, liquidity, pivots and other market facts.
ORIGINAL CONCEPT AND PURPOSE
The library converts confirmed analytical facts into auditable candidate-plan geometry using fixed source priorities and strict validation rules.
Every Entry, Stop Loss and target must originate from a real level supplied by the importing indicator. Missing or contradictory information remains unavailable instead of being replaced with a synthetic price.
ENTRY RESOLUTION
The candidate direction is derived from the primary bias supplied by the importing indicator.
For a BUY candidate, the Entry zone is selected from the first available source in this fixed order:
1. Bullish Order Block
2. Bullish Fair Value Gap
3. Discount half of the current dealing range
4. S1 pivot
For a SELL candidate, the fixed order is:
1. Bearish Order Block
2. Bearish Fair Value Gap
3. Premium half of the current dealing range
4. R1 pivot
The candidate Entry is the midpoint of the selected zone. A single-price pivot remains a single-price zone.
The library does not search for the best historical result and does not reorder sources according to later price movement.
STOP LOSS RESOLUTION
Stop Loss candidates are checked using a fixed protective hierarchy.
For BUY candidates, a valid Stop Loss must be below Entry. For SELL candidates, it must be above Entry.
The available candidates are checked in this order:
1. Opposite-side liquidity level
2. Direction-matching Order Block edge
3. Dealing-range edge
4. Directional pivot
A candidate located on the wrong side of Entry is skipped without changing the priority of the remaining sources.
If no supplied level is directionally valid, Stop Loss remains unavailable. The library never creates a Stop Loss from a fixed percentage or an arbitrary distance.
REAL TARGET SELECTION
Targets must be genuine levels supplied by the importing indicator.
Possible sources may include:
• liquidity pools,
• opposing Order Blocks,
• opposing Fair Value Gaps,
• confirmed swing levels,
• pivots,
• Premium, Discount or Equilibrium levels.
The importing indicator owns one bounded TargetCandidate array and decides which confirmed levels are eligible.
Each candidate contains:
• real price,
• source identifier,
• origin type,
• stable origin key,
• confirmation bar,
• direction,
• active state.
Candidates located on the wrong side of Entry are rejected. The origin used for Entry or Stop Loss can also be excluded from the target collection.
TARGET CLUSTERING
Several analytical sources may describe practically the same price area. The library groups nearby candidates into separate clusters using a caller-provided distance.
The distance can be calculated from ATR using clusterDistance(). ATR controls cluster separation only. It never creates, moves or estimates a target price.
The nearest real representative from the first separate cluster becomes TP1. The nearest representative outside the TP1 cluster becomes TP2. The nearest representative outside the first two clusters becomes TP3.
Every selected target is therefore an actual price supplied by the importing indicator.
STABLE ORIGIN KEYS
The library provides helpers for creating auditable source identities:
• zoneKey(...)
• liquidityKey(...)
• swingKey(...)
• pdKey(...)
• pivotKey(...)
These keys help the importing indicator identify duplicate sources and prevent the same analytical object from being reused incorrectly.
FINAL VALIDATION
The final resolver calculates:
• risk distance,
• reward to TP1, TP2 and TP3,
• RR1, RR2 and RR3,
• candidate order type,
• latest structural confirmation,
• directional confluence,
• final sanity status.
The geometry must satisfy all required conditions:
• Entry and Stop Loss are available,
• Stop Loss is on the protective side of Entry,
• targets are on the correct side of Entry,
• targets are ordered nearest-to-farthest,
• required target data is complete.
Invalid geometry returns a specific fail-closed status instead of displaying an apparently valid plan.
PUBLIC API
Typed records:
• EntryResult
• TargetCandidate
• TargetSelection
• FinalResult
Exported functions:
• resolveEntry(...)
• sameLevel(...)
• zoneKey(...)
• liquidityKey(...)
• swingKey(...)
• pdKey(...)
• pivotKey(...)
• addCandidate(...)
• selectTargets(...)
• clusterDistance(...)
• riskDistance(...)
• resolveFinal(...)
INTENDED USE
The importing indicator should:
1. Detect and confirm its own structure, zones, liquidity and pivots.
2. Pass the current facts to resolveEntry().
3. Add only genuine eligible levels to one bounded candidate array.
4. Call selectTargets() using an explicit cluster distance.
5. Pass Entry, Stop Loss, targets and contextual facts to resolveFinal().
6. Display a candidate only when the returned validity state permits it.
Conceptual example:
```pine
import AreXoN_/SMCNexusTradePlanCoreV2/1 as plan
plan.EntryResult entry = plan.resolveEntry(
primaryBias,
bullishObActive, bullishObHigh, bullishObLow,
bearishObActive, bearishObHigh, bearishObLow,
bullishFvgActive, bullishFvgHigh, bullishFvgLow,
bearishFvgActive, bearishFvgHigh, bearishFvgLow,
dealingRangeValid, dealingRangeHigh, dealingRangeLow,
equilibrium,
pivotS1Available, pivotS1,
pivotR1Available, pivotR1,
lastSsl, lastBsl)
array candidates =
array.new()
// Add only confirmed real levels detected by the importing indicator.
float distance = plan.clusterDistance(atrValue, 0.55)
plan.TargetSelection targets =
plan.selectTargets(
candidates,
entry.isBuy ? 1 : -1,
distance)
```
The example import path should be replaced with the exact path assigned by PulseWire after publication.
WHY THE CHART IS CLEAN
This is a non-visual calculation library. It intentionally creates no plots, labels, tables, lines or boxes.
The publication chart is therefore intentionally clean and contains no additional indicators, drawings or unexplained visual elements. Visual presentation is the responsibility of an importing indicator.
LIMITATIONS
• The result depends entirely on the confirmed facts supplied by the importing indicator.
• It is a mechanical analytical candidate, not a recommendation.
• It cannot verify live spread, slippage, broker StopLevel or execution rules.
• It does not provide native bid/ask order flow.
• It does not place, modify or close orders.
• Missing real levels produce an incomplete result by design.
• Risk-to-reward values describe supplied geometry and do not predict outcome.
• It produces no chart output by itself.
This library is an analytical and software-development component. It is not investment advice, a trading recommendation or an automated trading system. Library

SMCNexusConfigurationCoreV2SMCNexusConfigurationCoreV2 is an open-source, non-visual Pine Script library for resolving deterministic indicator configuration profiles and bounded visibility settings.
The library separates pure configuration decisions from market detection, chart state and presentation code. It does not generate signals, place orders or draw objects.
The importing indicator supplies its saved manual settings, chart timeframe and supported-symbol state. The library returns typed effective configuration records without calling input functions, requesting external timeframes or changing the importing script's saved settings.
ORIGINAL CONCEPT AND PURPOSE
The library implements three explicit configuration modes:
• MANUAL — preserves every value supplied by the importing indicator.
• AUTO — applies an exact predefined profile only when the supplied symbol and timeframe combination is explicitly supported.
• HYBRID — applies automatic values only to individually selected categories while preserving manual values for all other categories.
The implementation does not use nearest-timeframe guessing. An unsupported symbol or timeframe falls back to the supplied manual settings.
Detection parameters and visual settings are resolved separately. This prevents a visibility option from unintentionally disabling the underlying analytical calculation. For example, hiding a market-structure label does not remove the structure state used elsewhere by the importing indicator.
SUPPORTED PROFILE CONTEXT
The profile resolver distinguishes exact chart timeframes:
• M1
• M5
• M15
• M30
• H1
• H4
• D1
• W1
The importing indicator decides whether the current symbol is supported. If the symbol or timeframe is unsupported, the automatic profile is not applied.
CONFIGURATION CATEGORIES
The resolved configuration includes separate categories for:
• swing structure,
• Market Structure Shift requirements,
• Fair Value Gap parameters,
• Order Block parameters,
• liquidity and sweep parameters,
• volume-profile range settings,
• structure visibility,
• zone visibility,
• liquidity and Premium/Discount visibility,
• EMA, pivot and volume-marker visibility,
• panel and Trade Plan visibility,
• trendline and volume-profile visibility.
ADAPTIVE GRID RESOLUTION
The library also contains a bounded adaptive-grid resolver for importing scripts that build a volume-profile approximation.
The resolver receives:
• the manual tick floor,
• the instrument minimum tick,
• the current range low and high,
• the requested target number of bins.
It calculates:
• whether the result is valid,
• effective ticks per bin,
• effective bin size,
• maximum permitted span,
• actual span in ticks,
• applied scale.
The effective tick step is never lower than the supplied manual floor. The resolver increases the step using a power-of-two scale when the requested price span would exceed the bounded target. Invalid or incomplete inputs return an unavailable result instead of an invented value.
PUBLIC API
Typed result records:
• ProfileContext
• CoreConfiguration
• StructureVisibility
• ZoneVisibility
• ContextVisibility
• OverlayVisibility
• PanelVisibility
• AuxiliaryVisibility
• AdaptiveGridResolution
Exported resolvers:
• resolveAdaptiveGrid(...)
• resolveProfileContext(...)
• resolveCoreConfiguration(...)
• resolveStructureVisibility(...)
• resolveZoneVisibility(...)
• resolveContextVisibility(...)
• resolveOverlayVisibility(...)
• resolvePanelVisibility(...)
• resolveAuxiliaryVisibility(...)
INTENDED USE
An importing indicator first creates a ProfileContext. It then passes that context together with its saved manual settings to the required resolver.
Conceptual example:
```pine
import AreXoN_/SMCNexusConfigurationCoreV2/1 as config
config.ProfileContext profile = config.resolveProfileContext(
configurationMode,
supportedSymbol,
timeframe.period,
autoStructure,
autoMss,
autoFvg,
autoOb,
autoLiquidity,
autoVolumeProfile,
autoVisibility)
config.CoreConfiguration effective = config.resolveCoreConfiguration(
profile,
manualSwingLeft,
manualSwingRight,
manualRequireCloseBreak,
manualRequireOppositeBias,
manualRequireDisplacement,
manualDisplacementAtr,
manualFvgCount,
manualFvgAtrFilter,
manualFvgAtrSize,
manualObCount,
manualObLookback,
manualObStructureRequirement,
manualObBodyMode,
manualLiquidityLookback,
manualEqualLevelTolerance,
manualSweepCloseBack,
manualProfileMode,
manualProfileBars)
```
The example import path should be replaced with the exact path assigned by PulseWire after publication.
WHY THE CHART IS CLEAN
This is a non-visual configuration library. It intentionally creates no plots, labels, tables, lines or boxes.
The publication chart is therefore intentionally clean and contains no additional indicators, drawings or unexplained visual elements. An importing indicator is responsible for presenting the resolved settings.
LIMITATIONS
• Automatic profiles are applied only to exact supported combinations.
• The library does not optimize settings or claim that a profile is profitable.
• It does not independently inspect a symbol or identify a broker feed.
• It does not read live market data.
• It does not preserve state between executions.
• It does not place, modify or close orders.
• It produces no chart output by itself.
This library is a reusable software-development component. It is not investment advice, a trading signal or an automated trading system. Library

SMCNexusScoringCoreV2SMCNexusScoringCoreV2 is an open-source, non-visual Pine Script library that calculates a deterministic Smart Money Concepts evidence score from market facts supplied by an importing indicator.
The library does not independently read chart state, request other timeframes, generate trading signals, place orders or draw chart objects. Its purpose is to separate the scoring calculation from detection and presentation code, making every component reusable and independently auditable.
ORIGINAL CONCEPT AND PURPOSE
The library combines twelve bounded Smart Money Concepts evidence components into one normalized 0–100 result while retaining each individual component in the returned ScoreResult record.
It also provides optional event-age decay for selected structural evidence. This prevents an old BOS, CHoCH, MSS or liquidity sweep from retaining the same influence indefinitely.
The importing indicator is responsible for detecting and confirming market events. This library receives those facts through typed parameters and performs deterministic calculations only. It does not infer missing events or substitute unknown data.
CALCULATION METHOD
The twelve components are:
1. Market Structure Shift
2. Break of Structure
3. Change of Character
4. Fair Value Gap
5. Order Block
6. Liquidity context
7. Liquidity sweep
8. Premium or Discount location
9. Volume state
10. Momentum state
11. Local Smart Money context
12. Primary trend
Each component contributes a bounded value based on the supplied state. The component total is divided by twelve and normalized to a value from 0 to 100.
The resulting descriptive classes are:
• VERY WEAK
• WEAK
• NEUTRAL
• STRONG
• ELITE
These classes describe the supplied analytical evidence. They are not trading recommendations and do not predict future performance.
AGE DECAY
When age decay is enabled, the selected structural and sweep components use a linear age factor.
The factor:
• remains at 1.0 until the configured full-strength age,
• decreases linearly between the full-strength and zero-strength ages,
• reaches 0.0 at or beyond the configured zero-strength age.
If the supplied age window is invalid, the calculation fails safely to full strength instead of producing a negative or undefined weight.
PUBLIC API
ScoreResult
The returned record contains:
• all twelve effective components,
• effective MSS age factor,
• effective BOS/CHoCH age factor,
• effective sweep age factor,
• component total,
• normalized score,
• descriptive class,
• compact text representation.
calculate(...)
This function accepts typed, confirmed market facts and returns one ScoreResult record.
INTENDED USE
An importing indicator should:
1. Detect and confirm its own market-structure events.
2. Determine its current FVG, Order Block, liquidity, volume, momentum and trend states.
3. Pass those facts to calculate().
4. Read the normalized result or inspect the individual returned components for a complete breakdown.
Conceptual example:
```pine
import AreXoN_/SMCNexusScoringCoreV2/1 as scoring
scoring.ScoreResult result = scoring.calculate(
scoringEnabled,
ageDecayEnabled,
bar_index,
lastMssBar,
lastBreakBar,
lastSweepBar,
structureFullStrengthBars,
structureZeroStrengthBars,
sweepFullStrengthBars,
sweepZeroStrengthBars,
mssDirection,
breakType,
breakDirection,
fvgType,
fvgMitigated,
obType,
obMitigated,
liquidityContext,
sweepType,
premiumDiscountZone,
volumeState,
momentumState,
smartMoneyState,
primaryTrendState)
```
The example import path should be replaced with the exact path assigned by PulseWire after publication.
WHY THE CHART IS CLEAN
This is a non-visual calculation library. It intentionally creates no plots, labels, tables, lines or boxes. Visual output is the responsibility of an importing indicator.
The publication chart is therefore intentionally clean and contains no additional indicators or unexplained drawings.
LIMITATIONS
• Output quality depends on the facts supplied by the importing indicator.
• The library does not independently verify market events.
• It does not provide native bid/ask order flow or broker execution data.
• It does not account for spread, slippage or broker restrictions.
• It does not place, modify or close orders.
• It produces no chart output by itself.
• A score or class is not a guarantee of future market behavior.
This library is an analytical and software-development component. It is not investment advice or an automated trading system. Library

Library

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

Library

NeuralMarketsNetworkToolkitLibrary "NeuralMarketsNetworkToolkit"
Open-source network analysis toolkit for Pine Script.
This library provides reusable graph algorithms, matrix utilities and network analytics for building advanced multi-asset indicators. Rather than treating markets as isolated charts, it enables developers to model relationships between assets as weighted networks and extract structural characteristics such as connectivity, centrality, clustering and influence.
Current Modules
• Matrix utilities
• Directed & undirected graphs
• Network analytics
• Node analytics
• Graph algorithms
• Experimental financial network tools
Example Applications
• Correlation networks
• Market leadership analysis
• Sector relationship maps
• Cross-asset dependency analysis
• Financial network research
Design Philosophy
This toolkit provides reusable quantitative building blocks rather than trading signals. Functions are intentionally modular so they can be combined into custom indicators and research projects.
Markets are networks. This toolkit provides the building blocks to analyze them as such.
--------------------------------------------------------------------
matrixIndex(row, col, n)
Converts row/column coordinates into a flat matrix index.
Parameters:
row (int) : Row index.
col (int) : Column index.
n (int) : Matrix dimension.
Returns: Flat-array index.
clamp(x, lo, hi)
Clamp a float.
Parameters:
x (float) : Value.
lo (float) : Minimum.
hi (float) : Maximum.
Returns: Clamped value.
newMatrix(n, initialValue)
Creates an n x n flat matrix initialized to a value.
Parameters:
n (int) : Number of nodes.
initialValue (float) : Initial cell value.
Returns: Flat float array.
setCell(matrix, row, col, n, value)
Sets a matrix cell.
Parameters:
matrix (array) : Flat matrix.
row (int) : Row.
col (int) : Column.
n (int) : Matrix dimension.
value (float) : New value.
getCell(matrix, row, col, n)
Gets a matrix cell.
Parameters:
matrix (array) : Flat matrix.
row (int) : Row.
col (int) : Column.
n (int) : Matrix dimension.
Returns: Cell value.
setUndirectedEdge(matrix, a, b, n, weight)
Sets both directions of an undirected edge.
Parameters:
matrix (array) : Flat matrix.
a (int) : Node A.
b (int) : Node B.
n (int) : Matrix dimension.
weight (float) : Edge weight.
meanAbsoluteConnectivity(matrix, n)
Average absolute pairwise edge weight.
Parameters:
matrix (array) : Symmetric adjacency/weight matrix.
n (int) : Number of nodes.
Returns: Average absolute connectivity from 0 upward.
meanSignedConnectivity(matrix, n)
Average signed pairwise weight.
Parameters:
matrix (array) : Symmetric matrix.
n (int) : Number of nodes.
Returns: Mean signed relationship.
density(matrix, n, threshold)
Proportion of possible edges whose absolute weight exceeds threshold.
Parameters:
matrix (array) : Symmetric weight matrix.
n (int) : Number of nodes.
threshold (float) : Absolute edge threshold.
Returns: Network density from 0 to 1.
fragmentation(matrix, n, threshold)
Network fragmentation as inverse threshold density.
Parameters:
matrix (array) : Symmetric weight matrix.
n (int) : Number of nodes.
threshold (float) : Edge threshold.
Returns: Fragmentation from 0 to 1.
nodeDegree(matrix, n, node, threshold)
Number of strong edges attached to a node.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
node (int) : Node index.
threshold (float) : Absolute edge threshold.
Returns: Degree count.
nodeStrength(matrix, n, node)
Sum of absolute edge weights attached to node.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
node (int) : Node index.
Returns: Node strength.
strongestNode(matrix, n)
Node with greatest absolute network strength.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
Returns: Strongest node index.
averageNodeStrength(matrix, n)
Average node strength.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
Returns: Mean strength.
centralization(matrix, n)
Measures how much one node dominates the network.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
Returns: Strength centralization approximately 0 to 1.
strengthEntropy(matrix, n)
Shannon entropy of node-strength distribution.
Parameters:
matrix (array) : Weight matrix.
n (int) : Number of nodes.
Returns: Normalized entropy from 0 to 1.
mstDistance(matrix, n)
Computes total Prim minimum-spanning-tree distance.
Similarity is converted to distance using 1 - abs(similarity).
Parameters:
matrix (array) : Similarity matrix.
n (int) : Number of nodes.
Returns: Total MST distance.
mstCompactness(matrix, n)
Converts MST distance to compactness.
Parameters:
matrix (array) : Similarity matrix.
n (int) : Number of nodes.
Returns: Network compactness from approximately 0 to 1.
setDirectedEdge(matrix, fromNode, toNode, n, weight)
Sets one directed edge.
Parameters:
matrix (array) : Flat directed adjacency matrix.
fromNode (int) : Source node.
toNode (int) : Destination node.
n (int) : Number of nodes.
weight (float) : Directed edge weight.
outStrength(matrix, n, node)
Sum of outgoing positive influence from a node.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
node (int) : Source node.
Returns: Total outbound influence.
inStrength(matrix, n, node)
Sum of incoming positive influence to a node.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
node (int) : Destination node.
Returns: Total inbound influence.
netInfluence(matrix, n, node)
Net directional leadership.
Positive means the node influences others more than it follows them.
Negative means the node behaves more like a follower.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
node (int) : Node index.
Returns: Outbound minus inbound influence.
normalizedLeadership(matrix, n, node)
Normalized directional leadership score.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
node (int) : Node index.
Returns: Score approximately from -1 to +1.
leadingNode(matrix, n)
Node with the largest net directional influence.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
Returns: Node index.
followingNode(matrix, n)
Node with the greatest incoming influence.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
Returns: Node index.
meanDirectedInfluence(matrix, n)
Average directed influence in the network.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
Returns: Mean positive directed edge weight.
leadershipConcentration(matrix, n)
Concentration of outbound influence.
High values mean leadership is concentrated in fewer nodes.
Parameters:
matrix (array) : Directed matrix.
n (int) : Number of nodes.
Returns: Herfindahl-style concentration from 0 to 1.
connectedComponentsCount(matrix, n, threshold)
Counts connected components in an undirected threshold graph.
Parameters:
matrix (array) : Symmetric adjacency / similarity matrix.
n (int) : Number of nodes.
threshold (float) : Minimum absolute edge weight required to connect nodes.
Returns: Number of connected components.
localClusteringCoefficient(matrix, n, node, threshold)
Computes local clustering coefficient for one node.
Measures how interconnected the node's neighbors are.
Parameters:
matrix (array) : Symmetric similarity matrix.
n (int) : Number of nodes.
node (int) : Node index.
threshold (float) : Minimum absolute edge weight to define a connection.
Returns: Local clustering coefficient from 0 to 1.
averageClusteringCoefficient(matrix, n, threshold)
Computes mean clustering coefficient across all nodes.
Parameters:
matrix (array) : Symmetric similarity matrix.
n (int) : Number of nodes.
threshold (float) : Minimum absolute edge weight.
Returns: Average clustering coefficient from 0 to 1.
similarityDistance(similarity)
Converts similarity to graph distance.
Higher similarity becomes shorter distance.
Parameters:
similarity (float) : Edge similarity, typically from 0 to 1 in magnitude.
Returns: Distance from 0 to 1.
shortestPathDistance(matrix, n, source, target)
Dijkstra shortest-path distance between two nodes.
Uses distance = 1 - abs(similarity).
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
source (int) : Start node.
target (int) : End node.
Returns: Shortest path distance.
averagePathLength(matrix, n)
Average shortest-path distance across all node pairs.
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
Returns: Mean shortest path distance.
eigenvectorCentrality(matrix, n, node, iterations)
Approximate eigenvector centrality for one node using power iteration.
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
node (int) : Node index.
iterations (int) : Number of power iterations.
Returns: Approximate normalized centrality from 0 to 1.
eigenvectorLeader(matrix, n, iterations)
Returns node with highest eigenvector centrality.
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
iterations (int) : Number of power iterations.
Returns: Node index.
nodeStrengthPercentile(matrix, n, node)
Cross-sectional percentile rank for a node's strength.
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
node (int) : Node index.
Returns: Percentile rank from 0 to 100.
nodeStrengthRank(matrix, n, node)
Returns the rank position of a node by strength.
Rank 1 means strongest.
Parameters:
matrix (array) : Weighted matrix.
n (int) : Number of nodes.
node (int) : Node index.
Returns: One-based rank.
networkCohesion(matrix, n, threshold)
Composite network cohesion score.
Combines connectivity, density and clustering coefficient.
Parameters:
matrix (array) : Symmetric similarity matrix.
n (int) : Number of nodes.
threshold (float) : Edge threshold.
Returns: Composite cohesion from 0 to 1. Library

ExpEngineThe engine behind the EXP GRID / EXP OVERLAY reconstruction pair.
An indicator is either overlay or pane, never both. So a study that wants to draw levels on price AND report statistics about those levels has to be two scripts — and two scripts means two copies of the decision logic, and two copies drift. This library exists so that they cannot: the pane cannot measure a different trade than the price chart draws, because there is only one definition of it.
WHAT IS IN HERE
context() — nine signed volume and efficiency features, each clamped to , and the composite they average into.
aligned() / plan() — the arming condition and the trade state machine: arm on alignment, enter on a break of the prior bar in the armed direction, exit on stop, target, or the clock, whichever comes first. Tracks MFE, MAE, realised R and a running win/loss record.
shadow() — a random-entry baseline that runs under the IDENTICAL exit rule. A base rate computed under a different exit rule is not a base rate.
TWO THINGS WORTH KNOWING
When both the stop and the target are touched inside a single bar, the intrabar path is unknowable, so plan() assumes the STOP filled first. Calling that one a win is the most common way a backtest lies to you.
macroBundle() applies to every leg and is meant to be called with lookahead_on. That pairing is the only one of the four offset/lookahead combinations that reads a CLOSED higher-timeframe bar in both history and realtime; change one without the other and the script either leaks the future or disagrees with itself live. A library cannot make the request itself — Pine rejects a request.*() whose expression depends on an exported function's arguments (CE10051) — so the call site stays in your script:
= request.security(syminfo.tickerid, tf, es.macroBundle(len, aLen), lookahead = barmerge.lookahead_on)
float macroAtr = es.macroBias(mEma, mAtr, mClose)
Everything here reads confirmed bars only.
Library "ExpEngine"
version()
macroBundle(len, aLen)
Parameters:
len (simple int)
aLen (simple int)
macroBias(mEma, mAtr, mClose)
Parameters:
mEma (float)
mAtr (float)
mClose (float)
context(volLen, erFastLen, erSlowLen, atrLen, macroAtr)
Parameters:
volLen (simple int)
erFastLen (simple int)
erSlowLen (simple int)
atrLen (simple int)
macroAtr (float)
aligned(c, sessOpen, strongBand, armRvol)
Parameters:
c (Ctx)
sessOpen (bool)
strongBand (float)
armRvol (float)
plan(c, ok, stopAtr, rr, timeExit)
Parameters:
c (Ctx)
ok (bool)
stopAtr (float)
rr (float)
timeExit (int)
shadow(c, sessOpen, every, stopAtr, rr, timeExit)
Parameters:
c (Ctx)
sessOpen (bool)
every (simple int)
stopAtr (float)
rr (float)
timeExit (int)
Ctx
Fields:
fRvol (series float)
fPress (series float)
fCvd (series float)
fVwma (series float)
fEff (series float)
fRange (series float)
fClv (series float)
fMacro (series float)
fPersist (series float)
composite (series float)
macroAtr (series float)
rvol (series float)
atr (series float)
erF (series float)
erS (series float)
hasVol (series bool)
Plan
Fields:
state (series int)
dir (series int)
entry (series float)
stop (series float)
target (series float)
risk (series float)
entryBar (series int)
armed (series bool)
entered (series bool)
exited (series bool)
win (series bool)
rMult (series float)
exitPx (series float)
mfe (series float)
mae (series float)
mfeBar (series int)
lastMfe (series float)
lastMfeMin (series float)
wins (series int)
losses (series int)
avgWinBars (series float)
avgLossBars (series float)
avgMaeWin (series float)
sumR (series float)
Tally
Fields:
state (series int)
dir (series int)
entry (series float)
stop (series float)
target (series float)
bar (series int)
wins (series int)
losses (series int)
sumR (series float) Library

Library

EdgeStatsLibrary "EdgeStats"
A win rate on its own is not evidence. This library supplies the four things that turn one into a claim you can defend, none of which Pine ships: a base rate to subtract, a sample size corrected for overlapping forward windows, a confidence interval that behaves at small n, and a p-value that knows how many settings you tried before you picked this one.
The argument in three lines, all from the same 60 wins out of 100:
assess(60, 100, 0.5, horizon = 1) p = 0.046 significant
assess(60, 100, 0.5, horizon = 10) p = 0.527 not significant
assess(60, 100, 0.5, horizon = 10, trials = 30) p = 1.000 nothing at all
Nothing changed about the data. What changed is being honest that ten-bar forward returns sampled every bar are not a hundred independent observations, and that the best of thirty settings is not the same evidence as the only setting you tried.
WHAT THE DEMO SHOWS
Added to a chart directly, the library grades an ordinary signal: close above a 50 EMA, judged on whether price is higher ten bars later, over the last 500 bars. On BTCUSD 1h at the time of writing that is a hit rate of 39.9% against a base rate of 50.4%, an edge of -10.5 percentage points, and a two-sided p of 0.297.
Read that carefully, because it is the whole point. The signal looks bad. It is not reliably bad. Twenty-five independent observations cannot separate -10.5 points from noise, and the interval runs from 23.3% to 59.3%. A tool that says "I cannot tell" when it cannot tell is the only kind worth having.
THREE HONEST CAVEATS
n / horizon is a rough correction, not a theorem. It assumes overlap is the dominant source of dependence between observations. Where returns are autocorrelated beyond the window it is still optimistic. Treat it as a floor on your uncertainty rather than a ceiling.
zFor bisects normCdf, which is itself an approximation, so it inherits that error: zFor(0.95) lands about 1.2e-6 below the textbook 1.9599640. Irrelevant in practice, but it is an approximation of an approximation and you should hear that from me rather than discover it.
roll() uses ta.cum internally, so its call site must execute on every bar. Called inside "if barstate.islast" it has one bar of history and returns nonsense, and no max_bars_back setting repairs that. This is a property of Pine functions rather than of this library, and it is worth knowing generally.
VERIFICATION
Every fixed-input value is plotted to the Data Window and two are printed on the chart, so you can check the arithmetic rather than trust it. Against Python statistics.NormalDist:
normCdf(1.96) 0.9750022 true 0.9750021
normCdf(-1.0) 0.1586553
zFor(0.95) 1.9599628 true 1.9599640
zFor(0.99) 2.5758313 true 2.5758293
wilson(60, 100, 1.96)
selectionAdjusted(0.05, 30) 0.7853612
Corrections welcome, particularly to the effective sample size treatment, which is the part I would most like to be wrong about.
REFERENCE
normCdf(x)
Standard normal cumulative distribution. Abramowitz and Stegun 26.2.17, absolute error below 7.5e-8 across the whole real line.
Parameters:
x (float) : Value to evaluate.
Returns: Probability that a standard normal variate is at most x.
zFor(conf)
Two-sided z multiplier for a confidence level. Bisects normCdf, so any level works rather than a lookup of the usual three.
Parameters:
conf (float) : Confidence level in (0, 1). 0.95 returns 1.9599628.
Returns: The z for which the central interval of that width has the given coverage.
@remark Converged to float precision against normCdf, which is itself an approximation, so the result inherits its error: zFor(0.95) lands about 1.2e-6 below the textbook 1.9599640. Irrelevant for anything you would do with it, but it is an approximation of an approximation and worth saying so.
nEff(n, horizon)
Effective independent sample size when observations use overlapping forward windows.
Parameters:
n (float) : Raw observation count.
horizon (int) : Length in bars of the forward window each observation measures.
Returns: n divided by the horizon, with the horizon floored at 1.
wilson(hits, n, z)
Wilson score interval for a proportion. Unlike the normal approximation it stays inside and stays sane when n is small or the rate sits near an edge.
Parameters:
hits (float) : Successful observations.
n (float) : Total observations. Pass an effective count here, not a raw bar count, when the windows overlap.
z (float) : Multiplier from zFor().
Returns: A tuple on the proportion, or when there is no sample.
selectionAdjusted(p, trials)
Sidak correction. If you searched k settings and reported the best one, the p-value you found is not the p-value that best one deserves.
Parameters:
p (float) : Uncorrected two-sided p-value.
trials (int) : Settings, symbols or variants searched before this one was chosen. Pass 1 if you did not search.
Returns: Probability of seeing something at least this good in k independent tries.
roll(src, len)
Rolling window sum valid from the first bar, unlike math.sum which stays na until the window fills. Useful for counting events over a lookback.
Parameters:
src (float) : Series to accumulate.
len (simple int) : Window length in bars.
Returns: Sum of the last len values of src.
@remark Uses ta.cum internally, so the CALL SITE must execute on every bar. Called inside `if barstate.islast` it has one bar of history and returns nonsense. That is a property of Pine functions rather than of this library, and no max_bars_back setting repairs it. len is `simple` so Pine can size the history buffer at compile time.
assess(hits, n, base, horizon, conf, trials)
The whole assessment in one call.
Parameters:
hits (float) : Observations where the signal was right.
n (float) : Total observations.
base (float) : Rate at which the same outcome occurred unconditionally over the same horizon. This is the number that makes an edge an edge.
horizon (int) : Bars in the forward window. Overlapping windows shrink the effective sample.
conf (float) : Confidence level for the interval, default 0.95.
trials (int) : Settings searched before choosing this one, default 1.
Returns: A Verdict.
describe(v)
One line of plain English for a Verdict, sized to drop straight into a table cell.
Parameters:
v (Verdict) : The Verdict to describe.
Returns: A human-readable summary, or "no sample" when there is nothing to say.
Verdict
Everything needed to decide whether a measured hit rate means anything.
Fields:
rate (series float) : Observed hit rate, 0 to 1.
base (series float) : Base rate the signal is measured against, 0 to 1.
edge (series float) : rate minus base, in percentage points.
n (series float) : Raw observation count as supplied.
nEff (series float) : Observation count after the overlapping-window correction.
lo (series float) : Lower confidence bound on rate, computed on nEff.
hi (series float) : Upper confidence bound on rate, computed on nEff.
z (series float) : Test statistic of rate against base.
p (series float) : Two-sided p-value, already Sidak-adjusted for the trials argument.
clears (series bool) : True when the interval on the rate excludes the base rate. Library

Regression_ToolkitThis is toolkit/library bridges advanced regression approaches not natively supported in Pinescript, to Pinescript. Advanced regression frameworks that can be critical to ticker data, such as Ridge, Lasso, ElasticNET, and Logistic (normalized) regression, colinarity measuring and quantile regression. As well as approaches to linear based feature selection and importance assessments.
I hope you find it helpful!
Library "Regression_Toolkit"
multipleRegression(y, x1, x2, length)
Parameters:
y (float)
x1 (float)
x2 (float)
length (simple int)
ridgeRegression(y, x1, x2, x3, x4, nVars, length, lambda)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
lambda (simple float)
lassoRegression(y, x1, x2, x3, x4, nVars, length, lambda, iterations)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
lambda (simple float)
iterations (simple int)
logisticRegression(y, x1, x2, x3, x4, nVars, length, learningRate, iterations)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
learningRate (simple float)
iterations (simple int)
featureSelection(y, x1, x2, x3, x4, nVars, length)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
regressionStats(y, x1, x2, x3, x4, nVars, length, b0, b1, b2, b3, b4)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
b0 (float)
b1 (float)
b2 (float)
b3 (float)
b4 (float)
elasticNetRegression(y, x1, x2, x3, x4, nVars, length, lambda, alpha, iterations)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
lambda (simple float)
alpha (simple float)
iterations (simple int)
huberRegression(y, x1, x2, x3, x4, nVars, length, huberK, iterations)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
huberK (simple float)
iterations (simple int)
quantileRegression(y, x1, x2, x3, x4, nVars, length, tau, learningRate, iterations)
Parameters:
y (float)
x1 (float)
x2 (float)
x3 (float)
x4 (float)
nVars (simple int)
length (simple int)
tau (simple float)
learningRate (simple float)
iterations (simple int) Library

TVA_MathLibraryLibrary "TVA_MathLibrary"
f_htfBundle(tf)
Parameters:
tf (simple string)
f_htfBias(c, e20, e50, e200, r, atrv, adxv)
Parameters:
c (float)
e20 (float)
e50 (float)
e200 (float)
r (float)
atrv (float)
adxv (float)
f_stdTrendScore(c, e20, e50, e200, r, adxv)
Parameters:
c (float)
e20 (float)
e50 (float)
e200 (float)
r (float)
adxv (float)
f_confirmationScore(setupDir, biasW, biasD, bias4H, bias1H)
Parameters:
setupDir (int)
biasW (float)
biasD (float)
bias4H (float)
bias1H (float)
f_confluenceScore(alignmentPct, momentumConverge, adxv, volatilityCtx, volumeConfirm)
Parameters:
alignmentPct (float)
momentumConverge (float)
adxv (float)
volatilityCtx (float)
volumeConfirm (float)
f_buyProbability(baseBullPct, c, e20, e50, e200, r, macdHist, macdHistPrev, vol, volEma20, distToSupportATR, adxv, adxRising)
Parameters:
baseBullPct (float)
c (float)
e20 (float)
e50 (float)
e200 (float)
r (float)
macdHist (float)
macdHistPrev (float)
vol (float)
volEma20 (float)
distToSupportATR (float)
adxv (float)
adxRising (bool)
f_sellProbability(baseBearPct, c, e20, e50, e200, r, macdHist, macdHistPrev, vol, volEma20, distToResistATR, adxv, adxFallingDown)
Parameters:
baseBearPct (float)
c (float)
e20 (float)
e50 (float)
e200 (float)
r (float)
macdHist (float)
macdHistPrev (float)
vol (float)
volEma20 (float)
distToResistATR (float)
adxv (float)
adxFallingDown (bool)
f_marketRegime(adxv, efficiencyRatio, atr20, atr50, bbWidth, bbWidthEma20)
Parameters:
adxv (float)
efficiencyRatio (float)
atr20 (float)
atr50 (float)
bbWidth (float)
bbWidthEma20 (float)
f_chopIndex(adxv, diPlus, diMinus, efficiencyRatio, bbWidth, bbWidthEma20)
Parameters:
adxv (float)
diPlus (float)
diMinus (float)
efficiencyRatio (float)
bbWidth (float)
bbWidthEma20 (float)
f_volatilityClass(atrPercentile, histVolPercentile, trExpansionRatio, bbWidthPercentile)
Parameters:
atrPercentile (float)
histVolPercentile (float)
trExpansionRatio (float)
bbWidthPercentile (float)
f_emaSmooth2(src)
Parameters:
src (float)
f_scoreColor(score, highIsGood)
Parameters:
score (float)
highIsGood (bool)
f_gaugeText(score, label)
Parameters:
score (float)
label (string)
f_alignmentBar(pct)
Parameters:
pct (float) Library

Library

EWCoreLibEWCoreLib — Elliott Wave Pattern Evaluation Library
Overview
EWCoreLib is a Pine Script v6 library of exported functions that validate and score Elliott Wave price patterns. It has no chart output of its own and is not meant to be added to a chart; a calling script supplies the pivot data and decides what to do with the results.
It is one of three scripts published together: the EWCore indicator, this library, and EWCore Docs, an on-chart reference panel for EWCore.
If you are using EWCore, there is nothing to do here. EWCore pulls in this library itself, as part of its own code — you add EWCore to your chart and the library comes with it. This page exists for Pine programmers who want to call these functions from a script of their own, and as the open source behind EWCore's evaluation stage. The dependency runs one way only: EWCore needs this library, the library needs nothing from EWCore, and any script that can produce its own pivot series can use it.
Relation to the earlier publication
An earlier version of this library was published under the name EWCoreEvaluators. This publication continues the same codebase under a new name; it is not a variant or a competing implementation. The name changed because the earlier title stays bound to the earlier publication and cannot be reused. Any script that imports the old path should be pointed at Wick-Sniper/EWCoreLib, which is the one that receives further work.
Concepts
Pivots in, verdicts out. Every evaluator takes a pivot series — prices and bar positions in two parallel arrays — plus a starting index, and asks one question about the window beginning there: does this stretch of price form the pattern I check for? The answer comes back as a filled WaveCount object carrying the wave points, the hard-rule verdict, the component scores and an invalidation level, or as an empty one if the window does not qualify.
Configuration travels as an object, not as a parameter list. An exported function cannot read the global variables of the script importing it, and these evaluators need a great many settings — tolerances, score weights, Fibonacci levels, feature toggles. Passing them individually would mean unwieldy signatures that break on every added option. Instead the calling script builds one EngineConfig object per bar and hands it to whichever functions it calls.
Every exported function is pure. Parameters in, values out, no hidden state. That is what makes it safe to call the same evaluator from several contexts in one bar — a forward search, a historical chain walk, a sub-wave decomposition — without behaviour drifting between them.
Marginal violations are penalised, not rejected. A candidate that misses a rule by a hair is scored down rather than discarded, so a near-miss reading stays visible and comparable instead of vanishing silently.
Exported types
WaveCount — one complete candidate scenario: pattern type, direction, degree label, wave points and their bars, hard-rule and overlap flags, component scores, confidence tier, invalidation level, extension info.
EngineConfig — the settings bundle described above.
Exported functions, by purpose
Pattern evaluation — one per pattern in the canon this project supports: evaluateImpulseWindow, evaluateDiagonalWindow, evaluateZigzagFlatWindow, evaluateTriangleWindow, evaluateComboWXYWindow, evaluateComboWXYXZWindow, evaluateImpulseRecoveredWindow (rebuilds an impulse whose fourth wave the coarse pivot pass swallowed), evaluateLegWhole (judges a whole leg as a single structure rather than a chain of fragments).
Type arbitration — f_discriminateWindow, f_evalWindowTrio: when impulse, diagonal and triangle all pass on the same window, these decide which type the window really is, so the least strict pattern cannot win by default.
Re-checking and scoring — revalidateCandidate, f_comboBonus, f_dpEdgeModifier, f_legDominance, f_legWholeDominance, f_evalCandDegStep, f_evalFloorLeg, f_candDegPasses, f_floorLegPasses.
Chain and gap handling — f_realGapFill (dynamic-programming best-path search for a continuous chain of valid patterns across a pivot series), f_gapNoiseMetrics, f_depth2InnerLegs.
Degree handling — getDegreeLabel, shiftDegreeUp, shiftDegreeDown, f_degreeNameFor, f_notatedLabelTextArray: translate between Elliott degrees and the notation that belongs to each.
Explanatory text — f_patternExplanation, f_extGlyph, f_extTooltip, f_atomicDiagText, f_gapBridgeText, f_rankStage, f_rankWhy, impulseFunnelText, comboFunnelText: turn a verdict into readable reasoning for labels and tooltips.
Drawing helpers — drawImpulseFunnel, drawComboFunnel, f_drawWholeLegFallback, f_drawWholeLegFallbackFromPivots, f_drawWholeLegFallbackFromArrays, f_drawExplanationLabel, f_drawDateMarker, f_drawRoutedLeg.
Utilities — subLowerBound, f_barValToTime (resolves a stored bar value to a timestamp; historical drawings need xloc.bar_time), getLabelSize, f_lineStyle, f_frameCount.
Calling it from your own script
This section is for Pine programmers writing their own script. EWCore users can skip it — EWCore handles the import itself.
import Wick-Sniper/EWCoreLib/1 as ewcore
Type the alias by hand. The "copy to clipboard" button on the library page appends the library name a second time and produces an import line that does not resolve.
From there, build an EngineConfig once per bar, then call the evaluator for the pattern and window you are testing and read the returned WaveCount.
Notes
This library validates structure; it does not detect pivots. The quality of everything it returns depends on the pivot series you feed it — a threshold that admits noise produces confident verdicts about noise. In this project's own testing, wave counting becomes reliable at 15-minute charts and above.
A passing verdict means a reading exists that satisfies the rules checked, not that it is the correct count. Elliott Wave analysis admits more than one valid interpretation of the same chart, and these functions score candidates rather than settle them.
This library is a technical analysis building block. It is not financial advice and generates no trading signals. Library

Public_Library_ChessTalkThis is where the Chess script keeps its trash talk. The library stores every line the computer can say, and decides when it speaks and which line it picks. It imports nothing, knows nothing about chess, and never calls `math.random()`.
There are eight kinds of occasion: the computer won material, it lost material, it promoted, it's still in its opening book, the game just started, it wins, it loses, or the game ends in a draw. Each occasion fires at its own rate, so the computer needles you now and then rather than commenting on every move. Every decision comes from arithmetic on a seed boiled down from the moves played so far, which means the same game always says the same lines, however many times you reload, and a chosen line can't flicker between ticks.
We pass the {piece} token in so that a line can name its victim ("Mmm... free {piece}." becomes "Mmm... free knight."), and per-line filters keep the puns honest - the "good knight" gag only fires when a knight actually dies. A no-repeat rule stops a category saying the same line twice in a row. The banks run to 97 lines of misquoted pop culture.
The `buildTalkState()` function packs the banks, the rates, the no-repeat memory and the wounded detection into one object, so the consumer holds one variable instead of fifteen. The consumer spots the occasion while it replays the game, asks this library for a line, and stores what it gets. The live bar only reads.
See the Chess script for the backchat in action:
Library

Public_Library_ChessBookThis library holds the opening book for the Chess script. It lives apart from the brain (ChessAI) so the openings can grow without republishing the logic. It imports nothing and contains no logic of its own beyond building the map.
Each entry pairs the moves played so far (both sides' moves, lowercase, one space between) with our reply, written the same way - so the key "e2e4 e7e5" answers with "g1f3". Some entries offer several replies separated by "|", and the consumer picks between them with its game seed, so back-to-back games can open differently. The empty-string key holds White's very first move.
We use a map because the book question is exactly a lookup: given the moves played so far, what do we reply? Simply query the canonical move string as the map key and if we get a reply that's our move in response.
Pine maps can't hold arrays as values, which is why several replies pack into one "|"-separated string. Of course we could define a UDT that contains an array, but it's overhead. The trade-off of keying by move sequence rather than by position is that an unusual move order into a known position misses the book - the cost is an early exit to the ladder, never a wrong move, and in exchange every entry in the source reads as a real game you can play through.
The book holds enough entries for every common defence and sideline on both sides, deeper main lines, and wider choices in some of them.
This split of data from calculation is worth using for non-chess scripts: when a big lookup table and the logic that reads it live in separate libraries, the table can grow on its own release schedule.
See the Chess script to play the book in a real game: Library

Public_Library_ChessAIThis library is the brain of the Chess script: a small chess opponent built on the ChessCore rules engine.
It is not a search engine. It is a ladder of ten rules that looks at one position, tries the rules in order, and plays the first that fires:
1. Mate in one
2. Opening book
3. Avoid checkmate
4. Defence
5. Win material
6. Safe check
7. Exchange when ahead
8. Endgame
9. Develop
10. Any other safe move
🟩 THE FORESEE
Before the ladder runs, a foresee stage takes every legal move and adds to its object its most likely material outcome. This score comes from the opponent's best replies to our move, and a few captures after that. We look at the opponent's best captures, his checks, his most menacing quiet threats, and what happens if we don't take. We also look briefly whether two checks in a row force mate. Deep thinking follows more replies and reads six half-moves.
The score works mostly as a veto. From the list of possible moves for a ladder stage, we reject the ones that end in us being checkmated. When every legal move walks into one, we toss a coin to decide between playing the least-bad move and resigning.
🟩 KEEPING A WON GAME WON
If we are winning we want to win, not draw. While ahead on material, the quiet rules refuse any move that recreates a position the game has already seen, so it can't shuffle a rook between two good squares forever. And the foresee prices a stalemate at minus the lead it would throw away, so the winning side sidesteps the trap while the losing side, correctly, steers toward it. The endgame rule gives the ladder actual technique (push passers, rook to the seventh, king up to escort) to try to win.
🟩 DETERMINISM
No `math.random()` call decides anything on its own. The first five rules always give the same answer for a position. The last five pick from their pools with a seed the consumer supplies, derived from the game record. Variety between games comes from the consumer script mixing a clock reading into the seed, not from the library.
🟩 PROCESS FLOW
The exported functions are called in a certian order for each position:
ChessCore generates the legal moves.
`annotateMoves()` counts the attackers and defenders on every move's landing square, and notes the cheapest attacker. Every safety test the rules make reads these three numbers.
`filterPromotions()` and `classifyMoves()` trim pointless pawn promotions and flag moves that make the king's cover worse or that just undo the previous move.
The foresee adds a score to each candidate move: `foreseePrepare()` starts the story, `foreseeFinishCaptures()` follows the capture lines, and `foreseeFinishRest()` follows the checks and quiet threats. The consuming script spreads these calls across chart bars so no single bar works too hard.
The ladder rules run in order, `ruleMateInOne()` down to `ruleFallback()`, and the first one that returns a move wins.
See the Chess script to play against this AI: Library

Public_Library_ChessCoreThe rules of chess as a reusable Pine engine. It doesn't display anything or think of any moves. It just defines what is legal. This is the foundation library of the Chess script, and it's built so that any Pine project needing real chess - a different engine, a puzzle board, a game replayer - can build on it without rewriting the rules.
🟩 WHAT IT DOES
Keeps the whole position in one object: the board, whose turn it is, castling rights, the en-passant target, the move clocks, and a cached king square for each side.
Generates every fully legal move for the side to move, including castling, en passant, and promotions. It checks first based on how the pieces can move, and then creates a copy board to test which moves keeps the king out of check - so pins, discovered checks and the en-passant edge cases all just work.
Applies a move to a position and does all the admin.
Detects checkmate, stalemate, and the automatic draws. For threefold repetition it provides position keys and a counting helper. The consumer keeps the key history, because that's the one draw that needs to remember earlier positions, and these functions deliberately hold no history of their own.
Parses a typed move record like "e2e4 e7e5" - junk-tolerant and case-insensitive, so "e2-e4, E7e5" parses the same - and rebuilds it as one tidy canonical string. The Chess consumer uses that canonical record as its opening-book key and its random seed.
🟩 DESIGN NOTES
The big thing here is the scan that answers "who attacks this square?", with variants that count the attackers and price the cheapest one.
Another important part is the test of whether a move is legal on a COPY board. One definition of "attacked" is shared by the move generator, the game-status detection and castling's transit-square tests, so they can never disagree about what check means.
Each generated move is an object whose scoring fields are declared here but filled in from outside - `foreseeScore` for an AI's look-ahead, plus two endgame scores. ChessCore itself never touches them. This declare-then-fill pattern is how a foundational library can carry data that a higher library computes, without circular imports and without parallel arrays.
Internally everything thinks in (row, column), where row 0 is rank 8 (Black's back rank) and column 0 is file "a". Square names like "e4" appear only at the edges.
🟩 WHAT TRUSTS WHAT
The exports look independent, but they lean on each other in ways worth knowing before you build on them:
`applyMove()` trusts its move and changes the position in place. It doesn't re-check legality, so feed it moves from `generateLegalMoves()` - or from `matchLegalMove()`, which picks the move matching typed coordinates out of that list and brings the filled-in castling and en-passant details with it. A move object you build by hand would miss those.
To ask "what if?" without committing, `copyPosition()` first and apply the move to the copy. The generator's own self-check filter runs on such scratch boards, and so does the whole ChessAI look-ahead.
`gameStatusOf()` spots mate, stalemate and the automatic draws, but not threefold repetition, which needs history this library deliberately doesn't keep. Push each new `positionKey()` onto your own array, then ask `isThreefoldRepetition()`. Push first, then ask.
The position caches each king's square so check tests don't scan the board, and `applyMove()` maintains that cache. If you build a custom position by writing to the board matrix yourself, set the king fields to match, or every check test will look at the wrong square.
See the Chess script for the whole thing playing human vs computer: Library

PessimisticSimLibrary "PessimisticSim"
Broker-agnostic pessimistic fill simulator. Runs a shadow account
alongside any indicator or strategy, filling every signal at the
worst plausible price (half-spread + slippage + a fraction of the
adverse bar excursion) so you can see whether an edge survives
real-world friction.
Instrument-agnostic: set pointValue for futures, pick a commission
model, pick a sizing model, pick a fill model. Defaults reproduce
spot crypto / stock behaviour (multiplier 1, percent commission,
risk-based sizing, next-bar-open fills).
newState(cfg)
Creates a fresh shadow account seeded from `cfg`.
Parameters:
cfg (SimConfig) : Configuration object.
Returns: A SimState ready to pass to step().
commissionFor(cfg, price, qty)
Commission for one fill under the configured model.
Parameters:
cfg (SimConfig) : Configuration object.
price (float) : Fill price.
qty (float) : Units filled.
Returns: Commission in account currency. Zero when qty <= 0.
qtyFor(cfg, equity, stopDist, price, openRisk)
Position size under the configured sizing model, with an optional
leverage cap and quantity-step rounding. Host scripts should call
this for their live orders too, so both engines size identically.
Parameters:
cfg (SimConfig) : Configuration object.
equity (float) : Account equity to size against.
stopDist (float) : Distance from entry to stop, in PRICE units. Only used by
SizeMode.riskStop; pass 0 in the other modes.
price (float) : Fill price, used by the leverage cap and equityPct sizing.
openRisk (float) : Risk already committed by open positions, in CURRENCY
(i.e. qty * stopDist * pointValue). riskStop only.
Returns: Units to trade, rounded down to qtyStep. Zero when unsizable.
buyFillPrice(cfg, refPrice, advHigh)
Worst-case buy fill: reference price + half-spread + slippage +
a slice of the adverse upward excursion.
Parameters:
cfg (SimConfig) : Configuration object.
refPrice (float) : Reference price (bar open, or close under signalClose).
advHigh (float) : Adverse extreme to price against. Pass the bar high under
nextOpen; pass refPrice under signalClose to disable it.
Returns: The pessimistic buy price.
sellFillPrice(cfg, refPrice, advLow)
Worst-case sell fill: reference price - half-spread - slippage -
a slice of the adverse downward excursion.
Parameters:
cfg (SimConfig) : Configuration object.
refPrice (float) : Reference price (bar open, or close under signalClose).
advLow (float) : Adverse extreme to price against. Pass the bar low under
nextOpen; pass refPrice under signalClose to disable it.
Returns: The pessimistic sell price.
method closeAt(s, cfg, exitPrice)
Flattens the position at `exitPrice`, books PnL and updates stats.
No-op when flat.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
exitPrice (float) : Fill price for the exit.
Returns: Void.
method openAt(s, cfg, dir, fillPrice, stopDist)
Opens a position, or adds a unit while `units < cfg.maxUnits`.
Add-ons blend into a volume-weighted average entry and are sized
against the risk already committed.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
dir (int) : 1 to go long, -1 to go short.
fillPrice (float) : Pessimistic fill price.
stopDist (float) : Distance from entry to stop, in price units. Pass 0 under
fixedUnits / equityPct sizing.
Returns: Void.
method mark(s, cfg, price)
Marks the account to market and updates equity peak and drawdown.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
price (float) : Current mark price, normally close.
Returns: Void.
method stepAt(s, cfg, longIn, longOut, shortIn, shortOut, buyPrice, sellPrice, markPrice, stopDistLong, stopDistShort)
General escape hatch: processes one bar against explicit fill prices.
Use when your execution model is neither FillMode case — limit fills,
stop fills, VWAP, session opens, anything.
Order is exits, then reversals, then entries, then mark-to-market.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
longIn (bool) : Long entry signal.
longOut (bool) : Long exit signal.
shortIn (bool) : Short entry signal.
shortOut (bool) : Short exit signal.
buyPrice (float) : Price paid when buying.
sellPrice (float) : Price received when selling.
markPrice (float) : Price for the mark-to-market update.
stopDistLong (float) : Stop distance for longs, price units.
stopDistShort (float) : Stop distance for shorts, price units.
Returns: Void.
method step(s, cfg, longIn, longOut, shortIn, shortOut, o, h, l, c, stopDistLong, stopDistShort)
Processes one bar using the configured FillMode. Call once per
confirmed bar.
FillMode.nextOpen — pass PRIOR-bar signals (sig ); this bar's
open is the fill, its high/low the excursion.
FillMode.signalClose — pass CURRENT-bar signals; the close is the
fill and advFrac is inert.
Getting this pairing wrong produces plausible-but-wrong results, so
check it first when a comparison looks strange.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
longIn (bool) : Long entry signal, shifted per FillMode.
longOut (bool) : Long exit signal, shifted per FillMode.
shortIn (bool) : Short entry signal, shifted per FillMode.
shortOut (bool) : Short exit signal, shifted per FillMode.
o (float) : Bar open.
h (float) : Bar high.
l (float) : Bar low.
c (float) : Bar close.
stopDistLong (float) : Stop distance for longs, price units.
stopDistShort (float) : Stop distance for shorts, price units.
Returns: Void.
pf(gp, gl)
Profit factor with safe handling of an empty loss column.
Parameters:
gp (float) : Gross profit.
gl (float) : Gross loss, as a positive number.
Returns: gp/gl, 999 when there are no losses, 0 when there is nothing.
method netProfit(s, cfg)
Net profit of the shadow account, in currency.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
Returns: equity - initCap.
method profitFactor(s)
Profit factor of the shadow account.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
Returns: Profit factor.
method winRatePct(s)
Win rate of the shadow account, percent.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
Returns: Percentage of closed trades that were profitable.
method avgTradePct(s)
Average per-trade return, percent of equity-before-trade.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
Returns: Mean trade return, percent.
method rtCostPct(cfg)
Round-trip friction as a percent of notional. Only meaningful under
CommMode.pct — flat commissions do not scale with notional, so this
returns na under the other models. Compare against avgTradePct():
if the average trade does not clear this, the edge is smaller than
the cost of trading it.
Namespace types: SimConfig
Parameters:
cfg (SimConfig) : Configuration object.
Returns: Round-trip cost, percent, or na under flat commission models.
rowLabels()
Row labels matching the order of rowValues(). Lay out an audit table
in the host script from these, so strategy.* calls stay in the host.
Returns: Array of ten label strings.
method rowValues(s, cfg)
Preformatted metric strings for the shadow account, aligned to rowLabels().
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
Returns: Array of ten value strings.
method verdict(s, cfg, strategyPF, strategyNet)
Compares a host strategy's headline numbers against the shadow
account and returns a verdict string.
Namespace types: SimState
Parameters:
s (SimState) : Shadow account state.
cfg (SimConfig) : Configuration object.
strategyPF (float) : Host strategy profit factor.
strategyNet (float) : Host strategy net profit.
Returns: "DIVERGED — investigate", "SURVIVES", or "NO EDGE".
SimConfig
Instrument, cost, sizing and execution assumptions for the shadow account.
Fields:
spreadPct (series float) : Assumed FULL spread, percent. Half is charged per side.
slipPct (series float) : Extra slippage percent per side.
advFrac (series float) : Fraction of the fill bar's adverse excursion added to the fill.
commMode (series CommMode) : Commission model.
commPct (series float) : Commission percent of notional, per side.
commPerUnit (series float) : Flat commission per contract or share, per side.
commMin (series float) : Minimum commission per fill. Applied only when qty > 0.
pointValue (series float) : Currency value of one full point of price movement, per unit.
qtyStep (series float) : Rounds size DOWN to this increment. 0 = no rounding.
initCap (series float) : Starting equity of the shadow account.
sizeMode (series SizeMode) : Position sizing model.
riskPct (series float) : Risk per trade, percent of equity. SizeMode.riskStop only.
maxTotalPct (series float) : Ceiling on total open risk, percent of equity. riskStop only.
fixedUnits (series float) : Units per entry. SizeMode.fixedUnits only.
equityPct (series float) : Notional as percent of equity. SizeMode.equityPct only.
useLevCap (series bool) : Apply the leverage cap on top of the chosen sizing model.
maxLeverage (series float) : Max notional / equity.
maxUnits (series int) : Max entries per position. MUST equal the host strategy's
fillMode (series FillMode) : Execution assumption. Determines which signals step() wants.
SimState
Mutable state of the shadow account. Create with newState().
Fields:
equity (series float) : Realised equity, commissions already deducted.
dir (series int) : 1 long, -1 short, 0 flat.
entry (series float) : Volume-weighted average entry price.
qty (series float) : Total units held.
units (series int) : Number of fills making up the current position.
trades (series int) : Closed trades.
wins (series int) : Closed trades with net > 0.
grossP (series float) : Sum of winning net PnL.
grossL (series float) : Sum of absolute losing net PnL.
commPaid (series float) : Total commission paid, both sides.
peak (series float) : Mark-to-market equity high water mark.
maxDD (series float) : Worst mark-to-market drawdown, as a negative fraction.
consecL (series int) : Current consecutive-loss run.
maxConsL (series int) : Longest consecutive-loss run.
sumTrPct (series float) : Sum of per-trade returns, percent of equity-before-trade.
skipped (series int) : Entry signals dropped because sizing returned zero units. Library

KC Institutional Core LibraryKC Institutional Core Library v1.0
KCInstitutionalCore is a reusable Pine Script v6 utility library created to support structured technical-analysis workflows without duplicating common helper logic across multiple indicators and strategies.
The library provides transparent and independently reusable functions for:
Score normalization and trade-quality grading
Premium, Discount and Equilibrium classification
Risk-to-reward calculation
Risk-based position-size estimation
Timeframe-aware trading-style classification
Adaptive higher-timeframe selection
Directional alignment analysis
Execution-blocker identification
The exported functions are deterministic utilities. They do not generate guaranteed trading signals, predict future price movement or execute trades.
Basic import example
import Kelly_Carter12/KCInstitutionalCore/1 as kc
string grade = kc.scoreToGrade(78)
string style = kc.tradeStyle(timeframe.in_seconds())
= kc.rangeLocation(close, ta.highest(high, 50), ta.lowest(low, 50))
The detailed function documentation below explains every exported function, parameter and return value.
Library "KCInstitutionalCore"
Reusable Pine Script v6 utilities for timeframe context, score grading, premium/discount classification, alignment, risk-to-reward and position-size calculations. Designed as a transparent helper library for indicators and strategies.
clamp(value, minimum, maximum)
Restricts a numeric value to the supplied minimum and maximum boundaries.
Parameters:
value (float) : Value to restrict.
minimum (float) : Lower boundary.
maximum (float) : Upper boundary.
Returns: The restricted value.
scoreToGrade(score)
Converts a numeric score into a concise quality grade.
Parameters:
score (float) : Score expressed on a 0–100 scale.
Returns: A grade string from AA to D.
normalizeScore(rawScore, maximumScore)
Normalizes a raw score to a 0–100 scale.
Parameters:
rawScore (float) : Current raw score.
maximumScore (float) : Maximum possible raw score.
Returns: Normalized score from 0 to 100, or na when maximumScore is not positive.
rangeLocation(price, rangeHigh, rangeLow)
Classifies the current price inside a supplied dealing range.
Parameters:
price (float) : Current or evaluated price.
rangeHigh (float) : Upper boundary of the range.
rangeLow (float) : Lower boundary of the range.
Returns: A tuple containing PREMIUM, DISCOUNT, or EQUILIBRIUM and the 0–100 range percentage.
riskReward(entry, stop, target)
Calculates reward-to-risk from entry, stop and target prices.
Parameters:
entry (float) : Entry price.
stop (float) : Stop-loss price.
target (float) : Target price.
Returns: Absolute reward-to-risk ratio, or na when the stop distance is zero.
positionSize(accountSize, riskPercent, entry, stop, pointValue)
Estimates position size from account risk and stop distance.
Parameters:
accountSize (float) : Account balance or planning capital.
riskPercent (float) : Percentage of account risked.
entry (float) : Entry price.
stop (float) : Stop-loss price.
pointValue (float) : Monetary value per price point for one unit.
Returns: Estimated units or lots according to the supplied pointValue, or na for invalid inputs.
tradeStyle(chartSeconds)
Maps chart duration in seconds to a general planning style.
Parameters:
chartSeconds (float) : Chart timeframe duration in seconds, normally supplied with timeframe.in_seconds().
Returns: SCALP, INTRADAY, SWING, or POSITION.
adaptiveTimeframes(chartSeconds)
Suggests two broader context timeframes from the chart duration.
Parameters:
chartSeconds (float) : Chart timeframe duration in seconds, normally supplied with timeframe.in_seconds().
Returns: A tuple containing primary and secondary context timeframe strings.
alignmentState(localBias, htfBias, mtfBias)
Summarizes local, higher-timeframe and multi-timeframe directional agreement.
Parameters:
localBias (int) : Local direction: 1 bullish, -1 bearish, 0 neutral.
htfBias (int) : Higher-timeframe direction: 1 bullish, -1 bearish, 0 neutral.
mtfBias (int) : Broader alignment direction: 1 bullish, -1 bearish, 0 neutral.
Returns: BULL ALIGNED, BEAR ALIGNED, PARTIAL, CONFLICT, or NEUTRAL.
executionBlocker(direction, htfBias, mtfBias, location, structureConfirmed, liquidityConfirmed, newsBlocked)
Returns the first material execution blocker in a transparent priority order.
Parameters:
direction (int) : Intended direction: 1 long, -1 short, 0 neutral.
htfBias (int) : Higher-timeframe direction: 1 bullish, -1 bearish, 0 neutral.
mtfBias (int) : Multi-timeframe direction: 1 bullish, -1 bearish, 0 neutral.
location (string) : PREMIUM, DISCOUNT, or EQUILIBRIUM.
structureConfirmed (bool) : True when the required structure event is confirmed.
liquidityConfirmed (bool) : True when the required liquidity event is confirmed.
newsBlocked (bool) : True when a manual news blackout is active.
Returns: A concise blocker description, or CLEAR when no listed blocker is active. Library

Trade Wzrd - Library Alert String UtilsTrade Wzrd - Library Alert String Utils
WHAT IT IS
Open-source Pine library that builds comma-separated webhook alert strings for automated order commands. Import name: TradeWzrdAlerts.
This is an educational protocol helper for strategy and indicator authors. It is not a signal service and does not place broker orders by itself.
WHY IT EXISTS (ORIGINALITY)
Most automation scripts hand-concatenate alert text. That causes dialect drift, missing parameters, and broken multi-command messages. This library is a single export surface for the full command set used with webhook-style automation:
Market: BUY, SELL
Pending: BUYLIMIT, SELLLIMIT, BUYSTOP, SELLSTOP
Futures-style: BRACKET, REMOVE_SL, REMOVE_TP
Manage: MODIFY, BREAKEVEN
Close: CLOSE, CLOSEALL, LAYER_CLOSE
Cancel: CANCEL
It also provides zero-config PRICE helpers so you can pass exact strategy stop and take-profit prices (no manual pip math), plus a multi() joiner for semicolon-separated command chains.
HOW IT WORKS
1) Each command function returns one string: COMMAND,SYMBOL
2) Optional parameters are omitted when unset (na or empty string). Legitimate zero values such as OFFSET=0 are still emitted when you pass them.
3) COMMENT text is sanitized so commas and semicolons cannot break multi-command grammar.
4) Invalid required fields (empty symbol, pending without PRICE, MODIFY with neither SL nor TP) return an empty string. Callers should not fire alerts on empty strings.
5) Zero-config helpers (buyPrice, sellPrice, bracketPrice, modifySlPrice, breakEvenPrice, closePercent) force TPSLTYPE=PRICE and format prices with mintick precision.
HOW TO USE
1) Publish or open this library, then import it in your script (replace username and version as shown on the library page):
import USERNAME/TradeWzrdAlerts/1 as TW
2) Build a message, for example:
msg = TW.buy("EURUSD", vol=0.01, sl=100, tp=200, tpslType="PIPS")
3) Pass msg into strategy.entry / strategy.exit alert_message, or call alert(msg) when length(msg) > 0
4) Create a PulseWire alert with message:
{{strategy.order.alert_message}}
or use Any alert() function call when using alert()
5) Point the alert webhook field at whatever endpoint you already use
DEFAULTS AND RULES
- Symbol is pass-through (not force-uppercased)
- Ticket is an optional string parameter
- TPSLTYPE is only written when you provide it (except zero-config PRICE helpers)
- multi(a,b,...) joins non-empty segments with semicolons
LIMITATIONS
- Library only builds text. Execution quality depends on your webhook receiver and broker
- Pending-order automation support depends on your backend and platform
- Past results and example strings do not predict live performance
- Not intended as financial advice
No external links are required to understand or use this library.
Library
