볼린저 밴드는 존 볼린저(John Bollinger)라는 사람이 만든 대표적인 변동성 지표의 하나다. 볼린저 밴드를 설명할 때 유사한 엔벨롭을 빼놓을 수가 없는데, 엔벨롭의 단점 중 하나가 단순히 이동 평균 가격에 10%씩을 더하고 빼서 밴드를 형성하는데, 이게 가격 변동이 큰 종목의 경우 너무 잦고, 가격 변동이 작은 종목에 대해서는 매수, 매도 신호를 포착하기 어렵다는 것이다. 따라서 사용자가 종목에 따라, 혹은 시장 상황에 따라 임의로 밴드 폭을 조정하여 사용했는데 존 볼린저가 종목과 시장 상황에 상관없이 변동성을 반영할 수 있게 만든 것이 바로 이 볼린저 밴드이다. 볼린저 밴드는 기존 엔벨롭과 같은 단순히 백분율로 밴드를 구성하는 방식의 단점을 해소해 주었기에 당시 선풍적인 인기를 끌었었다. 참고로 당시는 기본적 분석보다 기술적 분석이 시장에서 더 많이 사용되던 시기이며, 기술적 분석의 역사는 기본적 분석의 그것보다 훨씬 길다.(일반적으로 기본적 분석의 기초가 되는 가치평가이론의 시작을 20세기 이후 벤저민 그레이엄으로 보고, 기술적 분석은 18세기 혼마 무네히사의 차트 작도법과 사케다 전법을 시작으로 본다.)
볼린저 밴드는 이동평균을 기준으로 삼고 통상 기간내 가격변동의 표준편차에 2배수를 해서 밴드 상단과 하단으로 사용한다. 때문에 가격변동이 심한 때에는 밴드폭이 벌어지고, 가격 변동이 없을 경우에는 밴드폭이 줄어든다. 가격의 절댓값에 따라 밴드가 넓어지고 줄어드는 엔벨롭 지표와 다른 점. 볼린저 밴드 역시 이동평균선의 종류를 변경해서 사용하거나, 길이, 표준편차 배수 등을 조정하여 적용하는 경우가 많다.
주가의 움직임이 정규분포를 따를 경우 표준편차의 상하단 두배수면 95%의 확률로 밴드 안에 들어오게 될 것이다. 이를 전제로 한 가장 기본적인 매매법과 전략은 밴드 상하단에 다다르면 매수와 매도를 하는 것.
하지만 역시 단점이 있는데, 가격매매가 주효한 박스권 장세에서는 기가 막히게 매수, 매도 시점을 잡아내나, 변동성이 없어서 밴드를 한껏 좁혀놓고 급등과 급락을 할 때는 손실을 내기 딱 좋다. 이런 문제들 때문에 적당히 변동성이 있는 종목을 선택해 매매하거나, 추세를 감안해 매수, 매도를 조절한다. 추세를 감안해 볼린저 밴드를 개선한 사례는 이전 포스팅을 참조하면 좋다.
2024.03.30 - [주가 예측 모델/관련 package] - TradingView 트레이딩뷰로 매매 전략 만들고 백테스팅 하기 : 볼린저 밴드 단점 보완
마지막으로 트레이딩 뷰 파인 스크립트 소스와 pandas-ta 소스를 공유하여 마친다.
- 볼린저 밴드 (Bollinger Bands) 트레이딩 뷰 파인 스크립트 지표 소스
//@version=5
indicator(shorttitle="BB", title="Bollinger Bands", overlay=true, timeframe="", timeframe_gaps=true)
import TradingView/ta/7 as ta7
len = input.int(20, minval=1)
src = input(close, title="Source")
mult = input.float(2.0, minval=0.001, maxval=50, title="StdDev")
maType = input.string("SMA", "MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA"])
ma(source, length, _type) =>
switch _type
"SMA" => ta.sma(source, length)
"EMA" => ta.ema(source, length)
"DEMA" => ta7.dema(source,length)
"TEMA" => ta7.tema(source,length)
"FRAMA" => ta7.frama(source,length)
"T3" => ta7.t3(source,length)
"TRIMA" => ta7.trima(source,length)
"RMA" => ta.rma(source, length)
"WMA" => ta.wma(source, length)
"HMA" => ta.hma(source, length)
"VWMA" => ta.vwma(source, length)
basis = ma(src, len, maType)
dev = mult * ta.stdev(src, len)
upper = basis + dev
lower = basis - dev
offset = input.int(0, "Offset", minval = -500, maxval = 500, display = display.data_window)
plot(basis, "Basis", color=#FF6D00, offset = offset)
p1 = plot(upper, "Upper", color=#2962FF, offset = offset)
p2 = plot(lower, "Lower", color=#2962FF, offset = offset)
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))
- 볼린저 밴드 (Bollinger Bands) 트레이딩 뷰 파인 스크립트 전략 소스
//@version=5
strategy(shorttitle="BB", title="Bollinger Bands", overlay=true, margin_long=100, margin_short=100, default_qty_type=strategy.percent_of_equity, default_qty_value=50, commission_type=strategy.commission.percent, commission_value=0.2, pyramiding=0)
import TradingView/ta/7 as ta7
len = input.int(20, minval=1)
src = input(close, title="Source")
mult = input.float(2.0, minval=0.001, maxval=50, title="StdDev")
maType = input.string("SMA", "MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA"])
ma(source, length, _type) =>
switch _type
"SMA" => ta.sma(source, length)
"EMA" => ta.ema(source, length)
"DEMA" => ta7.dema(source,length)
"TEMA" => ta7.tema(source,length)
"FRAMA" => ta7.frama(source,length)
"T3" => ta7.t3(source,length)
"TRIMA" => ta7.trima(source,length)
"RMA" => ta.rma(source, length)
"WMA" => ta.wma(source, length)
"HMA" => ta.hma(source, length)
"VWMA" => ta.vwma(source, length)
basis = ma(src, len, maType)
dev = mult * ta.stdev(src, len)
upper = basis + dev
lower = basis - dev
offset = input.int(0, "Offset", minval = -500, maxval = 500, display = display.data_window)
plot(basis, "Basis", color=#FF6D00, offset = offset)
p1 = plot(upper, "Upper", color=#2962FF, offset = offset)
p2 = plot(lower, "Lower", color=#2962FF, offset = offset)
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))
startDate = input.time(defval=timestamp("01 Jan 1970 00:00 +0000"), group = "Test Range")
finishDate = input.time(defval=timestamp("31 Dec 2025 24:00 +0000"), group = "Test Range")
time_condition = time >= startDate and time <= finishDate
if(time_condition)
if ta.crossover(src, lower)
strategy.entry("매수", strategy.long, stop=lower, oca_type=strategy.oca.cancel, comment="매수")
if ta.crossunder(src, upper)
strategy.close_all('매도')
bgcolor(strategy.position_size > 0 ? color.new(color.yellow,90) : na)
- 볼린저 밴드 (Bollinger Bands) pandas-ta 소스
import pandas as pd
import pandas_ta as ta
import FinanceDataReader as fdr
data = fdr.DataReader('005930')
bbands = ta.bbands(data['Close'], length=20, std=2, mamode='SMA')
data = pd.concat([data, bbands], axis=1)
data.dropna(inplace=True)
추가로 오늘의 주인공 존 볼린저가 쓴 볼린저 밴드 책을 소개한다.
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."