
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. .
Sistem perdagangan cerdas generasi baru dari CMC Markets - Supertrend
Berikut adalah artikel yang memperkenalkan sistem ini.

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.

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.

Dilihat dari grafiknya, cukup konsisten dengan tren. Namun sayangnya itu hanya sinyal Peringatan.
Kodenya tidak terlihat terlalu panjang, jadi mari kita terjemahkan dan mencobanya. ! (っ•̀ω•́)っ✎⁾⁾!
Kode pine lengkapnya seperti di atas. .
Di sini kami membuat strategi baru di FMZ dan menamakannya SuperTrade

Selanjutnya kita atur dua parameter Faktor dan Pd

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


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

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

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. ~!