
Mein guter Freund Ran beobachtet diesen Indikator schon lange und hat ihn mir vor Neujahr empfohlen, um zu besprechen, ob er in eine quantitative Form umgewandelt werden kann. Leider habe ich unter Prokrastination gelitten und ihm bis jetzt nicht dabei geholfen, seinen Wunsch zu erfüllen. Tatsächlich habe ich in letzter Zeit große Fortschritte in meinem Verständnis von Algorithmen gemacht. Ich habe vor, eines Tages einen Pine-Übersetzer zu schreiben. Alles kann Python sein. . Okay, ohne weitere Umschweife möchten wir Ihnen diese legendäre Supertrendlinie vorstellen. .
Die neue Generation intelligenter Handelssysteme von CMC Markets - Supertrend
Hier ist ein Artikel, der dieses System vorstellt.

Wählen Sie in der neuen Generation intelligenter Handelssysteme von CMC Markets „Super Trend Line“ in den technischen Indikatoren aus, um es aufzurufen. Wie in der Abbildung gezeigt, können Sie die „Farbe und Dicke“ der steigenden und fallenden Signale nach Ihren Wünschen anpassen. Was also ist der Supertrendindikator? Bevor man die Formel des Supertrend-Indikators versteht, muss man ATR verstehen, da Supertrend ATR-Werte zur Berechnung der Indikatorwerte verwendet.
Der Hauptalgorithmus wird auch im Bild unten vorgestellt.

Auf den ersten Blick ist die Hauptbeschreibung ein Kanal von HL2 (Durchschnittspreis der K-Linie) multipliziert mit n-mal ATR. Machen Sie einen Trendausbruch.
Der Artikel ist jedoch ziemlich kurz. Es gibt keinen detaillierten Algorithmus. Dann dachte ich an die beste Community Tradingview.
Kein Wunder. Und tatsächlich, es ist da.

Der Grafik zufolge entspricht es durchaus dem Trend. Aber leider ist es nur ein Warnsignal.
Der Code sieht nicht zu lang aus, also übersetzen wir ihn und probieren es aus. ! (っ•̀ω•́)っ✎⁾⁾!
Der vollständige Pine-Code ist wie oben. .
Hier erstellen wir eine neue Strategie in FMZ und nennen sie SuperTrade

Als nächstes setzen wir zwei Parameter Faktor und Pd

Um die Funktionsweise des Codes zu vereinfachen und verständlicher zu machen, müssen wir das erweiterte Datenerweiterungspaket von Python verwendenpandas
Während des Mittagessens fragte ich Lehrerin Mengmeng, ob die FMZ diese Bibliothek unterstützt. Ich habe es am Nachmittag überprüft und es hat tatsächlich funktioniert. Lehrer Mengmeng ist wirklich unglaublich.
1. Wir müssen die Pandas-Bibliothek Zeitbibliothek importieren 2. Richten Sie den Quartalsvertrag in der Hauptfunktion ein (hauptsächlich OKEX ausführen) 3. Richten Sie eine doTicker()-Schleife ein, um alle 15 Minuten einen Test durchzuführen. Führen Sie den Code im 15-Minuten-Zyklus aus Als nächstes schreiben wir die Hauptstrategie in 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. Wir müssen den OHCLV der K-Linie abrufen, also verwenden wir GetRecords() 5. Wir importieren die abgerufenen Daten in Pandas M15 = pd.DataFrame(Datensätze) 6. Wir müssen das Tabellenkopf-Tag ändern. M15.Spalten =[‘time’,‘open’,‘high’,‘low’,‘close’,‘volume’,‘OpenInterest’] Tatsächlich werden dabei nur die Anfangsbuchstaben von „open“, „high“, „low“ und „close“ in Kleinbuchstaben geändert, damit sich später Code leichter schreiben lässt, ohne zwischen Groß- und Kleinschreibung wechseln zu müssen.
def doTicker(records):
M15 = pd.DataFrame(records)
M15.columns = ['time','open','high','low','close','volume','OpenInterest']
7. Fügen Sie dem Datensatz hl2=(high+low)/2 eine Spalte hl2 hinzu
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
8. Als nächstes berechnen wir den ATR Da die Berechnung von ATR den Import einer variablen Länge erfordert, ist ihr Wert Pd
Dann verweisen wir auf das Mai-Sprachhandbuch, und die Algorithmusschritte des ATR-Durchschnitts der wahren Volatilität lauten wie folgt: TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR : RMA(TR,N)
Der TR-Wert ist der größte der folgenden drei Unterschiede. 1. Die Schwankung zwischen dem Höchstkurs und dem Tiefstkurs des aktuellen Handelstages HIGH-LOW 2. Die Schwankung zwischen dem Schlusskurs des vorherigen Handelstages und dem Höchstkurs des aktuellen Handelstages (REF(CLOSE,1)-HIGH) 3. Die Schwankung zwischen dem Schlusskurs des vorherigen Handelstages und dem niedrigsten Kurs des aktuellen Handelstages (REF(CLOSE,1)-LOW) Also TR: MAX(MAX((HOCH-NIEDRIG),ABS(REF(SCHLUSS,1)-HOCH)),ABS(REF(SCHLUSS,1)-NIEDRIG));
In Python-Berechnungen
M15['prev_close']=M15['close'].shift(1)
Richten Sie zunächst ein prev_close ein, um die Daten von close in der vorherigen Zeile abzurufen, d. h., verschieben Sie close um 1 Raster nach rechts, um einen neuen Parameter zu bilden
ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
Definieren Sie als Nächstes eine Zwischenvariable, um das Array der drei Vergleichswerte von TR aufzuzeichnen. (HOCH-NIEDRIG)(hoch-vorherig_schließen)(niedrig-vorherig_schließen)
M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
Wir definieren eine neue Spalte namens TR im Datensatz. Der Wert von TR ist der maximale absolute Wert der Zwischenvariable. Wir verwenden die Funktionen abs() und max().
alpha = (1.0 / length) if length > 0 else 0.5
M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()
Schließlich müssen wir den Wert von ATR berechnen, ATR: RMA (TR, N). Es stellt sich heraus, dass der RMA-Algorithmus tatsächlich eine Festwertvariante des EMA-Algorithmus ist. N ist die von uns importierte Variable, wobei der Standardparameter für ATR 14 ist. Hier importieren wir Alpha = den Kehrwert der Länge.
===
Verwenden Sie dann den EWM-Algorithmus zur Berechnung des EMA Der vollständige ATR-Berechnungsprozess läuft wie folgt ab
#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 Beginnen Sie mit der Berechnung von Up und Dn
M15['Up']=M15['hl2']-(Factor*M15['atr'])
M15['Dn']=M15['hl2']+(Factor*M15['atr'])
Up=hl2 -(Factor * atr) Dn=hl2 +(Factor * atr) Ist es nicht einfach?
Nachfolgend sehen Sie den Kerncodeabschnitt der Zeilen 15-21 in 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
Der Hauptzweck dieses Absatzes besteht darin, auszudrücken, Wenn in einer bullischen Phase, (untere Linie) TrendUp = max(Up,TrendUp[1]) Wenn es sich in der fallenden Phase befindet (obere Linie), TrendDown=min(Dn,TrendDown[1]) Das heißt, in einem Trend hat der ATR-Wert eine Technik verwendet, die der Bandit-Bollinger-Strategie ähnelt. Verengen Sie die andere Seite des Kanals weiter
Hier muss jede Berechnung von TrendUp und TrendDown selbst iteriert werden. Das heißt, jeder Schritt muss auf Grundlage des vorherigen Schritts berechnet werden. Wir müssen also den Datensatz durchlaufen.
Hier müssen wir zunächst die neuen Felder TrendUp, TrendDown, Trend und Linienfarbe für den Datensatz erstellen. Und geben Sie ihnen einen Anfangswert Verwenden Sie dann die Syntax fillna(0), um die Daten mit Nullwerten in den zuvor berechneten Ergebnissen mit 0 zu füllen
M15['TrendUp']=0.0
M15['TrendDown']=0.0
M15['Trend']=1
M15['Tsl']=0.0
M15['linecolor']='Homily'
M15 = M15.fillna(0)
Starten Sie eine For-Schleife Verwenden ternärer Python-Operationen in Schleifen
for x in range(len(M15)):
TrendUp berechnen TrendUp = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up Die allgemeine Bedeutung ist: Wenn der vorherige Schlusswert > der vorherige TrendUp ist, wird, wenn dies zutrifft, der Maximalwert von Up und dem vorherigen TrendUp genommen, wenn dies nicht zutrifft, wird der Up-Wert genommen und an den aktuellen TrendUp übergeben
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]
Berechnen Sie in ähnlicher Weise 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]
Unten ist das Flag zur Berechnung der Steuerrichtung. Ich habe den Pseudocode vereinfacht Trend= 1 if (close > TrendDown[-1]) else (x) x = -1 if (close< TrendUp[-1]) else Trend[-1]
Die Bedeutung ist, dass wenn der Schlusskurs > dem vorherigen TrendDown ist, dann 1 (bullisch) genommen wird, wenn nicht, dann x genommen wird. Wenn der Schlusskurs unter dem vorherigen TrendUp liegt, nehmen Sie -1 (Short). Wenn nicht, nehmen Sie den vorherigen Trend (was bedeutet, dass er unverändert bleibt). Grafisch übersetzt bedeutet dies, dass ein Durchbrechen der oberen Schiene die Flagge auf bullisch umstellt, ein Durchbrechen der unteren Schiene die Flagge auf bärisch umstellt und die übrigen Zeitpunkte unverändert bleiben.
M15['Tsl'].values[x] = M15['TrendUp'].values[x] if (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
TSL und Linienfarbe berechnen Tsl= rendUp if (Trend==1) else TrendDown Tsl wird verwendet, um den Wert von SuperTrend im Diagramm darzustellen. Dies bedeutet: Wenn Sie optimistisch sind, markieren Sie die untere Spur im Diagramm, und wenn Sie pessimistisch sind, markieren Sie die obere Spur im Diagramm. linecolor= ‘green’ if (Trend==1) else ‘red’ Die Bedeutung der Linienfarbe ist: Wenn Sie bullisch sind, markieren Sie die grüne Linie, wenn Sie bearisch sind, markieren Sie die leere Farbe (hauptsächlich für die Tradingview-Anzeige verwendet)
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'
Die folgenden Zeilen 23-30 dienen hauptsächlich dem Plotten und werden hier nicht näher erläutert.
Schließlich gibt es noch 2 Codezeilen für die Kauf- und Verkaufssignalsteuerung In Tradingview bedeutet dies, nach dem Umkehren der Flagge ein Signal zu geben. Konvertieren Sie bedingte Anweisungen in Python. Wenn sich das vorherige Trend-Flag von -1 auf 1 ändert, bedeutet dies, dass der obere Widerstand durchbrochen wurde. Öffnen Sie eine Long-Position. Wenn sich die vorherige Trendflagge von 1 auf -1 ändert, bedeutet dies, dass die Abwärtsunterstützung durchbrochen wurde. Eröffnen Sie eine Short-Position.
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)
Der vollständige Code für diesen Abschnitt lautet wie folgt:
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)


Ich habe die gesamte Codestruktur angepasst. Und integrieren Sie die Long- und Short-Order-Anweisungen in die Strategie. Hier ist der komplette Code
'''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);
Öffentlicher Strategielink: https://www.fmz.com/strategy/200625
Für das Backtesting haben wir Daten aus dem vergangenen Jahr ausgewählt. Verwenden Sie den OKEX-Quartalsvertrag mit einem 15-Minuten-Zyklus. Die festgelegten Parameter sind: Factor=3 Pd=45 vol=100 (100 Tickets pro Bestellung) Die annualisierte Rendite beträgt ca. 33 %. Im Allgemeinen ist die Korrektur nicht sehr groß. Der Hauptgrund hierfür ist der Absturz der 312, der erhebliche Auswirkungen auf das System hatte. Wenn es die Nummer 312 nicht gäbe, wäre die Rendite besser.

SuperTrend ist ein sehr gutes Handelssystem
Das Hauptprinzip des SuperTrend-Systems besteht in der Verwendung der ATR-Kanal-Ausbruchsstrategie (ähnlich dem Kent-Kanal). Die wichtigste Änderung liegt jedoch in der Verwendung der Bandit-Bollinger-Verengungsstrategie bzw. des umgekehrten Donchian-Prinzips. Die oberen und unteren Kanäle verengen sich während der Marktoperation ständig. Um den Kanaldurchbruch und die Drehoperation zu erreichen. (Sobald der Kanal durchbricht, kehren die oberen und unteren Schienen zu ihren Anfangswerten zurück)
Ich habe dn TrendUp TrendDn separat auf TradingView dargestellt
Dies wird Ihnen helfen, diese Strategie besser zu verstehen
Übersichtlich auf einen Blick

Es gibt auch eine JS-Version auf GitHub. Ich verstehe nicht viel von JS, aber der if-Anweisung nach zu urteilen, scheint es da ein Problem zu geben. Die Adresse lautethttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js
Endlich habe ich die Originalversion gefunden. Es wurde am 29.05.2013 veröffentlicht Geschrieben von Rajandran R C++-Code im Mt4-Forum veröffentlichthttps://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4 Ich verstehe die Bedeutung von C++ im Großen und Ganzen und werde es neu schreiben, wenn ich die Gelegenheit dazu habe.
Ich hoffe, dass jeder das Wesentliche daraus lernen kann. Es ist schwierig. ~!