0
집중하다
48
수행원

SuperTrend V.1--슈퍼 트렌드 라인 시스템

만든 날짜: 2020-04-20 22:10:36, 업데이트 날짜: 2024-12-12 21:03:30
comments   28
hits   11392

SuperTrend V.1–슈퍼 트렌드 라인 시스템

1. 이야기의 기원

저의 좋은 친구인 란은 이 지표를 오랫동안 관찰해왔고, 이를 정량적 형태로 변환할 수 있는지 논의하기 위해 새해 전에 제게 추천해주었습니다. 불행히도, 나는 미루는 버릇이 있어서 지금까지 그의 소원을 이루도록 돕지 못했습니다. 사실, 알고리즘에 대한 나의 이해는 최근에 크게 발전했습니다. 언젠가는 소나무 번역기를 써보고 싶습니다. 모든 것이 파이썬이 될 수 있습니다. . 좋습니다. 더 이상 미루지 말고 이 전설적인 슈퍼 트렌드 라인을 소개하겠습니다. .

2. 시스템 소개

CMC Markets의 차세대 지능형 거래 시스템 - Supertrend 이 시스템을 소개하는 기사는 다음과 같습니다. SuperTrend V.1–슈퍼 트렌드 라인 시스템

CMC Markets의 신세대 지능형 거래 시스템에서는 기술 지표에서 “슈퍼 트렌드 라인”을 선택하여 불러옵니다. 그림에서 보듯이, 사용자의 선호도에 따라 상승 및 하강 신호의 “색상 및 두께”를 조절할 수 있습니다. 그렇다면 슈퍼트렌드 지표는 무엇일까요? 슈퍼트렌드 지표 공식을 이해하기 전에 ATR을 이해하는 것이 필요합니다. 슈퍼트렌드는 ATR 값을 사용하여 지표 값을 계산하기 때문입니다.

주요 알고리즘도 아래 그림에 소개되어 있습니다. SuperTrend V.1–슈퍼 트렌드 라인 시스템

대략적으로 보면 주요 설명은 HL2 채널(K-라인의 평균 가격)에 ATR을 n배 곱한 것입니다. 트렌드를 혁신하세요. 하지만 기사 내용은 다소 짧습니다. 자세한 알고리즘은 없습니다. 그러다가 최고의 커뮤니티인 Tradingview가 떠올랐습니다. 놀랍지도 않네요. 실제로 그것은 거기에 있었습니다. SuperTrend V.1–슈퍼 트렌드 라인 시스템

그래프로 판단할 때, 이는 추세와 상당히 일치합니다. 하지만 불행히도 그것은 단지 경고 신호일 뿐입니다.

3. 소스코드를 연구하세요

코드가 그렇게 길지 않은 것 같으니, 번역해서 한 번 시도해 볼까요? ! (っ•̀ω•́)っ✎⁾⁾! SuperTrend V.1–슈퍼 트렌드 라인 시스템 전체 소나무 코드는 위와 같습니다. .

4. 코드 변환

여기서 FMZ에서 새로운 전략을 만들고 이를 SuperTrade라고 명명합니다. SuperTrend V.1–슈퍼 트렌드 라인 시스템

다음으로, 우리는 Factor와 Pd라는 두 개의 매개변수를 설정합니다. SuperTrend V.1–슈퍼 트렌드 라인 시스템

코드의 작동을 더 단순화하고 이해하기 쉽게 하기 위해 Python의 고급 데이터 확장 패키지를 사용해야 합니다.pandas

점심시간에 저는 멩멩 선생님께 FMZ에서 이 도서관을 지원하는지 물었습니다. 오후에 확인해보니 실제로 작동하더군요. 멍멍 선생님은 정말 놀랍습니다.

1. pandas 라이브러리 time 라이브러리를 가져와야 합니다. 2. 메인 기능(주로 OKEX 실행)에서 분기별 계약 설정 3. doTicker() 루프를 설정하여 15분마다 테스트합니다. 15분 주기로 코드 실행 다음으로 doTicker()에서 주요 전략을 작성합니다.

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)
        

4. K-라인의 OHCLV를 검색해야 하므로 GetRecords()를 사용합니다. 5. 검색된 데이터를 pandas로 가져옵니다 M15 = pd.DataFrame(records) 6. 테이블 헤더 태그를 수정해야 합니다. M15.열 =[‘time’,‘open’,‘high’,‘low’,‘close’,‘volume’,‘OpenInterest’] 사실, 이 코드는 단지 ‘open’, ‘high’, ‘low’, ‘close’의 첫 글자를 소문자로 바꾸어서 나중에 대문자와 소문자를 번갈아 사용하지 않고도 코드를 작성하기 쉽게 해줍니다.

def doTicker(records):
    M15 = pd.DataFrame(records)
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  

7. 데이터 세트에 hl2 열 추가 hl2=(high+low)/2

#HL2
M15['hl2']=(M15['high']+M15['low'])/2

8. 다음으로 ATR을 계산해 보겠습니다. ATR 계산에는 가변 길이의 수입이 필요하므로 그 값은 Pd입니다.

그런 다음 Mai 언어 매뉴얼을 참조하면 ATR 실제 변동성 평균의 알고리즘 단계는 다음과 같습니다. TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR : RMA(TR,N)

TR 값은 다음 세 가지 차이점 중 가장 큰 값입니다. 1. 현재 거래일의 최고가와 최저가의 변동 HIGH-LOW 2. 전거래일 종가와 현재거래일 최고가의 변동폭 (REF(CLOSE,1)-HIGH) 3. 전거래일 종가와 현재거래일 최저가의 변동폭 (REF(CLOSE,1)-LOW) 따라서 TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));

파이썬 계산

M15['prev_close']=M15['close'].shift(1)

먼저, 이전 행의 close 데이터를 가져오기 위해 prev_close를 설정합니다. 즉, close를 오른쪽으로 1 그리드만큼 이동하여 새 매개변수를 형성합니다.

ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]

다음으로, TR의 세 가지 비교값 배열을 기록하기 위한 중간 변수를 정의합니다. (높음-낮음)(높음-이전_종가)(낮음-이전_종가)

M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)

데이터 집합에 TR이라는 새 열을 정의합니다. TR의 값은 중간 변수의 최대 절대값입니다. abs() 및 max() 함수를 사용합니다.

    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

마지막으로 ATR, ATR: RMA(TR, N)의 값을 계산해야 합니다. RMA 알고리즘은 실제로 EMA 알고리즘의 고정 값 변형인 것으로 밝혀졌습니다. N은 우리가 가져온 변수이고, ATR의 기본 매개변수는 14입니다. 여기서 우리는 알파 = 길이의 역수를 가져옵니다.

===

그런 다음 EWM 알고리즘을 사용하여 EMA를 계산합니다. 전체 ATR 계산 프로세스는 다음과 같습니다.

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

9 위아래 계산 시작

    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])

Up=hl2 -(Factor * atr) Dn=hl2 +(Factor * atr) 간단하지 않나요?

다음은 TV의 15-21행의 핵심 코드 세그먼트입니다.

TrendUp=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn

Trend = close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl = Trend==1? TrendUp: TrendDown

linecolor = Trend == 1 ? green : red

이 문단의 주요 목적은 다음을 표현하는 것입니다. 강세 국면인 경우 (아래쪽 선) TrendUp = max(Up,TrendUp[1]) 하락단계일 경우 (윗줄) TrendDown=min(Dn,TrendDown[1]) 즉, 추세적으로 ATR 값은 밴딧 볼린저 전략과 유사한 기술을 사용하고 있습니다. 채널의 반대편을 계속 좁히세요

여기에서는 TrendUp과 TrendDown의 각 계산이 자체 반복되어야 합니다. 즉, 각 단계는 이전 단계를 기반으로 계산되어야 합니다. 그래서 데이터 세트를 반복해야 합니다.

여기서는 먼저 데이터 집합에 대한 새로운 필드 TrendUp, TrendDown, Trend 및 linecolor를 만들어야 합니다. 그리고 그들에게 초기값을 제공합니다 그런 다음 fillna(0) 구문을 사용하여 이전에 계산된 결과의 null 값을 0으로 채웁니다.

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

for 루프를 시작합니다 루프에서 Python 삼항 연산 사용

    for x in range(len(M15)):

TrendUp 계산 TrendUp = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up 일반적인 의미는 이전 종가 > 이전 TrendUp인 경우, 참이면 Up의 최대값을 가져오고, 참이 아니면 Up 값을 가져와 현재 TrendUp에 전달합니다.

        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]

마찬가지로 TrendDown을 계산합니다. TrendDown=min(Dn,TrendDown[-1]) if close[-1]

        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]

아래는 제어 방향을 계산하기 위한 플래그입니다. 의사 코드를 단순화했습니다. Trend= 1 if (close > TrendDown[-1]) else (x) x = -1 if (close< TrendUp[-1]) else Trend[-1]

즉, 종가가 이전 TrendDown보다 높으면 1(강세)을 취하고 그렇지 않으면 x를 취한다는 의미입니다. 종가가 이전 TrendUp보다 낮으면 -1(숏)을 취합니다. 그렇지 않으면 이전 Trend(즉, 변경되지 않음)을 취합니다. 그래픽 언어로 번역하면, 상단 레일을 돌파하여 플래그를 강세로 전환하고, 하단 레일을 돌파하여 플래그를 약세로 전환하는 것을 의미하며, 다른 시간은 변경되지 않습니다.

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]

Tsl과 Linecolor 계산 Tsl= rendUp if (Trend==1) else TrendDown Tsl은 그래프에서 SuperTrend의 값을 나타내는 데 사용됩니다. 즉, 상승장세일 때는 차트의 아래쪽 트랙을 표시하고, 하락장세일 때는 차트의 위쪽 트랙을 표시하세요. linecolor= ‘green’ if (Trend==1) else ‘red’ linecolor의 의미는 상승장세라면 녹색선을 표시하고 하락장세라면 빈 색상을 표시한다는 것입니다(주로 Tradingview 디스플레이에 사용됨)

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'

이어지는 23~30번째 줄은 주로 플로팅을 위한 것이므로, 여기서는 자세히 설명하지 않겠습니다.

마지막으로, 신호 제어를 구매 및 판매하기 위한 2줄의 코드가 있습니다. Tradingview에서는 플래그를 반전한 후 신호를 보내는 것을 의미합니다. 조건문을 파이썬으로 변환합니다. 이전 트렌드 플래그가 -1에서 1로 변경되면 상단 저항이 깨졌다는 의미입니다. 오픈 롱 이전 트렌드 플래그가 1에서 -1로 변경되면 하향 지원이 깨졌다는 의미입니다. 숏 포지션을 엽니다.

    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)

이 섹션의 전체 코드는 다음과 같습니다.

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)
    
    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'
        
    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
        Log('Tsl=',Tsl)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)
        Log('Tsl=',Tsl)

SuperTrend V.1–슈퍼 트렌드 라인 시스템

SuperTrend V.1–슈퍼 트렌드 라인 시스템

5. 모든 코드

전반적인 코드 구조를 조정했습니다. 그리고 롱과 숏 관련 주문 지침을 전략에 병합합니다. 전체 코드는 다음과 같습니다.

'''backtest
start: 2019-05-01 00:00:00
end: 2020-04-21 00:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
'''

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)

       
def doTicker(records):
    #Log('onTick',exchange.GetTicker())
    M15 = pd.DataFrame(records)

    #Factor=3
    #Pd=7
    
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  
    
    #HL2
    M15['hl2']=(M15['high']+M15['low'])/2

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()


    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])
    
    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'Long' if ( M15['Trend'].values[x]==1) else  'Short'
 

    linecolor=M15['linecolor'].values[-2]
    close=M15['close'].values[-2]
    Tsl=M15['Tsl'].values[-2] 


    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):

        Log('SuperTrend V.1 Alert Long','Create Order Buy')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closesell")
            exchange.Buy(_C(exchange.GetTicker).Sell*1.01, Amount);
        
        exchange.SetDirection("buy")
        exchange.Buy(_C(exchange.GetTicker).Sell*1.01, vol);

    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long','Create Order Sell')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closebuy")
            exchange.Sell(_C(exchange.GetTicker).Buy*0.99,Amount);
        exchange.SetDirection("sell")
        exchange.Sell(_C(exchange.GetTicker).Buy*0.99, vol*2);

공개 전략 링크: https://www.fmz.com/strategy/200625

6. 백테스팅 및 요약

우리는 백테스팅을 위해 작년의 데이터를 선택했습니다. 15분 주기의 OKEX 분기별 계약을 사용하세요. 설정된 매개변수는 다음과 같습니다. Factor=3 Pd=45 vol=100 (주문당 티켓 100장) 연간 수익률은 약 33%이다. 일반적으로 되돌림 폭은 크지 않습니다. 그 주된 이유는 시스템에 상당한 영향을 끼친 312번 추락 사고 때문입니다. 312가 없었다면 수익이 더 좋았을 텐데요.

SuperTrend V.1–슈퍼 트렌드 라인 시스템

6. 마무리 생각

SuperTrend는 매우 좋은 거래 시스템입니다

SuperTrend 시스템의 주요 원리는 ATR 채널 브레이크아웃 전략(Kent 채널과 유사)을 사용하는 것입니다. 하지만 가장 큰 변화는 밴딧 볼린저 협소화 전략, 혹은 역 돈키안 원칙을 사용하는 데 있습니다. 시장이 운영되는 동안 상단 및 하단 채널은 지속적으로 좁아집니다. 채널 돌파 및 회전 작업을 달성하기 위해. (채널이 돌파되면 위쪽과 아래쪽 레일은 초기 값으로 돌아갑니다)

저는 TradingView에서 별도로 dn TrendUp TrendDn을 그래프로 표시했습니다. 이렇게 하면 이 전략을 더 잘 이해하는 데 도움이 됩니다. 한눈에 보기에 명확함 SuperTrend V.1–슈퍼 트렌드 라인 시스템

Github에는 js 버전도 있습니다. 저는 js를 잘 이해하지 못하지만, if 문으로 판단해 보면 문제가 있는 것 같습니다. 주소는https://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

마침내 원본을 찾아냈습니다. 2013.05.29에 게시되었습니다 Rajandran R 작성 Mt4 포럼에 게시된 C++ 코드https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4 저는 C++의 의미를 대략적으로 이해하고 있으며, 기회가 되면 다시 작성해 보겠습니다.

모두가 이것의 본질을 배울 수 있기를 바랍니다. 어렵죠. ~!