SuperTrend V.1 -- Sistem Garis Super Trend

Penulis:Lydia, Dibuat: 2022-12-01 11:36:33, Diperbarui: 2023-09-11 20:04:38

img

I. Asal-usul cerita

Tuan Ran, teman baik saya, telah mengamati indikator ini untuk waktu yang lama dan merekomendasikannya kepada saya sebelum Hari Tahun Baru untuk mendiskusikan apakah dapat dikonversi ke dalam kuantifikasi. Sangat disayangkan bahwa penunda telah menunda sampai sekarang untuk membantunya memenuhi keinginan seperti itu. Diperkirakan suatu hari nanti aku akan menulis penerjemah untuk bahasa Pine. Nah, tanpa banyak omong kosong, mari kita perkenalkan garis super trend legendaris.

II. Pengenalan Sistem

Dalam sistem perdagangan cerdas generasi baru di CMC Markets, kita dapat memilih Super Trend Line dari indikator teknis yang akan digunakan, Kita dapat menyesuaikan warna dan ketebalan dari sinyal meningkat dan menurun sesuai dengan preferensi kita sendiri. Jadi apa itu indikator super trend? Sebelum memahami rumus indikator super trend, perlu dipahami ATR, karena super trend mengadopsi nilai ATR untuk menghitung nilai indikator. Algoritma utama juga dijelaskan dalam gambar berikut:

img

Lihatlah secara singkat. Ini terutama menggambarkan saluran di mana HL2 (harga rata-rata garis k) ditambah n kali ATR. Buat terobosan tren. Tapi artikelnya sederhana. tidak ada algoritma rinci. lalu saya memikirkan komunitas yang paling luar biasa, TradingView. Memang, memang ada.

img

Melihat grafiknya, itu sesuai dengan tren.

III. Belajar kode sumber

Kode tidak terlalu panjang, jadi mari kita coba menerjemahkannya.!(っ•̀ω•́)っ))!

img

Kode pinus lengkap adalah seperti di atas.

VI. Konversi kode

Di sini kita membuat strategi baru di FMZ, menamainya sebagai SuperTrend

img

Selanjutnya, kita akan menetapkan dua parameter, Faktor dan Pd

img

Untuk lebih menyederhanakan operasi kode dan memfasilitasi pemahaman, kita perlu menggunakan paket ekspansi data canggih Python Pandas (https://pandas.pydata.org/) FMZ mendukung perpustakaan ini sekarang.

  1. Kita perlu mengimpor perpustakaan panda dan perpustakaan waktu
  2. Dalam fungsi utama, tetapkan penggunaan kontrak triwulanan (terutama untuk okex)
  3. Atur siklus doTicker untuk mendeteksi sekali setiap 15 menit. Jalankan kode pada periode 15 menit Kemudian kita menulis strategi utama di 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. Kita perlu mengambil OHCLV dari K-line, jadi kita menggunakan GetRecords()
  2. Kami mengimpor data yang diambil ke panda M15 = pd.DataFrame (rekaman)
  3. Kita perlu memodifikasi label header tabel. M15.kolom = [time,open,high,low,close,volume,OpenInterest] Sebenarnya, ini adalah untuk mengubah huruf awal dari open, high, low, dan close ke huruf kecil, sehingga tulisan kode kita nanti tidak perlu berubah dari huruf besar ke huruf kecil.
def doTicker(records):
    M15 = pd.DataFrame(records)
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  
  1. Tambahkan kolom ke set data hl2 hl2=(tinggi+rendah)/2
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
  1. Lalu mari kita hitung ATR Karena perhitungan ATR perlu mengimpor panjang variabel, yang nilainya adalah Pd

Kemudian kita merujuk ke manual MyLanguage, dan langkah algoritma dari nilai rata-rata amplitudo fluktuasi nyata 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 maksimum dari tiga perbedaan berikut

  1. Fluktuasi antara harga tertinggi dan harga terendah pada hari perdagangan saat ini
  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((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));

Dalam perhitungan Python

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

Kita perlu mengatur prev_close untuk mengambil data close di baris sebelumnya, yaitu, bergerak dekat ke kanan oleh satu kisi untuk membentuk parameter baru

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

Selanjutnya, kita mendefinisikan variabel menengah yang mencatat array dari 3 nilai kontras untuk TR. (HIGH-LOW) (high-prev_close) (low-prev_close)

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

Kita mendefinisikan kolom baru dalam set data dan menamainya sebagai TR. Nilai TR adalah nilai absolut terbesar dari variabel perantara, 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()

Akhirnya, kita perlu menghitung nilai ATR, ATR: RMA (TR, N). Ternyata algoritma RMA adalah varian nilai tetap algoritma EMA sebenarnya. N adalah variabel yang kita impor. parameter default ATR adalah 14.

===

Kemudian algoritma ewm digunakan untuk menghitung ema Proses perhitungan ATR lengkap 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 - ((Faktor * atr) Dn=hl2 +(Faktor * atr) Bukankah itu sederhana?

Ini adalah bagian kode inti dari baris 15-21 dari 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

Poin utama dari paragraf ini adalah untuk menyatakan bahwa, Jika berada dalam tahap bullish, (garis bawah) TrendUp=max (Up, TrendUp [1]) Jika berada di tahap jatuh, (garis atas) TrendDown=min (Dn, TrendDown [1]) Artinya, dalam tren, nilai ATR telah menggunakan teknologi yang mirip dengan strategi Bandit Bollinger. Tetap mempersempit sisi lain dari saluran

Di sini, setiap perhitungan TrendUp dan TrendDown membutuhkan iterasi diri. Artinya, setiap langkah harus dihitung sesuai dengan langkah sebelumnya. Oleh karena itu, set data harus diulang dalam loop.

Pertama, kita membuat bidang baru TrendUp, TrendDown, Trend, linecolor untuk set data. dan memberi mereka nilai awal Kemudian kita menggunakan tata bahasa fillna (0) untuk mengisi data dengan nilai nol dalam hasil yang dihitung 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)

Aktifkan loop for Menggunakan operasi ternar python dalam loop

    for x in range(len(M15)):

Menghitung TrendUp TrendUp = MAX(Up,TrendUp[-1]) jika dekat[-1]>TrendUp[-1] sebaliknya Up Ini kira-kira berarti bahwa jika penutupan sebelumnya>TrendUp sebelumnya benar, nilai maksimum antara Up dan TrendUp sebelumnya akan diambil; jika tidak, nilai Up akan diambil dan diteruskan 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, menghitung TrendDown TrendDown=min(Dn,TrendDown[-1]) jika dekat[-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 ini adalah bendera untuk menghitung arah kontrol. Trend= 1 jika (close > TrendDown[-1]) sebaliknya (x) x = -1 jika (dekat< TrendUp[-1]) sebaliknya Trend[-1]

Artinya adalah bahwa jika harga penutupan > TrendDown sebelumnya, ambil nilai 1 (bullish). Jika tidak, ambil nilai x Jika harga penutupan lebih rendah dari TrendUp sebelumnya, ambil nilai -1 (bearish). Jika tidak, ambil Trend sebelumnya (berarti tidak berubah) Untuk menerjemahkan ke dalam bahasa gambar adalah bahwa pecahnya bendera transisi jalur atas untuk bullish; dan pecahnya bendera transisi jalur bawah untuk bearish.

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

Menghitung Tsl dan Linecolor Tsl= rendUp jika (Trend==1) lain TrendDown Tsl adalah nilai yang digunakan untuk mewakili SuperTrend pada gambar. Ini berarti untuk menandai jalur ke bawah pada gambar ketika kita berada di bullish, dan menandai jalur atas pada gambar ketika kita berada di bearish. linecolor= hijau jika (Trend==1) sebaliknya merah Artinya linecolor adalah untuk menandai garis hijau jika kita berada di bullish, dan menandai warna kosong jika kita berada di bearish (terutama untuk tujuan tampilan Tradeview)

        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 baris kode berikutnya sebagian besar adalah gambar plot, yang tidak dijelaskan di sini.

Akhirnya ada 2 baris kode untuk mengontrol sinyal beli dan jual Dalam Tradeview, itu berarti bahwa sinyal diberikan setelah membalikkan Bendera Mengkonversi pernyataan bersyarat ke Python. Jika bendera Trend terakhir berubah dari -1 menjadi 1, itu berarti bahwa resistance atas telah melebihi dan membuka posisi panjang. Jika bendera Trend terakhir berubah dari 1 menjadi -1, itu berarti bahwa dukungan ke bawah telah melebihi dan membuka 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 lengkapnya 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

V. Kode lengkap

Aku menyesuaikan keseluruhan struktur kode. Dan saya menggabungkan instruksi order yang berkaitan dengan pergi panjang dan pergi pendek ke dalam strategi. Ini 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);

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

VI. Pengujian latar belakang dan ringkasan

Kami memilih data dari tahun lalu untuk backtesting. Kami menggunakan kontrak triwulanan OKEX untuk periode 15 menit. Parameter yang ditetapkan adalah: Faktor = 3 Pd=45 Vol=100 (100 kontrak untuk setiap pesanan) Pengembalian tahunan adalah sekitar 33%. Secara umum, penarikan tidak terlalu banyak, Penurunan tajam dari 312 memiliki dampak yang relatif besar pada sistem, Jika tidak ada 312, pengembalian harus lebih baik.

img

VII. Tulis di akhir

SuperTrend adalah sistem perdagangan yang sangat baik

Prinsip utama sistem SuperTrend adalah mengadopsi strategi terobosan saluran ATR (mirip dengan saluran Kent) Namun, perubahannya terutama disebabkan oleh penggunaan strategi penyempitan Bandit Bollinger, atau kebalikan dari prinsip Donchian. Dalam operasi pasar, saluran atas dan bawah terus menyempit. Untuk mencapai operasi kemudi terobosan saluran. (Setelah saluran menerobos, jalur atas dan bawah akan kembali ke nilai awal)

Saya memetakan, dn, TrendUp dan TrendDn secara terpisah pada TradeView, yang membuat lebih mudah untuk memahami strategi yang lebih baik. Lihatlah dengan jelas:

img

Selain itu, ada versi js di github. Saya tidak pandai dengan js, tapi sepertinya ada yang salah dengan pernyataan if. Alamatnya:https://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

Akhirnya, aku menemukan versi aslinya. Diterbitkan pada tanggal 29 Mei 2013 Penulisnya adalah Rajandran R. Kode C++ dipublikasikan di forum Mt4:https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4Saya telah memahami secara kasar arti C++, dan saya akan menulis ulang ketika saya memiliki kesempatan.

Kuharap kau bisa belajar esensinya darinya. Ini sulit.~!


Berkaitan

Lebih banyak