Squeeze Momentum Indicator는 트레이딩뷰 오픈 소스로 ‘LazyBear‘라는 유저가 공개하였습니다.
[유저 설명 번역]
이것은 John Carter의 “TTM Squeeze” 변동성 지표의 파생 버전으로, 그의 저서 “Mastering the Trade” (11장)에서 설명된 내용을 바탕으로 한 것입니다.
중앙선에 검정색 크로스가 나타나면 시장이 방금 스퀴즈에 들어갔다는 것을 의미합니다 (볼린저 밴드가 켈트너 채널 내에 있을 때). 이는 변동성이 낮고 시장이 폭발적인 움직임(상승 또는 하락)을 준비하고 있다는 신호입니다. 회색 크로스는 “Squeeze release”를 의미합니다.
Carter는 검정색 크로스 후 첫 번째 회색 크로스가 나타날 때까지 기다린 후, 모멘텀의 방향으로 포지션을 취하라고 제안합니다. 예를 들어, 모멘텀 값이 0 이상이면 롱 포지션을 취하는 방식입니다. 포지션은 모멘텀이 변화할 때 (색상 변화로 표시됨) 종료합니다. 제 경험상 좋은 진입 포인트를 놓치지 않기 위해 ADX나 WaveTrend와 같은 추가적인 지표가 필요하다는 것을 알게 되었습니다. 또한 Carter는 단순한 모멘텀 지표를 사용한 반면, 저는 다른 방식(선형 회귀 기반)을 사용하여 히스토그램을 표시했습니다.
트레이딩뷰: https://kr.tradingview.com/v/nqQ1DT5a/
트레이딩뷰 커뮤니티 1등 지표🚀
Squeeze Momentum Indicator는 커뮤니티 TOP 1위의 지표입니다.

Squeeze Momentum Indicator 구현
1️⃣ 저는 편의상 스퀴즈 조건을 on / off로 표시하겠습니다.

2️⃣ 추가로 히스토그램의 값을 구하고 히스토그램의 색상도 강도에 따라서 GREEN / g / RED / r 로 구분하겠습니다.
💡트레이딩뷰 차트 설정에 아래 변수가 2로 설정되어 있지만 코드 확인 결과 미사용 중인 변수로 구현에서도 생략하겠습니다.

CODE
pip install pandas ccxt pinetopy numpy
import pandas as pd
import ccxt
import pinetopy as pp # 0.0.6 버전 이상
import numpy as np
# 예시) 비트코인 선물 BTCUSDT, 1시간 봉
bnb = ccxt.binance({'options': { 'defaultType': 'future' }})
ohlcv = bnb.fetch_ohlcv(symbol="BTC/USDT", timeframe="1h", limit=500)
df = pd.DataFrame(ohlcv, columns=['time', 'open', 'high', 'low', 'close', 'volume'])
df['time'] = pp.kst(df['time'])
def main(df, bb_len=20, kc_len=20, mult=1.5):
_df = df.copy()
# Calculate BB
_df[['basis','upperBB','lowerBB']] = pp.bband(df=df, length=bb_len, factor=mult)
# Calculate KC
ma = pp.sma(df=df['close'], length=kc_len)
range = np.maximum(
_df['high'] - _df['low'],
np.abs(_df['high'] - _df['close'].shift(1)),
np.abs(_df['low'] - _df['close'].shift(1))
)
rangema = pp.sma(range, length=kc_len)
_df['upperKC'] = ma + rangema * mult
_df['lowerKC'] = ma - rangema * mult
sqzOn = (_df['lowerBB'] > _df['lowerKC']) & (_df['upperBB'] < _df['upperKC'])
sqzOff = (_df['lowerBB'] < _df['lowerKC']) & (_df['upperBB'] > _df['upperKC'])
noSqz = ~(sqzOn | sqzOff)
highest_val = df['high'].rolling(window=kc_len).max()
lowest_val = df['low'].rolling(window=kc_len).min()
avg_high_low = (highest_val + lowest_val) / 2
sma_val = df['close'].rolling(window=kc_len).mean()
final_avg = (avg_high_low + sma_val) / 2
val = pp.linreg(df['close'] - final_avg, kc_len, offset=0)
bcolor = np.where(val > 0,
np.where(val > val.shift(1), 'GREEN', 'g'),
np.where(val < val.shift(1), 'RED', 'r')
)
dot = np.where(noSqz, '', np.where(sqzOn, 'off', 'on'))
df['histo'], df['histo_color'], df['dot'] = val, bcolor, dot
return df
print(main(df, bb_len=20, kc_len=20, mult=1.5)) # 트레이딩뷰 디폴트 값
Check



✅ 히스토그램 값
✅ 히스토그램 색상
✅ 스퀴즈 진입 여부