Python으로 AlphaTrend 지표 구현하기

AlphaTrend는 트레이딩뷰 오픈 소스로 ‘KivancOzbilgic‘ 라는 유저가 공개하였습니다.

💡유저 설명 요약

1️⃣ 손실을 최소화하고 횡보 시장 상황을 극복합니다.
2️⃣ 추세 시장 조건에서 더 정확한 매수/매도 신호를 제공합니다.
3️⃣ 중요한 지지선과 저항선을 제공합니다.
4️⃣ 모멘텀, 추세, 변동성, 거래량, 이동 손절매 등 다양한 카테고리의 지표들을 함께 결합하여 의미 있는 조합을 만듭니다.

AlphaTrend 지표는 Magic Trend의 한계를 개선하여 손실을 최소화하고 횡보 시장의 거짓 신호를 줄이는 데 중점을 둡니다. 이 지표는 모멘텀, 추세, 변동성, 거래량, 그리고 이동 손절매를 포괄하는 여러 지표의 조합을 활용합니다.

import pandas as pd
import ccxt
import pinetopy as pp
import numpy as np

# Binance Futures, BTCUSDT, 1h
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 _atr(df, length=14):
    _df = df.copy()
    _df['HL'] = _df['high'] - _df['low']
    _df['HC'] = abs(_df['high'] - _df['close'].shift())
    _df['LC'] = abs(_df['low'] - _df['close'].shift())
    
    _df['TR'] = _df[['HL', 'HC', 'LC']].max(axis=1)
    return pp.sma(_df['TR'], length=length)

def barssince(df, condition):
    condition_hits = df[condition].astype(int)
    groups = condition_hits.cumsum()
    bars_since_hit = df.groupby(groups).cumcount()
    bars_since_hit[condition_hits == 1] = 0
    return bars_since_hit

# TradingView Default Settings
def main(df, length=14, mult=1.0, no_volume_data=False):
    
    atr = _atr(df, length=length)
    upT = df['low'] - atr * mult
    downT = df['high'] + atr * mult
    
    mfi = pp.mfi(df, length=length)
    rsi = pp.rsi(df['close'], length=length)
    
    df['AlphaTrend'] = 0.0
    for i in range(1, len(df)):
        prev_alpha = df.loc[i-1, 'AlphaTrend']
        condition = rsi[i] >= 50 if no_volume_data else mfi[i] >= 50

        if condition:
            df.loc[i, 'AlphaTrend'] = prev_alpha if upT[i] < df.loc[i-1, 'AlphaTrend'] else upT[i]
        else:
            df.loc[i, 'AlphaTrend'] = prev_alpha if downT[i] > df.loc[i-1, 'AlphaTrend'] else downT[i]

    df['AlphaTrend'] = df['AlphaTrend'].fillna(0)
    df['AlphaTrend_2'] = df['AlphaTrend'].shift(2).fillna(0)
    
    df['buy_signal'] = (df['AlphaTrend'] > df['AlphaTrend'].shift(2))
    df['sell_signal'] = (df['AlphaTrend'] < df['AlphaTrend'].shift(2))
    df['buy_signal'] = np.where((df['buy_signal']) & (~df['buy_signal'].shift(1, fill_value=False)), True, False)
    df['sell_signal'] = np.where((df['sell_signal']) & (~df['sell_signal'].shift(1, fill_value=False)), True, False)
    df['buy_signal_prev'] = df['buy_signal'].shift(1).fillna(0)
    df['sell_signal_prev'] = df['sell_signal'].shift(1).fillna(0)
    
    buySignalk = df['buy_signal']
    sellSignalk = df['sell_signal']
    k1 = barssince(df, 'buy_signal')
    k2 = barssince(df, 'sell_signal')
    o1 = barssince(df, 'buy_signal_prev')
    o2 = barssince(df, 'sell_signal_prev')

    df['signal'] = np.where(buySignalk & (o1 > k2), 'Buy', np.where(sellSignalk & (o2 > k1), 'Sell', ''))

    # only signal
    signal = df[df['signal'] != '']
    return signal[['time', 'AlphaTrend', 'AlphaTrend_2', 'signal']]

print(main(df))

트레이딩뷰 차트와 비교