SuperTrend V.1 - Système de ligne de tendance supérieure

Auteur:l' homélie, Créé: 2020-04-20 22:10:36, Mis à jour: 2023-10-08 19:57:57

img

Premièrement, le récit

Mon bon ami Vago a observé l'indicateur pendant longtemps et me l'a recommandé avant le Nouvel An pour discuter de sa conversion en quantification. Malheureusement, la procrastination a pris le relais et a été retardée jusqu'à présent pour lui permettre de réaliser ce souhait, en fait, la compréhension de l'algorithme a explosé récemment. J'espère écrire un jour un traducteur en pin. Tout est en python. Pour ne pas dire trop de bêtises, nous allons vous présenter les super tendances de cette légende.

Deuxièmement, une introduction au système

CMC Markets est une nouvelle génération de système de trading intelligent.Un article sur ce système est disponible ici.img

Dans la nouvelle génération de systèmes de négociation intelligents de CMC Markets, le réglage de la ligne de tendance super-trend peut être utilisé pour sélectionner des indicateurs techniques, et il est possible de les utiliser pour les autres indicateurs. Comme indiqué dans le graphique, vous pouvez ajuster la couleur de l'aiguille et la finesse de l'aiguille en fonction de vos préférences pour les signaux ascendants et descendants. Avant de comprendre la formule de l'indicateur d'ultra-trend, il est nécessaire de comprendre l'ATR, car l'ultra-trend utilise la valeur de l'ATR pour calculer la valeur de l'indicateur.

Les principaux algorithmes sont présentés ci-dessous.img

En gros, la description principale est celle de HL2 (la valeur moyenne de la ligne k) multipliée par n fois le canal ATR. Mais l'article est relativement simple. Il n'y a pas d'algorithmes détaillés. Il y en a bien au-dessus.img

Le graphique montre une tendance plus ou moins correcte. Malheureusement, il s'agit d'un signal d'alarme d'Alert.

Troisièmement, apprendre le code source

Si le code n'est pas trop long, alors nous allons essayer de le traduire.imgLe code pin complet est ci-dessous.

Quatre, le code est transformé.

Ici, nous avons créé une nouvelle stratégie sur FMZ, appelée SuperTrade.img

Ensuite, nous allons définir deux paramètres Factor, Pd.img

Pour mieux simplifier les opérations du code et le rendre plus compréhensible, on utilise les extensions de données avancées de Python.les pandas

Au déjeuner, j'ai demandé à mon professeur si FMZ soutenait cette bibliothèque. Le professeur de rêve est vraiment génial.

1.我们要导入pandas库time库 2.在main函数当中设置使用季度合约(主要跑okex) 3. Configurez un cycle de doTicker pour 15 minutes de détection une fois.Je suis en train d'exécuter le code sur des cycles de 15 minutes. Ensuite, nous avons écrit les principales stratégies dans 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. nous allons prendre le OHCLV de la ligne k, alors nous allons utiliser GetRecords. 5. Nous allons importer les données récupérées dans panda M15 = pd.DataFrame ((records) 6. Nous voulons modifier les balises de tête de la table. M15.columns = [balises de temps, balises d'ouverture, balises de hauteur, balises de bas, balises de proximité, balises de volume, balises d'OpenInterest]En fait, il s'agit de changer les premières lettres de "open", "high", "low", "close" en minuscules, pour faciliter l'écriture ultérieure du code.

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

7. Ajouter une colonne à la collection de données: hl2 hl2 = ((high+low) /2)

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

8.接着我们来计算ATRParce que l'ATR doit importer une longueur de variable, sa valeur est Pd

Ensuite, en consultant le manuel de la langue Ma, nous pouvons voir les étapes de l'algorithme pour obtenir la moyenne de l'amplitude réelle de l'ATR: TR: MAX (en anglais seulement): MAX (en anglais seulement): HIGH-LOW, ABS (en anglais seulement): REF (en anglais seulement): CLOSE, 1) -HIGH); ATR: RMA (TR,N)

La valeur TR est la plus grande des trois valeurs inférieures. 1, la fourchette HIGH-LOW entre le prix le plus élevé et le prix le plus bas de la journée en cours 2 ̊ Largeur de l'écart entre le prix de clôture de la journée précédente et le prix le plus élevé de la même journée REF ((CLOSE, 1) -HIGH) 3 ̊ Largeur entre le prix de clôture de la journée précédente et le prix le plus bas de la même journée REF ((CLOSE, 1) - LOW) Donc TR: MAX (depuis MAX (depuis haut bas), ABS (depuis REF (depuis CLOSE, 1) - haut)), ABS (depuis REF (depuis CLOSE, 1) - bas));

Dans le calcul Python

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

Pour obtenir les données de la ligne précédente, vous devez d'abord configurer un paramètre pré_close, c'est-à-dire déplacer la grille de 1 à droite pour créer un nouveau paramètre.

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

Ensuite, définissez une variable intermédiaire.

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

Nous avons défini une nouvelle colonne nommée TR dans un ensemble de données, la valeur de TR est la plus grande valeur absolue de la variable intermédiaire, en utilisant les fonctions abs (()) et max (()).

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

Enfin, nous devons calculer la valeur de l'ATR, ATR: RMA ((TR,N), selon laquelle l'algorithme de l'RMA est en fait un algorithme EMA à valeur fixe variable. N est la variable que nous importons, dont le paramètre par défaut de l'ATR est 14.

===

On utilise ensuite l'algorithme ewm pour calculer l'ema.Le processus complet de calcul de l'ATR est le suivant:

    #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 Compte à rebours de Up et Dn

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

Up = hl2 - ((Facteur * atr) Dn = hl2 + ((facteur * atr)) Il y a des gens qui se demandent si c'est facile.

Ci-dessous, le code de base de 15 à 21 lignes.

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

Le but principal de ce passage est d'exprimer que les gens ne sont pas les seuls à avoir besoin d'aide. Si vous êtes dans la phase de hausse, alors la ligne inférieure (TrendUp) = max (Up, TrendUp[1]) Si la tendance est à la baisse, alors la tendance est à la baisse (ligne supérieure)C'est-à-dire qu'au cours d'une tendance, la valeur de l'ATR a toujours été utilisée avec une technique similaire à la stratégie du brainwashing des pirates. Il a continué à se rétrécir de l'autre côté du tunnel.

Dans ce cas, les calculs de TrendUp et TrendDown nécessitent une auto-irritabilité à chaque fois. Il y a une autre façon de faire les choses, c'est de prendre chaque étape pour calculer la précédente. C'est pourquoi il est nécessaire de faire un parcours en boucle sur les données.

Ici, vous devez créer de nouveaux champs pour la collection de données: TrendUp, TrendDown, Trend, linecolor et leur donner une valeur initiale. La syntaxe fillna ((0) est ensuite utilisée pour remplir les données avec des valeurs vides dans les résultats calculés précédemment.

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

Activer une boucle for L'utilisation de la troisième opération de Python dans le cycle

    for x in range(len(M15)):

Calculer le TrendUpTrendUp = MAX ((Up,TrendUp[-1]) si près [-1]>TrendUp[-1] ailleurs En haut Ce qui signifie que si la dernière close> la dernière TrendUp, la plus grande valeur de la prise de tendance et la dernière TrendUp, ne sont pas prises de tendance et sont transmises à la tendance actuelle

        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]

Parallèlement, calculer le TrendDownTrendDown=min ((Dn, TrendDown[-1]) si 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]

En dessous, il y a le drapeau qui calcule la direction du contrôle, et j'ai simplifié le pseudo-code.Tendance = 1 si (close > TrendDown[-1]) autrement (x) x = -1 si (close< TrendUp[-1]) autrement Tendance[-1]

Cela signifie que si le prix de clôture > le dernier TrendDown, prendre 1 (voir plus) ne fonctionne pas prendre x. Si le prix de clôture est < le dernier TrendUp, prenez -1 (le vide) n'est pas établi prenez une tendance (ce qui signifie qu'il n'y a pas de changement) La traduction en langage d'images est de briser le drapeau de conversion en train de lire plus, de briser le drapeau de conversion en train de lire moins, le reste du temps ne change pas.

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

Calculer Tsl et LinecolorTsl = rendUp if (Trend==1) else Tendance en bas Tsl est utilisé pour indiquer la valeur de la SuperTrend sur une image. Cela signifie que la tendance est marquée sur le graphique lorsque vous regardez plus, et la tendance est marquée sur le graphique lorsque vous regardez moins. Linecolor= vert pâle if (Trend==1) else rouge pâle La signification de linecolor est marquée en vert si vous lisez plus, en blanc si vous regardez moins (principalement utilisé pour l'affichage 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'

Les lignes de code suivantes, 23 à 30, sont principalement des diagrammes de plots, ce qui n'est pas expliqué ici.

Enfin, il y a deux lignes de code pour contrôler les signaux d'achat et de vente.Dans Tradingview, il signifie que le signal est donné après avoir inversé le drapeau Convertissez les statements conditionnels en python. Si le précédent drapeau de tendance passe de -1 à 1, cela signifie que la résistance supérieure est dépassée. Si le précédent drapeau de tendance passe de 1 à -1, cela représente une rupture avec le support en aval.

    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)

Le code complet est le suivant:

    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

Cinquièmement, tout le code

J'ai modifié l'ensemble de la structure du code. Les instructions relatives à l'augmentation du nombre de postes vacants seront intégrées à la stratégie. Voici le code complet.

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

Les liens vers les stratégies publiques: https://www.fmz.com/strategy/200625

6 - Révision et résumé

Nous avons sélectionné des données de près d'un an pour une analyse. Utilisez le cycle de 15 minutes du contrat trimestriel okx. Les paramètres sont les suivants: Le facteur est 3. Pd est égal à 45. Vol = 100 (envoyez 100 commandes à la fois) Les bénéfices annuels, environ 33%. Le retrait n'a pas été très important dans l'ensemble. La baisse de 312 a été la plus importante, mais elle a eu un impact sur le système. Les bénéfices devraient être meilleurs s'il n'y avait pas de 312.

img

Six, écrit à la fin

SuperTrend est un très bon système de trading.

Le principe principal du système SuperTrend est d'utiliser une stratégie de rupture du canal ATR (similaire au canal de Kent) Mais le changement est principalement lié à l'utilisation de la stratégie de contraction du brigand Brin, ou le principe inverse de Donchian. Le gouvernement a décidé d'arrêter la vente de cigarettes et de réduire le nombre de cigarettes. Pour atteindre l'opération de virage de rupture de canal,.. (une fois le canal brisé, les voies supérieures et inférieures sont restaurées à leur valeur initiale)

J'ai tracé le up dn TrendUp dans TradingView et j'ai vu que le up dn TrendUp est un graphique de la tendance. Cela nous aide à mieux comprendre cette stratégie.Je suis désolé.img

Il y a aussi une version de js sur github. Je ne sais pas très bien, mais il y a un problème avec la syntaxe if. L'adresse esthttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

J'ai finalement cherché l'original. Il a été publié le 29.05.2013. Auteur Rajandran R. Le code C++ est publié sur le forum Mt4https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4J'ai une bonne compréhension de C++ et j'ai l'occasion de réécrire un autre.

J'espère que tout le monde peut en tirer des leçons. Il est difficile d'arrêter de fumer!


Relationnée

Plus de

- Je ne sais pas.Ça y est!

Je suis désolée.Si vous utilisez cette stratégie directement dans les transactions d'échanges OK, vous devez savoir comment connecter les échanges, le petit blanc ne fonctionnera pas Python, ce qui est difficile à comprendre

les garde-corpsIci, si la vague de 312 n'a pas été mangée, il devrait y avoir beaucoup de marge de manœuvre, car le supertrend est principalement une liste de tendances, le 312 ne doit pas être manqué.

Je ne peux pas.Malheureusement, les cycles et les paramètres ne fonctionnent pas très bien, je ne sais pas comment les autres ont optimisé.

Il est gros.C'est fait, c'est fait, merci pour votre aide.

Il est gros.Si vous n'êtes pas d'accord, ceci s'affiche: Traceback (most recent call last): File "", line 1473, in Run File "", line 8, in ImportError: No module named pandas

Je suis désolée.Le traducteur de pine, attendant

le tempsIl y a une culture qui ne dit qu'une chose: arrogant!

Je vous en prie.Je suppose que je vais écrire un jour un traducteur de pine. Tout est en python.

Le KmeansSi le code du moteur de répétition est open source, je veux réaliser une répétition et ensuite utiliser svm pour trouver les meilleurs paramètres.

Je vous en prie.Ce système semble avoir été une stratégie de futures dans le top 10 des taux de rendement.

Des nuages légersBonjour, PD est la longueur d'ATR, n'est-ce pas?

Le petit rêveJe vous en prie.

les ovalesJ'espère que Pine ne comprend pas vraiment, et il y a peu de tutoriels.

l' homélieCela signifie qu'il manque le pack Panda, votre système peut avoir besoin de Pip pour installer Panda.

Le ciel des fourmisComment cela a-t-il été géré?

l' homélieMerci, chef.

Le petit rêveUne minute, c'est ouvert.

L'homme solitaireJ'ai besoin d'une version JS!

l' homélieJe suis très heureux d'apprendre l'essentiel.

Des nuages légersBien, merci! Mq4 a aussi été retiré, merci.

l' homélieOui, tout à fait.

l' homélieGloire à Allah, Seigneur de l'univers!

Le petit rêveIl se trouve que j'ai aussi écrit une version sous JS.

l' homélieMerci professeur Dream Dream.