Skip to content

Squeeze Momentum

by MeMyselfAndI · 0 in use · published 3 months ago

Loading Squeeze Momentum on BTC-USDT 1h…

Source

sha256 d400ee65e73f1e6d

1// Squeeze Momentum Indicator [LazyBear] — VP Script port.
2// Original © LazyBear. This port keeps the original calculation while using
3// only the public API documented at https://view.lancedb.dev/docs/script/llms.
4
5indicator('Squeeze Momentum Indicator [LazyBear] — VP', {
6 shortTitle: 'SQZMOM_LB — VP',
7 pane: 'separate',
8})
9
10const length = input.int('BB Length', 20, { min: 1, max: 500 })
11const bbMult = input.float('BB MultFactor', 2, { min: 0.1, max: 20 })
12const lengthKC = input.int('KC Length', 20, { min: 1, max: 500 })
13const multKC = input.float('KC MultFactor', 1.5, { min: 0.1, max: 20 })
14const useTrueRange = input.bool('Use True Range (KC)', true)
15const source = input.source('Source', 'close')
16
17// Bollinger Bands. The Pine sample accidentally used multKC here; bbMult is
18// intentional so the "BB MultFactor" input actually controls the BB width.
19const basis = ta.sma(source, length)
20const dev = math.mul(ta.stdev(source, length), bbMult)
21const upperBB = math.add(basis, dev)
22const lowerBB = math.sub(basis, dev)
23
24// Keltner Channels.
25const ma = ta.sma(source, lengthKC)
26const candleRange = math.sub(high, low)
27const range = useTrueRange ? ta.tr() : candleRange
28const rangeMa = ta.sma(range, lengthKC)
29const rangeDev = math.mul(rangeMa, multKC)
30const upperKC = math.add(ma, rangeDev)
31const lowerKC = math.sub(ma, rangeDev)
32
33const highestHigh = ta.highest(high, lengthKC)
34const lowestLow = ta.lowest(low, lengthKC)
35const rangeMid = math.mul(math.add(highestHigh, lowestLow), 0.5)
36const closeMean = ta.sma(close, lengthKC)
37const anchor = math.mul(math.add(rangeMid, closeMean), 0.5)
38const value = ta.linreg(math.sub(source, anchor), lengthKC, 0)
39const previous = math.shift(value, 1)
40
41const histogramColors = new Array(barCount).fill(null)
42const squeezeColors = new Array(barCount).fill(null)
43const zero = new Array(barCount).fill(null)
44
45for (let i = 0; i < barCount; i++) {
46 const v = value[i]
47 const p = previous[i]
48 if (v !== null) {
49 if (v > 0) {
50 histogramColors[i] = p !== null && v > p ? '#00ff00' : '#008000'
51 } else {
52 histogramColors[i] = p !== null && v < p ? '#ff0000' : '#800000'
53 }
54 }
55
56 const bbU = upperBB[i]
57 const bbL = lowerBB[i]
58 const kcU = upperKC[i]
59 const kcL = lowerKC[i]
60 if (bbU === null || bbL === null || kcU === null || kcL === null) continue
61
62 const sqzOn = bbL > kcL && bbU < kcU
63 const sqzOff = bbL < kcL && bbU > kcU
64 zero[i] = 0
65 squeezeColors[i] = sqzOn ? '#000000' : sqzOff ? '#808080' : '#0000ff'
66}
67
68plot(value, { title: 'Momentum', color: histogramColors, width: 4, style: 'histogram' })
69plot(zero, { title: 'Squeeze status', color: squeezeColors, width: 3, style: 'circles' })
70
71alertcondition(ta.crossover(value, 0), {
72 title: 'Momentum crossed above zero',
73 message: 'Squeeze Momentum crossed above zero.',
74})
75alertcondition(ta.crossunder(value, 0), {
76 title: 'Momentum crossed below zero',
77 message: 'Squeeze Momentum crossed below zero.',
78})
79

Versions

  • v1currentd400ee653 months ago

This indicator runs in an isolated sandbox: it cannot reach your account, your data or the network, and if it stops responding it is stopped for you. That does not make it correct — nobody has checked whether it is any good, which is why its source is above.