Type/to search
0
Follow
48
Followers
SuperTrend V.1 - スーパートレンドラインシステム
Original
Created 2020-04-20 22:10:36  Updated 2024-12-12 21:03:30
 28
 12168

img

1. 物語の起源

私の親友のランは長い間この指標を観察していて、元旦前に私にそれを勧め、定量的な形に変換できるかどうか議論しました。
残念ながら、私は先延ばし癖があり、今まで彼の願いを叶える手助けをしてきませんでした。実際、アルゴリズムに対する私の理解は最近大きく進歩しました。
いつか松の翻訳機を書こうと思っています。すべてを Python にすることができます。 。
さて、これ以上前置きせずに、この伝説的なスーパートレンドラインを紹介しましょう。 。

2. システムの紹介

CMC Markets の新世代インテリジェント取引システム - Supertrend
このシステムを紹介する記事はこちらです。
img

CMC Markets の新世代インテリジェント取引システムでは、テクニカル指標で「スーパートレンドライン」を選択して呼び出します。
図のように、上昇信号と下降信号の「色と太さ」を好みに応じて調整できます。
では、スーパートレンド指標とは何でしょうか?スーパートレンドインジケーターの計算式を理解する前に、ATR を理解する必要があります。スーパートレンドは ATR 値を使用してインジケーターの値を計算するためです。

主なアルゴリズムは下の図でも紹介されています。
img

ざっと見てみると、主な説明はHL2(Kラインの平均価格)にATRのn倍を乗じたチャネルです。トレンドを突破する。
しかし、この記事はかなり短いです。詳細なアルゴリズムはありません。そこで、最高のコミュニティであるTradingviewを思いつきました。
驚くことではありません。確かに、そこにあります。
img

グラフから判断すると、傾向とかなり一致しています。しかし残念ながら、それは単なる警告信号です。

3. ソースコードを調べる

コードはそれほど長くはないので、翻訳して試してみましょう。 ! (っ•̀ω•́)っ✎⁾⁾!
img
完全な Pine コードは上記のとおりです。 。

4. コード変換

ここではFMZで新しい戦略を作成し、SuperTradeと名付けます。
img

次に、2つのパラメータFactorとPdを設定します。
img

コードの操作をより簡素化し、理解しやすくするために、Pythonの高度なデータ拡張パッケージを使用する必要があります。pandas

昼食時に、私は孟孟先生に、FMZがこのライブラリをサポートしているかどうか尋ねました。午後に確認したところ、実際に動作しました。
孟孟先生は本当にすごいです。

1.パンダライブラリのtimeライブラリをインポートする必要があります
2. メイン機能(主にOKEXを実行)で四半期契約を設定する
3. 15 分ごとに 1 回テストするループ doTicker() を設定します。
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 値は、次の 3 つの差の中で最大になります。

  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));

Pythonの計算では

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の3つの比較値の配列を記録するための中間変数を定義します。 (高値-安値)(高値-前日終値)(安値-前日終値)

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 です。ここでは、長さの逆数である alpha をインポートします。

===

次に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 UpとDnの計算を開始する

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)構文を使用して、以前に計算された結果のデータを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 = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up
一般的な意味は、前回の終値 > 前回のトレンドアップの場合、それが真であれば、アップと前回のトレンドアップの最大値を取得し、それが真でない場合は、アップ値を取得して現在のトレンドアップに渡すことです。

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]<TrendDown[-1] else Dn
一般的な意味は、前回の終値が前回のTrendDownより小さい場合、それが真であればDnと前回のTrendDownの間の最小値を取得し、それが真でない場合はDn値を取得して現在のTrendDownに渡すことです。

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]

意味は、終値が前回のトレンドダウンよりも大きい場合は1(強気)を取り、そうでない場合はxを取るということです。
終値が前回のトレンドアップより低い場合は、-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 (Trend==1) else TrendDown
Tsl はグラフ上で SuperTrend の値を表すために使用されます。つまり、強気の場合はチャートの下側​​のトラックをマークし、弱気の場合はチャートの上側のトラックをマークします。
linecolor= 'green' if (Trend==1) else 'red'
ラインカラーの意味は、強気の場合は緑の線をマークし、弱気の場合は空の色をマークします(主に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では、フラグを反転した後にシグナルを出すことを意味します。
条件文を 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

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. バックテストとまとめ

バックテストのために過去 1 年間のデータを選択しました。
15 分周期の OKEX 四半期契約を使用します。
設定されたパラメータは、
Factor=3
Pd=45
vol=100 (1回の注文につき100枚のチケット)
年率換算の利回りは約33%です。
一般的に、リトレースメントはそれほど大きくありません。
その主な理由は、システムに大きな影響を与えた 312 クラッシュです。
312 がなければ、リターンはもっと良くなるでしょう。

img

6. 最後に

SuperTrendは非常に優れた取引システムです

SuperTrendシステムの主な原則は、ATRチャネルブレイクアウト戦略(ケントチャネルに類似)を使用することです。
しかし、主な変更点は、バンディット・ボリンジャー・ナローイング戦略、または逆ドンチャン原理の使用にあります。
市場操作中、上部チャネルと下部チャネルは常に狭くなっています。
チャネル突破と旋回動作を実現するため。 (チャネルが突破されると、上部レールと下部レールは初期値に戻ります)

私はTrendUp TrendDnをTradingViewで別々にプロットしました
これにより、この戦略をよりよく理解できるようになります

一目でわかる
img

github には js バージョンもあります。 js はよく分かりませんが、if 文から判断すると、何か問題があるようです。
住所はhttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

ついにオリジナル版を見つけました。
2013.05.29に公開されました
著者:Rajandran R
C++ コードが Mt4 フォーラムに公開されましたhttps://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4
C++ の意味は大体理解しているので、機会があれば書き直すつもりです。

皆さんもそこから本質を学んでいただければと思います。
それは難しい。 ~!

Related Recommendations
Comment
All comments (25)

    YYDS!

    5 years ago

    如果直接使用这个策略在OK交易所交易需要怎么连接交易所,小白一个不会python,看不明白

    6 years ago

    这里如果312那波行情没吃到的话应该参数还有很大的调整空间,因为supertrend主要就是抓趋势单,312是不应该错过的。另外期待lz的pine翻译器早日问世

    6 years ago

    可惜各种周期和参数,回测效果都不怎么好, 不知道其它人怎么优化的?

    6 years ago

    可以了,弄好了,感谢您的付出

    6 years ago

    用不了呢,显示这个:Traceback (most recent call last): File "<string>", line 1473, in Run File "<string>", line 8, in <module> ImportError: No module named pandas

    6 years ago

    意思是缺少pandas包 你的系统可能需要pip install pandas

    6 years ago

    请问这是怎么处理的呢?万分感谢

    6 years ago

    pine的翻译器,期待

    6 years ago

    没啥文化只能说一声 牛逼!

    6 years ago

    “估摸着某一天写一个pine的翻译器。一切皆可python。”—— 牛,好些人看好这个!

    6 years ago

    啊哈哈,谢谢老板

    6 years ago

    期待期待,pine真的看不太懂,教程也很少

    6 years ago

    回测引擎的代码是否可以开源呢,我想实现复现一下 然后用svm找出最好的参数

    6 years ago

    这个系统好像也曾经是收益率前十的期货策略。长期坚持做下去是能赚钱的。

    6 years ago

    恩啊。学习精髓。

    6 years ago

    你好,请教下,PD就是 ATR的长度值吧? 比如 ATR(14) ,就是 PD赋值14了吧?

    6 years ago

    是的,完全正确

    6 years ago

    好的,谢谢!!!
    顺手mq4也收走了,谢谢。。 o(∩_∩)o

    6 years ago

    感谢梦梦老师哈

    6 years ago

    碰巧我也写了个JS版本的。

    6 years ago

    求JS版!

    6 years ago

    一会儿,公开。

    6 years ago

    赞的,!

    6 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)