スーパートレンドV.1 -- スーパートレンドラインシステム

作者: リン・ハーンリディア, 作成日:2022-12-01 11:36:33, 更新日:2023-09-11 20:04:38

img

I. 物語の起源

良き友人であるラン氏は この指標を長い間観察し 新年明け前には 定量化できるかどうか 議論するために 私に勧めました 延ばし屋がそんな願いを叶えるのを 今までに遅らせてしまったのは残念です 実際,最近 アルゴリズムについての私の理解は急速に改善しました いつの日か私はパインの言語の翻訳者を書こうと推定されています.何でもパイソンでできます. 冗談を言わずに 伝説的なスーパートレンドラインを紹介しましょう

システム導入

CMC Marketsの新しい世代のインテリジェント・トレーディング・システムでは,使用するテクニカル・インジケーターから"スーパー・トレンド・ライン"を選択できます. 増幅信号と減少信号の色と厚さを 自分の好みに応じて調整できます スーパートレンドインジケーターの公式を理解する前に,ATRを理解する必要があります. スーパートレンドはATR値を採用して指標値を計算します. 主なアルゴリズムは次の図で説明されています.

img

HL2 (k線平均価格) + ATRの n 倍. トレンド突破をします. 詳細なアルゴリズムはありません. そこで私は最も素晴らしいコミュニティを考えました, TradingView. 実に,それは確かにそこにあります.

img

グラフを見ると 傾向に合致しています 残念なことに これはアラーム信号に過ぎません

III. ソースコードを学ぶ

コードが長くないので 翻訳してみましょう!

img

パインコードは上記のように

VI コード変換

FMZで新しい戦略を作り出し,それをスーパートレンドと名付けます

img

2つのパラメータを設定します.

img

Pythonの高度なデータ拡張パッケージ Pandas を使用する必要があります (https://pandas.pydata.org/) について FMZは今この図書館をサポートしています.

  1. パンダ図書館とタイムライブラリをインポートする必要があります
  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)
  1. K-lineの OHCLV を取得する必要があります.
  2. パンダ M15 = pd.DataFrame (記録) に取得したデータをインポートします.
  3. M15.kolumns = [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']  
  1. データセットに列を追加します hl2 hl2=(high+low) /2
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
  1. ATRを計算してみましょう. 値が Pd の変数長を輸入する必要があります.

次にMyLanguageのマニュアルを参照し,ATRの実際の変動幅の平均値のアルゴリズムステップは以下のとおりです. TR: MAX (MAX) (MAX) (HIGH (HIGH) (Low) (ABS (REF) (CLOSE,1) (HIGH) (ABS (REF) (CLOSE,1) (Low)) ATR: RMA (TR,N)

TR値は,次の3つの差の最大値である.

  1. 当日取引中の最高価格と最低価格の変動 HIGH-LOW
  2. 前回の取引日の終了価格と現在の取引日の最高価格の間の変動 (REF) (CLOSE, 1) - HIGH
  3. 前回の取引日の終了価格と現在の取引日の最低価格の変動 (REF) (CLOSE, 1) - LOW) だからTR:MAX (MAX) (MAX) (HIGH-LOW) (ABS (REF) (CLOSE,1) (HIGH) (ABS (REF) (CLOSE,1) (Low));

Python の計算では

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

前の行で,つまり,新しいパラメータを形成するために1グリッドで右に移動

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

次に,TRの対照値3つの配列を記録する中間変数を定義します. (HIGH-LOW) (high-prev_close) (low-prev_close)

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

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:RMA (TR,N) の値を計算する必要があります. RMAアルゴリズムは EMAアルゴリズムの固定値変数であることが判明しました. 標準パラメータは 14 です. ここで,アルファ=長さの対数をインポートします.

===

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 アップとDnを計算する

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

Up=hl2 - (因数*atr) Dn=hl2 +(因数 * 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

この段落の主なポイントは, 上昇段階にある場合 (下の線) トレンドアップ=最大 (上昇,トレンドアップ [1]) 落ちている場合 (上行) TrendDown=min (Dn,TrendDown [1]) つまり,ATR値が動いている傾向は,Bandit Bollinger戦略に似た技術を使っているということです. 運河の反対側を絞り続ける

この場合は,TrendUpとTrendDownの各計算は自己繰り返しを必要とします. つまり,各ステップは前のステップに従って計算されるべきです. したがって,データセットはループで繰り返されるべきです.

初期値を与えます. 初期値が,最初の値に等しくなります. 0 で計算した結果の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)):

トレンドアップを計算する トレンドアップ = MAX(アップ,トレンドアップ[-1]) 近い場合[-1]>トレンドアップ[-1] 前回の Close>前回の TrendUp が true ならば,Up と前回の TrendUp の間の最大値が取られ,そうでなければ,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]

同じように,トレンドダウンを計算します. トレンドダウン=min(Dn,TrendDown[-1]) が接近している場合[-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]

制御方向を計算するためのフラグです.私は偽コードを簡素化しました トレンド= 1 if (close > TrendDown[-1]) else (x) x = -1 もし (close

値が1 (上昇) ならば,値を取ります. そうでない場合は,値を取ります. 閉じる価格が前回のトレンドアップより低い場合は, -1 (下落) の値を取ります.そうでなければ,前回のトレンド (変化なし) を取ります. 画像言語に翻訳すると,上線トレイル移行フラグのブレイクが上昇し,下線トレイル移行フラグのブレイクが下線トレイル移行フラグのブレイクです.

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

Tsl と Linecolor を計算する Tsl=RendUp if (トレンド==1) else トレンドダウン Tsl は,画像上のスーパートレンドを表すのに使用される値です. これは,上昇傾向にある画像のダウントラックをマークし,下落傾向にある画像の上部トラックをマークすることを意味します. linecolor= 緑色 (トレンド==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'

次の 23-30 行のコードは主にグラフ図で,ここでは説明されていません.

購入と販売の信号を制御する 2 行のコードがあります Tradeviewでは,信号がフラグを逆転した後で与えられていることを意味します 条件文を python に変換します 最後のトレンドフラグが -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)

img img

V. 完全なコード

全体のコード構造を調整した ストラテジーに組み込みました ストラテジーは 完全なコードはこうです

'''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

VI バックテストと要約

過去1年のデータを バックテストに利用しました 15分間の期間で OKEXの四半期契約を使います 設定されたパラメータは: 要素=3 Pd=45 Vol=100 (各注文につき100契約) 年間収益率は約33%です 一般的に,抽出はあまり多くありません 312 の急激な減少は,システムに比較的大きな影響を与えた. 312がないなら 返金はもっと良いはずです

img

VII.最後に書く

スーパートレンドは非常に良い取引システムです

スーパートレンドシステムの主な原則は,ATRチャンネル突破戦略を採用することです (ケントチャンネルに似ている) しかし,その変化は主にバンディット・ボリンガー (Bandit Bollinger) の絞り込み戦略,またはドンチアン原理の逆の使用によるものです. 市場操作では 上下のチャネルが絶えず狭くなっています (チャネルを突破すると,上部と下部の軌跡は元の値に戻る)

TradeViewで TrendUpとTrendDnを別々にグラフ化します 戦略をよりよく理解できるようにします 一目でわかるように

img

js のバージョンが github にあります. js は苦手ですが,if ステートメントに何か問題があるようです. アドレス:https://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

最終的にはオリジナルのバージョンを 追跡しました 2013年5月29日に掲載されました 著者はラジャンドラン R C++コードは Mt4 フォーラムで公開されました:https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4C++の意味を大まかに理解し,機会があったら書き直します.

精髓を学べるといいな 難しい!


関連性

もっと