ml_weights is a dependency-free library for Pine v6 for the one thing most confluence engines never do: change their factor weights. A typical composite sums five or ten factors with hand-set weights that stay fixed forever, whether or not each factor actually predicts anything on your instrument. This library lets those weights learn from the forward test — and, just as importantly, gives you the guardrails to keep the learning honest.

The progression

It follows the standard escalation, each piece usable on its own:

rankWeight — a static, normalized weight from an importance rank (a Best-Worst-Method-style floor). The hand-set baseline the learner starts from.
reliability — an online EMA of “when this factor spoke, did the outcome agree.” The simplest learned weight: a live hit rate.
adamWeight — a single factor’s weight learned by the Adam optimizer, stepped on each resolved forward-test outcome.
blend — mix a learned weight with the static base by a capped fraction, so an unlucky stretch can’t dominate. The anti-overfit control.
normalize / dot — turn a weight set into a bounded weighted composite.
The functions
rankWeight(rank, n) — inverse-rank weight (1 = most important) among n factors, normalized so the set sums to 1.
reliability(resolve, agreed, alpha, floorW) — trust score in [floorW, 1]. Call every bar; set resolve = true on the bar a forward outcome resolves, with agreed = (the factor’s direction matched the realized move). alpha ≈ 2/(N+1) sets the memory. A factor that keeps being right drifts toward 1; one that’s coin-flip sits near 0.5.
adamWeight(resolve, scoreAtSignal, win, lr, cap, w0) — the factor’s weight learned by Adam, bounded to [0, cap]. On each resolved outcome the gradient is g = (win ? +1 : −1) · scoreAtSignal (the factor’s score on the signal bar); Adam adapts the step size from the running gradient moments. Deterministic and repaint-free. w0 is the starting weight.
blend(base, learned, frac) — (1−frac)·base + frac·learned. Keep frac modest (0.3–0.5) so the learned component is a nudge, not a takeover.
normalize(w) — normalize a weight array to sum to 1 (negatives floored at 0; all-equal if the sum is 0).
dot(scores, weights) — the weighted composite Σ scoreᵢ·weightᵢ. Pass a normalized weight array for a bounded result.
How to use

See also  MSS Sweeps | Trading Indicator

Weight three factors by their learned reliability, blended onto a rank floor:

//version=6
indicator(“Example — adaptive confluence”, overlay = false)
import Market_Logic_India/ml_weights/1 as wt

// your three factor scores in [-1,+1] and their directional agreement at resolution …
f1 = ta.rsi(close,14)/50 – 1, f2 = ta.cci(close,20)/200, f3 = math.sign(ta.change(close,5))

// forward-test resolution (host-side): set resolve=true when an outcome resolves, and each
// factor’s `agreed` = did it point the right way. Here shown schematically:
resolve = barstate.isconfirmed
r1 = wt.reliability(resolve, math.sign(f1[10]) == math.sign(close-close[10]), 0.05, 0.1)
r2 = wt.reliability(resolve, math.sign(f2[10]) == math.sign(close-close[10]), 0.05, 0.1)
r3 = wt.reliability(resolve, math.sign(f3[10]) == math.sign(close-close[10]), 0.05, 0.1)

// blend each learned weight onto a Best-Worst rank floor, normalize, and combine
w = array.from(wt.blend(wt.rankWeight(1,3), r1, 0.4),
wt.blend(wt.rankWeight(2,3), r2, 0.4),
wt.blend(wt.rankWeight(3,3), r3, 0.4))
wn = wt.normalize(w)
composite = wt.dot(array.from(f1, f2, f3), wn)
plot(composite, “Adaptive composite”)
Notes
Non-repainting: weights advance only on the bars you mark resolve, which you should drive from a forward-test resolution on barstate.isconfirmed. No ta.* inside, so nothing short-circuits; each call keeps its own state, so give every factor its own call site.
Anti-overfit is your job too: keep the blend fraction modest, cap adamWeight, and always render the live forward-test edge next to the weighted vote so a learned weight is never trusted blindly.
Types: simple for the ranks, learning rate, cap and blend fraction; series for the scores and resolution flags; array for normalize / dot.
Gradient-boosting is intentionally omitted — it doesn’t fit Pine’s execution model; the Adam + reliability path covers the useful, transparent middle.
Concept credits

The Best-Worst-Method for deriving weights from importance ranks is Jafar Rezaei’s. The Adam optimizer is Kingma & Ba (2015). Reliability / inverse-variance weighting and forward-testing follow standard quantitative practice. This library is an original, dependency-free Pine v6 packaging of those public techniques; it is not affiliated with, nor endorsed by, any originator.

See also  Line Break | Trading Indicator

License

Mozilla Public License 2.0 — as required for TradingView libraries (open source). Free to import and build on.

Library “ml_weights”

rankWeight(rank, n)
  Parameters:
    rank (simple int)
    n (simple int)

reliability(resolve, agreed, alpha, floorW)
  Parameters:
    resolve (bool)
    agreed (bool)
    alpha (simple float)
    floorW (simple float)

adamWeight(resolve, scoreAtSignal, win, lr, cap, w0)
  Parameters:
    resolve (bool)
    scoreAtSignal (float)
    win (bool)
    lr (simple float)
    cap (simple float)
    w0 (simple float)

blend(base, learned, frac)
  Parameters:
    base (simple float)
    learned (float)
    frac (simple float)

normalize(w)
  Parameters:
    w (array)

dot(scores, weights)
  Parameters:
    scores (array)
    weights (array)


Source link

Author

Shin John
Shin JohnYtv Market News
Share-market news writer and analyst with deep experience covering equities, commodities, forex, and cryptocurrencies for readers in the USA, UK, Canada, and Australia. Ytv Market News delivers timely market updates, practical trading insights, and clear explanations of macro and company-level catalysts that move prices. Combines on-the-ground financial reporting with technical analysis, using concise charts and actionable ideas to help investors and traders make smarter decisions.
Latest entries
See also  Coil Breaker | RSI Range Compression