Type/to search
0
Follow
48
Followers
SuperTrend V.1--Sistem Garis Tren Super
Original
Created 2020-04-20 22:10:36  Updated 2024-12-12 21:03:30
 28
 12333

img

1. Asal usul cerita

Teman baik saya Ran telah mengamati indikator ini sejak lama dan merekomendasikannya kepada saya sebelum Tahun Baru untuk membahas apakah indikator ini dapat diubah ke dalam bentuk kuantitatif.
Sayangnya, saya suka menunda-nunda dan belum membantunya memenuhi keinginannya hingga sekarang. Padahal, pemahaman saya tentang algoritma telah mengalami kemajuan pesat akhir-akhir ini.
Saya berencana untuk menulis penerjemah pinus suatu hari nanti. Semuanya bisa menjadi python. .
Oke, tanpa basa-basi lagi, mari kita perkenalkan lini tren super legendaris ini. .

2. Pengenalan Sistem

Sistem perdagangan cerdas generasi baru dari CMC Markets - Supertrend
Berikut adalah artikel yang memperkenalkan sistem ini.
img

Pada sistem perdagangan cerdas generasi baru di CMC Markets, pilih "Super Trend Line" pada indikator teknis untuk memanggilnya.
Seperti yang ditunjukkan pada gambar, Anda dapat menyesuaikan "warna dan ketebalan" sinyal naik dan turun sesuai dengan preferensi Anda.
Jadi apa itu indikator supertrend? Sebelum memahami rumus indikator supertrend, perlu dipahami terlebih dahulu ATR, karena supertrend menggunakan nilai ATR untuk menghitung nilai indikatornya.

Algoritma utama juga diperkenalkan dalam gambar di bawah.
img

Sekilas, deskripsi utamanya adalah saluran HL2 (harga rata-rata K-line) dikalikan n kali ATR. Buat terobosan tren.
Namun artikelnya agak singkat. Tidak ada algoritma yang terperinci. Lalu saya teringat komunitas terbaik Tradingview.
Tidak mengherankan. Benar saja, itu ada.
img

Dilihat dari grafiknya, cukup konsisten dengan tren. Namun sayangnya itu hanya sinyal Peringatan.

3. Pelajari kode sumbernya

Kodenya tidak terlihat terlalu panjang, jadi mari kita terjemahkan dan mencobanya. ! (っ•̀ω•́)っ✎⁾⁾!
img
Kode pine lengkapnya seperti di atas. .

4. Konversi Kode

Di sini kami membuat strategi baru di FMZ dan menamakannya SuperTrade
img

Selanjutnya kita atur dua parameter Faktor dan Pd
img

Untuk lebih menyederhanakan pengoperasian kode dan membuatnya lebih mudah dipahami, kita perlu menggunakan paket ekspansi data lanjutan Pythonpandas

Saat makan siang, saya bertanya kepada Guru Mengmeng apakah FMZ mendukung perpustakaan ini. Saya memeriksanya di sore hari dan ternyata berfungsi.
Guru Mengmeng sungguh hebat.

1. Kita perlu mengimpor pustaka pandas time library
2. Siapkan kontrak triwulanan di fungsi utama (terutama menjalankan OKEX)
3. Atur loop doTicker() untuk menguji sekali setiap 15 menit.
Jalankan kode pada siklus 15 menit
Berikutnya kita menulis strategi utama dalam 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. Kita perlu mengambil OHCLV dari K-line, jadi gunakan GetRecords()
5. Kami mengimpor data yang diambil ke pandas M15 = pd.DataFrame(records)
6. Kita perlu memodifikasi tag header tabel. M15.kolom =['time','open','high','low','close','volume','OpenInterest']
Faktanya, ia hanya mengubah huruf pertama dari 'open', 'high', 'low', dan 'close' menjadi huruf kecil, sehingga lebih mudah dalam penulisan kode nantinya tanpa perlu berganti-ganti antara huruf besar dan kecil.

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

7. Tambahkan kolom hl2 ke kumpulan data hl2=(tinggi+rendah)/2

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

8. Selanjutnya, mari kita hitung ATR
Karena perhitungan ATR memerlukan impor panjang variabel, nilainya adalah Pd

Kemudian kita merujuk ke manual bahasa Mai, dan langkah-langkah algoritma rata-rata volatilitas sejati ATR adalah sebagai berikut:
TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));
ATR : RMA(TR,N)

Nilai TR adalah yang terbesar dari tiga perbedaan berikut.

  1. Fluktuasi antara harga tertinggi dan harga terendah pada hari perdagangan saat ini HIGH-LOW
  2. Fluktuasi antara harga penutupan hari perdagangan sebelumnya dan harga tertinggi hari perdagangan saat ini (REF(CLOSE,1)-HIGH)
  3. Fluktuasi antara harga penutupan hari perdagangan sebelumnya dan harga terendah hari perdagangan saat ini (REF(CLOSE,1)-LOW)
    Jadi TR : MAX(MAX((TINGGI-RENDAH),ABS(REF(TUTUP,1)-TINGGI)),ABS(REF(TUTUP,1)-RENDAH));

Dalam perhitungan Python

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

Pertama, atur prev_close untuk mendapatkan data penutupan di baris sebelumnya, yaitu, pindahkan tutup ke kanan sebanyak 1 grid untuk membentuk parameter baru

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

Berikutnya, tentukan variabel antara untuk mencatat susunan tiga nilai perbandingan TR. (TINGGI-RENDAH)(tinggi-sebelumnya_tutup)(rendah-sebelumnya_tutup)

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

Kami mendefinisikan kolom baru bernama TR dalam kumpulan data. Nilai TR adalah nilai absolut maksimum dari variabel antara. Kami menggunakan fungsi abs() dan max().

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

Terakhir, kita perlu menghitung nilai ATR, ATR: RMA (TR, N). Berdasarkan penyelidikan, algoritma RMA sebenarnya merupakan varian nilai tetap dari algoritma EMA.
N adalah variabel yang kita impor, di mana parameter default untuk ATR adalah 14. Di sini kita mengimpor alpha = kebalikan dari panjang.

===

Kemudian gunakan algoritma EWM untuk menghitung EMA
Proses perhitungan ATR lengkapnya adalah sebagai berikut

#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 Mulai menghitung Up dan Dn

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

Up=hl2 -(Factor * atr)
Dn=hl2 +(Factor * atr)
Bukankah itu sederhana?

Berikut ini adalah segmen kode inti baris 15-21 di TV

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

Tujuan utama dari paragraf ini adalah untuk mengungkapkan,
Jika dalam fase bullish, (garis bawah) TrendUp = max(Naik,TrenNaik[1])
Jika dalam tahap jatuh, (garis atas) TrendDown=min(Dn,TrendDown[1])
Dengan kata lain, dalam suatu tren, nilai ATR telah menggunakan teknik yang mirip dengan strategi Bandit Bollinger.
Terus persempit sisi lain salurannya

Di sini, setiap perhitungan TrendUp dan TrendDown perlu diulang sendiri.
Artinya, setiap langkah harus dihitung berdasarkan langkah sebelumnya.
Jadi, kita perlu mengulang rangkaian data tersebut.

Di sini pertama-tama kita perlu membuat bidang baru TrendUp, TrendDown, Trend, dan linecolor untuk kumpulan data. Dan beri mereka nilai awal
Kemudian gunakan sintaks fillna(0) untuk mengisi data dengan nilai null pada hasil perhitungan sebelumnya dengan 0

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

Memulai perulangan for
Menggunakan operasi terner Python dalam loop

for x in range(len(M15)):

Menghitung TrendUp
TrendUp = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up
Makna umumnya adalah jika penutupan sebelumnya > TrendUp sebelumnya, jika benar, ambil nilai maksimum Naik dan TrendUp sebelumnya, jika tidak benar, ambil nilai Naik dan teruskan ke TrendUp saat ini.

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]

Demikian pula, hitung TrendDown
TrendDown=min(Dn,TrendDown[-1]) if close[-1]<TrendDown[-1] else Dn
Makna umumnya adalah jika penutupan sebelumnya < TrendDown sebelumnya, jika benar, ambil nilai minimum antara Dn dan TrendDown sebelumnya, jika tidak benar, ambil nilai Dn dan teruskan ke TrendDown saat ini.

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]

Berikut adalah bendera untuk menghitung arah kontrol. Saya menyederhanakan kode semu
Trend= 1 if (close > TrendDown[-1]) else (x)
x = -1 if (close< TrendUp[-1]) else Trend[-1]

Artinya jika harga penutupan lebih besar dari TrendDown sebelumnya maka ambil 1 (bullish) dan jika tidak maka ambil x
Jika harga penutupan lebih rendah dari TrendUp sebelumnya, maka ambil -1 (short). Jika tidak, ambil Trend sebelumnya (yang berarti tidak berubah).
Bila diterjemahkan ke bahasa grafis, artinya menerobos rel atas untuk mengganti bendera menjadi bullish, menerobos rel bawah untuk mengganti bendera menjadi bearish, dan waktu-waktu lainnya tetap tidak berubah.

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

Hitung TSL dan Linecolor
Tsl= rendUp if (Trend==1) else TrendDown
Tsl digunakan untuk mewakili nilai SuperTrend pada grafik. Artinya, bila Anda bersikap bullish, tandai jalur paling bawah pada grafik, dan bila Anda bersikap bearish, tandai jalur paling atas pada grafik.
linecolor= 'green' if (Trend==1) else 'red'
Arti dari linecolor adalah jika anda bullish, tandai garis hijau, jika anda bearish, tandai warna kosong (terutama digunakan untuk tampilan 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'

Baris berikutnya 23-30 terutama untuk perencanaan, yang tidak akan dijelaskan secara rinci di sini.

Terakhir, ada 2 baris kode untuk membeli dan menjual kontrol sinyal
Dalam Tradingview, artinya memberi sinyal setelah membalikkan Bendera.
Ubah pernyataan kondisional ke python.
Jika bendera Tren sebelumnya berubah dari -1 ke 1, itu berarti resistensi atas telah ditembus. Buka posisi beli
Jika bendera Tren sebelumnya berubah dari 1 ke -1, itu berarti support ke bawah telah ditembus. Buka posisi short.

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)

Kode lengkap untuk bagian ini adalah sebagai berikut:

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. Semua kode

Saya menyesuaikan struktur kode keseluruhan.
Dan gabungkan instruksi order terkait panjang dan pendek ke dalam strategi.
Berikut kode lengkapnya

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

Tautan strategi publik: https://www.fmz.com/strategy/200625

6. Backtesting dan Ringkasan

Kami memilih data dari tahun lalu untuk pengujian ulang.
Gunakan kontrak triwulanan OKEX dengan siklus 15 menit.
Parameter yang ditetapkan adalah,
Factor=3
Pd=45
vol=100 (100 tiket per pesanan)
Pengembalian tahunan sekitar 33%.
Secara umum, penelusuran kembali tidak terlalu besar.
Alasan utamanya adalah crash 312 yang berdampak signifikan pada sistem.
Kalau tidak ada 312, hasilnya akan lebih baik.

img

6. Pemikiran Akhir

SuperTrend adalah sistem perdagangan yang sangat bagus

Prinsip utama sistem SuperTrend adalah menggunakan strategi breakout saluran ATR (mirip dengan saluran Kent)
Namun perubahan utama terletak pada penggunaan strategi penyempitan Bandit Bollinger, atau prinsip Donchian terbalik.
Saluran atas dan bawah terus menyempit selama operasi pasar.
Untuk mencapai terobosan saluran dan operasi pembubutan. (Setelah saluran tersebut menerobos, rel atas dan bawah kembali ke nilai awalnya)

Saya memplot dn TrendUp TrendDn secara terpisah di TradingView
Ini akan membantu Anda lebih memahami strategi ini

Jelas sekilas
img

Ada juga versi js di github. Saya tidak begitu paham js, tetapi dilihat dari pernyataan if, tampaknya ada masalah.
Alamatnya adalahhttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

Akhirnya saya menemukan versi aslinya.
Diterbitkan pada 29/5/2013
Ditulis oleh Rajandran R
Kode C++ dipublikasikan di forum Mt4https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4
Saya kira-kira mengerti arti C++ dan akan menulis ulang ketika saya punya kesempatan.

Saya harap semua orang dapat mengambil intisarinya.
Sulit. ~!

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
Forums
PINE Language
Get the app
iPhone Download
© 2015 - ∞ INVENTOR PTE LTD (SG)