SMI 에르고딕 (SMI Ergodic)는 SMI (Stochastics Momentum Index, 스토캐스틱 모멘텀 지수)와 TSI (rue Strength Index, 트루 스트랭스 인덱스)가 결합된 지표이다. 스토캐스틱을 계산할 때 종가를 사용하지 않고 TSI를 넣어 SMI 지표를 만드는 방식이다. SMI 에르고딕은 TSI를 만든 윌리엄 블라우(William Blau)라는 사람이 본인이 만든 TSI에 스토캐스틱을 결합하여 만든 지표다.
2024.05.05 - [주가 분석/기술적 분석] - [기술적 분석] 지표/전략 : 트루 스트랭스 인덱스(TSI, True Strength Index)
2024.05.11 - [주가 분석/기술적 분석] - [기술적 분석] 지표/전략 : 스토캐스틱 슬로우(Stochastic Slow)
TSI는 과거 특정일자의 가격과 현재 가격을 비교하여 기간 동안의 가격 변화(Price Change)를 이용하여 이중 지수 이동 평균(DEMA, Double Exponential Moving Average)을 하여 모멘텀을 측정하는 지표이다. 기본적으로 종가를 기준으로 할 때와는 시각이 다른 게 가격변화를 가지고 스토캐스틱을 뽑아내기 때문에 가격변화 폭에 대한 스토캐스틱이라고 할 수 있다. TSI는 가격변화 폭의 측정 지표이고, 스토캐스틱 오실레이터는 현재 가격이 과거 고가, 저가 범위 내에 어느 정도쯤에 위치해 있는지를 측정하는 지표이니, 가격변화 폭이 관찰기간 내에 어느 정도 와있는지 즉, 현재의 모멘텀을 측정할 수 있는 지표라고 할 수 있다.
TSI 역시 모멘텀을 측정하는 지표인데, TSI를 만들었던 윌리엄 블라우는 이를 더 발전시키기 위해 에르고딕이라는 개념을 적용하였다. 에르고딕(Ergodic)의 사전적인 의미는 상당한 시간이 지난 후에 하나의 체계가 최초의 상태와 거의 유사한 조건에 포함된다는 어려운 개념인데, 좀 더 간단하게 설명하면 시간의 평균과 공간의 평균이 일치하는, 통계적 평균과 장기기간 동안의 평균이 일치하는 상태라는 심오한 의미이다. 근데 윌리엄 블라우는 이 단어를 알고 쓴 걸까..
어쨌든, 스토캐스틱에 TSI를 적용하면서 가격을 기준으로 측정하던 일반적인 스토캐스틱에 비해 좀 더 민감하게 움직이고 기간 내의 모멘텀의 강도를 빠르게 반영할 수 있는 지표가 만들어졌다. SMI 에르고딕은 통상 SMI Ergodic Indicator와 SMI Ergodic Oscillator 두 가지가 있는데 SMI 에르고딕 인디케이터는 스토캐스틱에 존재하는 빠른, 단기의 DEMA 값 %K, 그리고 느린, 장기의 DEMA 값 %D의 두 가지 라인을 그려 표현하는 지표이고 SMI 에르고딕 오실레이터는 SMI 에르고딕 인디케이터의 %K, %D의 차이를 MACD의 히스토그램처럼 표현하는 지표이다.
이번 포스팅에서는 SMI 에르고딕 인디케이터와 SMI 에르고딕 오실레이터를 같이 다뤄 표현한다.
매매 전략은 SMI 라인과 시그널 라인의 교차에 따른, 즉 히스토그램이 양전/음전할 때 매수와 매도를 하는 방식이다. SMI 라인이 시그널 라인을 상향 돌파할 때, 히스토그램이 양전 할 때, 매수, 그리고 SMI 라인이 시그널 라인을 하향 돌파할 때, 히스토그램이 음전할 때, 매도하는 방식이다.
다음으로는 상하단에 밴드를 그려 놓고 SMI 라인이 하단 밴드의 하단에 있다가 상향 돌파할 때, 매수, 상단 밴드의 상단에 있다가 하향 돌파할 때, 매도하는 방식이다. 값의 범위가 크지 않아 -0.2 ~ 0.2, 혹은, -0.25 ~ 0.25 사이를 밴드로 설정하는 경우가 많다.
마지막으로 트레이딩 뷰 파인 스크립트 소스와 pandas-ta 소스를 공유하며 마친다.
- SMI 에르고딕 (SMI Ergodic Indicator/Oscillator) 트레이딩 뷰 파인 스크립트 지표 소스
//@version=5
indicator(title="SMI Ergodic Indicator/Oscillator", shorttitle="SMIIO", format=format.price, precision=4, timeframe="", timeframe_gaps=true)
import TradingView/ta/7 as ta7
import blackcat1402/pandas_ta/7 as pta
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 * volume, length)
"ALMA" => pta.alma(source, length)
"JMA" => pta.jma(source, length)
"SINWMA" => pta.sinwma(source, length)
"FWMA" => pta.fwma(source, length)
"LINREG" => pta.linreg(source, length)
"SWMA" => pta.swma(source)
"YIDYA" => pta.vidya(source, length)
"VWAP" => pta.vwap(source)
"ZLMA" => pta.zlma(source, length)
tsiSourceInput = input.source(close, "TSI Source")
tsiFastLengthInput = input.int(defval=13, title="TSI Fast Length")
tsiSlowLengthInput = input.int(defval=25, title="TSI Slow Length")
signalLegnthInput = input.int(defval=13, title="Signal Line Length")
maTypeInput = input.string("EMA", title="MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], display = display.data_window)
upperInput = input.float(0.2, title="Upper", group="Band Settings")
lowerInput = input.float(-0.2, title="Lower", group="Band Settings")
smi = ta.tsi(tsiSourceInput, tsiFastLengthInput, tsiSlowLengthInput)
signal = ma(smi, signalLegnthInput, maTypeInput)
histogram = smi - signal
smiPlot = plot(smi, color=color.blue, title="SMI")
signalPlot = plot(signal, color=color.orange, title="Signal")
upperBand = hline(upperInput, "Upper Band", color=color.gray)
hline(0, "Middle Band", linestyle=hline.style_dotted, color=color.gray)
lowerBand = hline(lowerInput, "Lower Band", color=color.gray)
fill(upperBand, lowerBand, title="Background", color=color.new(color.gray, 90))
plot(histogram, title = "Histogram", style = plot.style_columns, color = (histogram >= 0 ? (histogram[1] < histogram ? #26A69A : #B2DFDB) : (histogram[1] < histogram ? #FFCDD2 : #FF5252)))
midLinePlot = plot(0, color = na, editable = false, display = display.none)
fill(smiPlot, midLinePlot, 0.5, upperInput, top_color = color.green, bottom_color = color.new(color.green, 100), title = "Overbought Gradient Fill")
fill(smiPlot, midLinePlot, lowerInput, -0.5, top_color = color.new(color.red, 100), bottom_color = color.red, title = "Oversold Gradient Fill")
- SMI 에르고딕 (SMI Ergodic Indicator/Oscillator) 트레이딩 뷰 파인 스크립트 지표 소스
//@version=5
strategy(title="SMI Ergodic Indicator/Oscillator", shorttitle="SMIIO", 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
import blackcat1402/pandas_ta/7 as pta
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 * volume, length)
"ALMA" => pta.alma(source, length)
"JMA" => pta.jma(source, length)
"SINWMA" => pta.sinwma(source, length)
"FWMA" => pta.fwma(source, length)
"LINREG" => pta.linreg(source, length)
"SWMA" => pta.swma(source)
"YIDYA" => pta.vidya(source, length)
"VWAP" => pta.vwap(source)
"ZLMA" => pta.zlma(source, length)
tsiSourceInput = input.source(close, "TSI Source")
tsiFastLengthInput = input.int(defval=13, title="TSI Fast Length")
tsiSlowLengthInput = input.int(defval=26, title="TSI Slow Length")
signalLegnthInput = input.int(defval=9, title="Signal Line Length")
maTypeInput = input.string("EMA", title="MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], display = display.data_window)
upperInput = input.float(0.2, title="Upper", group="Band Settings")
lowerInput = input.float(-0.2, title="Lower", group="Band Settings")
strategySignal = input.string("SMI-Signal Cross", title="Strategy Indicator", options = ["SMI-Band", "Signal-Band", "SMI-Signal Cross"])
smi = ta.tsi(tsiSourceInput, tsiFastLengthInput, tsiSlowLengthInput)
signal = ma(smi, signalLegnthInput, maTypeInput)
histogram = smi - signal
smiPlot = plot(smi, color=color.blue, title="SMI")
signalPlot = plot(signal, color=color.orange, title="Signal")
upperBand = hline(upperInput, "Upper Band", color=color.gray)
hline(0, "Middle Band", linestyle=hline.style_dotted, color=color.gray)
lowerBand = hline(lowerInput, "Lower Band", color=color.gray)
fill(upperBand, lowerBand, title="Background", color=color.new(color.gray, 90))
plot(histogram, title = "Histogram", style = plot.style_columns, color = (histogram >= 0 ? (histogram[1] < histogram ? #26A69A : #B2DFDB) : (histogram[1] < histogram ? #FFCDD2 : #FF5252)))
midLinePlot = plot(0, color = na, editable = false, display = display.none)
fill(smiPlot, midLinePlot, 0.5, upperInput, top_color = color.green, bottom_color = color.new(color.green, 100), title = "Overbought Gradient Fill")
fill(smiPlot, midLinePlot, lowerInput, -0.5, top_color = color.new(color.red, 100), bottom_color = color.red, title = "Oversold Gradient Fill")
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 (strategySignal == "SMI-Band")
if ta.crossover(smi, lowerInput)
strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
if ta.crossunder(smi, upperInput)
strategy.close_all('매도')
if (strategySignal == "Signal-Band")
if ta.crossover(signal, lowerInput)
strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
if ta.crossunder(signal, upperInput)
strategy.close_all('매도')
if (strategySignal == "SMI-Signal Cross")
if ta.crossover(smi, signal)
strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
if ta.crossunder(smi, signal)
strategy.close_all('매도')
bgcolor(strategy.position_size > 0 ? color.new(color.yellow,90) : na)
- SMI 에르고딕 (SMI Ergodic Indicator) 트레이딩 뷰 파인 스크립트 지표 소스
import pandas as pd
import pandas_ta as ta
import FinanceDataReader as fdr
data = fdr.DataReader('005930')
tsi = ta.tsi(close=data['Close'], fast=13, slow=25, signal=13, mamode='EMA')
data = pd.concat([data, tsi], axis=1)
data.dropna(inplace=True)