[기술적 분석] 지표/전략 : 관성 (Inertia)

반응형

 

  관성(Inertia)은 도날드 도시(Donald Dorsey)에 의해 개발된 지표로 본인이 만든 지표인 상대 변동성 지수(RVI, Relative Volatility Index)를 이용하여 RVI를 선형 회귀(Linear Regression) 하여 평활화 한 값을 사용해 주가의 모멘텀과 추세를 측정하는 지표이다.

 

2024.05.04 - [주가 분석/기술적 분석] - [기술적 분석] 지표/전략 : 상대 변동성 지수 (RVI, Relative Volatility Index)

 

[기술적 분석] 지표/전략 : 상대 변동성 지수 (RVI, Relative Volatility Index)

상대 강도 지수 (RSI, Relative Strength Index)와 이름이 비슷한 상대 변동성 지수(RVI, Relative Volatility Index)는 RSI와 유사하나 약간 차이가 있다. RSI는 가격을 비교하여 상승은 상승끼리, 하락은 하락끼리

antsinvest.tistory.com

 

  RVI는 상승분의 표준편차가 하락분의 표준편차에 비해 상대적으로 큰지 작은 지를 표시해주는 변동성 지표이며, 이는 상승 시에 변동성이 하락하거나 횡보할 때보다 변동성이 크다는 전제 하에서 동작한다. 관성은 이를 선형 회귀하거나 지수 이동 평균하여 0~100 사이의 값으로 표현하며 50이 넘으면 상승 추세, 50 밑이면 하락 추세라고 판단한다.

 

관성 (Inertia) 보조지표

반응형

 

  기본적인 매매 방법으로는 50을 기준으로 50보다 크면 매수, 50보다 작으면 매도하는 전략인데, 앞서 설명했듯 이 관성 지표는 50을 기준으로 50 위에서는 상승 추세, 50 아래에서는 하락 추세라고 판단한다. 

 

  다른 매매 방법은 밴드를 정해서 하단 밴드 밑에서는 과매도 구간, 상단 밴드 위에서는 과매수 구간으로 보며 하단 밴드를 상향 돌파할 경우 매수하고, 상단 밴드를 하단 돌파할 경우 매도하는 전략이다. 단 밴드의 간격 설정은 종목에 따라 최적 밴드가 차이가 많이 날 수 있다. 

 

  마지막으로 관성 (Inertia) 트레이딩 뷰 파인 스크립트 소스와 pandas-ta 소스를 공유하며 마친다.

 

 

  • 관성 (Inertia) 트레이딩 뷰 파인 스크립트 지표 소스
//@version=5
indicator(title="Inertia", shorttitle="Inertia", format=format.price, precision=2, 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)

sourceInput = input.string("High, Low", title="Source", options=["Close", "High, Low", "High, Low, Close"], group="RVI Settings")
stdLengthInput = input.int(10, minval=1, title="Standard Deviation Length", group="RVI Settings")
rviLengthInput = input.int(14, minval=1, title="RVI Length", group="RVI Settings")
rviMATypeInput = 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"], group="RVI Settings")
maLengthInput = input.int(20, title="MA Length", group="MA Settings")
maTypeInput = input.string("LINREG", title="MA Type", options=["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="MA Settings")
lower = input.int(30, title="Lower", group="Band Settings")
upper = input.int(70, title="Upper", group="Band Settings")

rvi=0.0
if (sourceInput == "Close")
    close_stddev = ta.stdev(close, stdLengthInput)
    clsee_upper = ma(ta.change(close) <= 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    clsee_lower = ma(ta.change(close) > 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    rvi := clsee_upper / (clsee_upper + clsee_lower) * 100
if (sourceInput == "High, Low")
    high_stddev = ta.stdev(high, stdLengthInput)
    high_upper = ma(ta.change(high) <= 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_lower = ma(ta.change(high) > 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_rvi = high_upper / (high_upper + high_lower) * 100
    low_stddev = ta.stdev(low, stdLengthInput)
    low_upper = ma(ta.change(low) <= 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_lower = ma(ta.change(low) > 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_rvi = low_upper / (low_upper + low_lower) * 100
    rvi := (high_rvi + low_rvi) / 2
if (sourceInput == "High, Low, Close")
    high_stddev = ta.stdev(high, stdLengthInput)
    high_upper = ma(ta.change(high) <= 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_lower = ma(ta.change(high) > 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_rvi = high_upper / (high_upper + high_lower) * 100
    low_stddev = ta.stdev(low, stdLengthInput)
    low_upper = ma(ta.change(low) <= 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_lower = ma(ta.change(low) > 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_rvi = low_upper / (low_upper + low_lower) * 100
    close_stddev = ta.stdev(close, stdLengthInput)
    clsee_upper = ma(ta.change(close) <= 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    clsee_lower = ma(ta.change(close) > 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    close_rvi = clsee_upper / (clsee_upper + clsee_lower) * 100   
    rvi := (high_rvi + low_rvi + close_rvi) / 3

inertia = ma(rvi, maLengthInput, maTypeInput)


h0 = hline(upper, "Upper Band", color=color.gray)
hline(50, "Middle Band", color=color.gray)
h1 = hline(lower, "Lower Band", color=color.gray)
fill(h0, h1, color=color.new(color.gray, 80), title="Background")

inertiaPlot = plot(inertia, title="Inertia", color=color.blue)
midLinePlot = plot(50, color = na, editable = false, display = display.none)
fill(inertiaPlot, midLinePlot, 100, 50, top_color = color.green, bottom_color = color.new(color.green, 100))
fill(inertiaPlot, midLinePlot, 50, 0, top_color = color.new(color.red, 100), bottom_color = color.red)

 

 

  • 관성 (Inertia) 트레이딩 뷰 파인 스크립트 전략 소스
//@version=5
strategy(title="Inertia", shorttitle="Inertia", 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)

sourceInput = input.string("High, Low", title="Source", options=["Close", "High, Low", "High, Low, Close"], group="RVI Settings")
stdLengthInput = input.int(10, minval=1, title="Standard Deviation Length", group="RVI Settings")
rviLengthInput = input.int(14, minval=1, title="RVI Length", group="RVI Settings")
rviMATypeInput = 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"], group="RVI Settings")
maLengthInput = input.int(20, title="MA Length", group="MA Settings")
maTypeInput = input.string("LINREG", title="MA Type", options=["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="MA Settings")
lowerInput = input.int(30, title="Lower", group="Band Settings")
upperInput = input.int(70, title="Upper", group="Band Settings")

rvi=0.0
if (sourceInput == "Close")
    close_stddev = ta.stdev(close, stdLengthInput)
    clsee_upper = ma(ta.change(close) <= 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    clsee_lower = ma(ta.change(close) > 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    rvi := clsee_upper / (clsee_upper + clsee_lower) * 100
if (sourceInput == "High, Low")
    high_stddev = ta.stdev(high, stdLengthInput)
    high_upper = ma(ta.change(high) <= 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_lower = ma(ta.change(high) > 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_rvi = high_upper / (high_upper + high_lower) * 100
    low_stddev = ta.stdev(low, stdLengthInput)
    low_upper = ma(ta.change(low) <= 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_lower = ma(ta.change(low) > 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_rvi = low_upper / (low_upper + low_lower) * 100
    rvi := (high_rvi + low_rvi) / 2
if (sourceInput == "High, Low, Close")
    high_stddev = ta.stdev(high, stdLengthInput)
    high_upper = ma(ta.change(high) <= 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_lower = ma(ta.change(high) > 0 ? 0 : high_stddev, rviLengthInput, rviMATypeInput)
    high_rvi = high_upper / (high_upper + high_lower) * 100
    low_stddev = ta.stdev(low, stdLengthInput)
    low_upper = ma(ta.change(low) <= 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_lower = ma(ta.change(low) > 0 ? 0 : low_stddev, rviLengthInput, rviMATypeInput)
    low_rvi = low_upper / (low_upper + low_lower) * 100
    close_stddev = ta.stdev(close, stdLengthInput)
    clsee_upper = ma(ta.change(close) <= 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    clsee_lower = ma(ta.change(close) > 0 ? 0 : close_stddev, rviLengthInput, rviMATypeInput)
    close_rvi = clsee_upper / (clsee_upper + clsee_lower) * 100   
    rvi := (high_rvi + low_rvi + close_rvi) / 3

inertia = ma(rvi, maLengthInput, maTypeInput)


h0 = hline(upperInput, "Upper Band", color=color.gray)
hline(50, "Middle Band", color=color.gray)
h1 = hline(lowerInput, "Lower Band", color=color.gray)
fill(h0, h1, color=color.new(color.gray, 80), title="Background")

inertiaPlot = plot(inertia, title="Inertia", color=color.blue)
midLinePlot = plot(50, color = na, editable = false, display = display.none)
fill(inertiaPlot, midLinePlot, 100, 50, top_color = color.green, bottom_color = color.new(color.green, 100))
fill(inertiaPlot, midLinePlot, 50, 0, top_color = color.new(color.red, 100), bottom_color = color.red)

buySignalInput = input.string("Inertia-Band", title="Buy Signal", options = ["Inertia-Band", "Inertia-50 Cross"])
sellSignalInput = input.string("Inertia-Band", title="Sell Signal", options = ["Inertia-Band", "Inertia-50 Cross"])
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 (buySignalInput == "Inertia-Band")
		if ta.crossover(inertia, lowerInput)
			strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
	if (buySignalInput == "Inertia-50 Cross")
		if ta.crossover(inertia, 50)
			strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
    if (sellSignalInput == "Inertia-Band")
        if ta.crossunder(inertia, upperInput)
			strategy.close_all('매도')
    if (sellSignalInput == "Inertia-50 Cross")
		if ta.crossunder(inertia, 50)
			strategy.close_all('매도')
    
bgcolor(strategy.position_size > 0 ? color.new(color.yellow,90) : na)

 

 

  • 관성 (Inertia) pandas-ta 소스
import pandas as pd
import pandas_ta as ta
import FinanceDataReader as fdr

data = fdr.DataReader('005930')
inertia = ta.inertia(close=data['Close'], high=data['High'], low=data['Low'], length=20, rvi_length=14, mamode='EMA')
data = pd.concat([data, inertia], axis=1)
data.dropna(inplace=True)
반응형