English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Filtrage des Signaux en Fonction des Données Statistiques de la Corrélation des Prix.

Filtrage des Signaux en Fonction des Données Statistiques de la Corrélation des Prix.

MetaTrader 5Trading | 12 janvier 2022, 14:38
60 0
Михаил Тарачков
Михаил Тарачков

Comment cela a commencé

L'idée qui a conduit à la rédaction de cet article est apparue après avoir lu le livre de Larry Williams" de Long-Term Secrets court terme trading ", dans laquelle le détenteur du record du monde des investissements (au cours de 1987, il a augmenté son capital de 11 000%) défait complètement les mythes de "... des professeurs d'université et d'autres universitaires, riches en théorie et pauvres en connaissance du marché..." sur l'absence de corrélation entre le comportement passé des prix et les tendances futures.

Si vous lancez une pièce 100 fois, elle tombera 50 fois pile et 50 fois pile. À chaque lancer successif, la probabilité de pile est de 50 %, la même que celle de pile. La probabilité ne change pas d'un lancer à l'autre, car ce jeu est aléatoire et n'a pas de mémoire. Admettons que les marchés se comportent comme une pièce de monnaie, de manière chaotique.

Par conséquent, lorsqu'une nouvelle barre apparaît, un prix a la même chance de monter ou de descendre, et les barres précédentes n'affectent même pas le moins du monde la barre actuelle. Idylle! Créez un système de trading, définissez un bénéfice supérieur au stop loss (c'est-à-dire, définissez l'attente mathématique sur la zone positive), et le tour est joué. Tout simplement époustouflant. Cependant, le problème est que notre hypothèse sur le comportement du marché n'est pas tout à fait vraie. Franchement, c'est absurde ! Et je vais le prouver.

Créons un modèle Expert Advisor à l'aide de l'assistantMQL5 et en utilisant des interventions alphanumériques simples, présentons-le dans un état adapté à l'accomplissement de la tâche. Nous encoderons un Expert Advisor pour simuler l'achat qui suit une, deux et trois barres clôturées. La simulation indique que le programme se souviendra simplement des paramètres des barres analysées. L'envoi d'ordres (une manière plus habituelle) dans ce cas ne fonctionnera pas, car les spreads et les swaps peuvent remettre en cause la fiabilité des informations reçues.

Voici le code :

//+------------------------------------------------------------------+
//|                                                     explorer.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//---Variables---
double profit_percent,open_cur,close_cur;
double profit_trades=0,loss_trades=0,day_cur,hour_cur,min_cur,count;
double open[],close[];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
/* Calculate percent of closures with increase from the total number */
   profit_percent=NormalizeDouble(profit_trades*100/(profit_trades+loss_trades),2);
   Print("Percent of closures with increase ",profit_percent,"%");   // Enter data to the Journal
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---find out the time---
   MqlDateTime time;                        // Create a structure to store time
   TimeToStruct(TimeCurrent(),time);         // Structuring the data
   day_cur=time.day_of_week;              // Receive the value of the current day
   hour_cur=time.hour;                    // Receive the current hour
   min_cur=time.min;                      // Receive the current minute
//---Find out the prices---
   CopyOpen(NULL,0,0,4,open);ArraySetAsSeries(open,true);
   CopyClose(NULL,0,0,4,close);ArraySetAsSeries(close,true);

   if(close[1]<open[1]/*&&close[2]<open[2]&&close[3]<open[3]*/ && count==0) // If it closed with a loss
     {
      open_cur=open[0];                   // Remember open price of the current bar
      count=1;
     }
   if(open_cur!=open[0] && count==1)      // The current bar has closed
     {
      close_cur=close[1];                 // Remember the close price of the formed bar
      count=0;
      if(close_cur>=open_cur)profit_trades+=1;  // If the close price is higher than open,
      else loss_trades+=1;                      // +1 to closures with profit, otherwise +1 to closures with loss
     }
  }
//+------------------------------------------------------------------+

Le test sera réalisé sur l'EUR/USD, sur l'intervalle du 1er janvier 2000 au 31 décembre 2010 :

Figure 1. Le pourcentage de clôtures à la hausse.

Figure 1. Le pourcentage de clôtures avec l'augmentation

(La première colonne affiches les données pour toute la période, les deuxième, troisième et quatrième - après une clôture simple, double et triple)

C'est de cela que je parlais ! Les barres précédentes ont un impact assez important sur l'actuelle, car le prix cherche toujours à récupérer les pertes.


Un autre pas en avant

Super! Une fois que nous nous assurons que le comportement des prix n'est pas accidentel, nous devons utiliser ce fait étonnant dès que possible. Bien sûr, ce n'est pas suffisant pour un système de trading indépendant, mais ce sera un bel outil qui pourra vous libérer des signaux fastidieux et souvent erronés. Mettons-le en œuvre !

Voilà donc ce qu'il nous faut :

  1. Un système d'auto-trade, affichant des résultats positifs au moins pour la dernière année.
  2. Quelques exemples amusants qui confirment la présence de corrélations dans le comportement des prix.

J'ai trouvé beaucoup d'idées utiles dans le livre de L. Williams. Je vais partager l'un d'eux avec vous.

La stratégie TDW (Trade Day Of Week). Cela nous permettra de voir ce qui se passera si certains jours de la semaine nous n'achetons que, et les autres - n'ouvrent que des courtes positions.. Après tout, nous pouvons admettre que le prix au cours d'une journée augmente dans un plus grand pourcentage de cas que dans l'autre. Quelle en est la raison ? La situation géopolitique, les statistiques macroéconomiques, ou, comme l'écrit le livre de A. Elder, le lundi et le mardi sont les jours des profanes, tandis que les jeudis et vendredis sont ceux des professionnels ? Tentons de comprendre.

Tout d'abord, nous ne vendrons que chaque jour de la semaine, puis nous ne vendrons que. À la fin de l'étude, nous ferons correspondre les meilleurs résultats, et ce sera un filtre pour notre système de trading. D'ailleurs, j'ai quelques mots à ce sujet. C'est un pur classique !

Le système est basé sur deux MAs et MACDake. Signaux :                                                            

  1. Si la moyenne mobile rapide croise la moyenne lente de bas en haut et que l'histogramme MACD est en dessous de la ligne zéro, alorsBUY .
  2. Si la moyenne mobile rapide croise la lente à l'envers et que le MACD est au-dessus de zéro, alorsSELL

Quittez une position en utilisant un stop suiveur à partir d'un point. Le lot est fixe - 0,1. 

 Par souci de commodité, j'ai placé la classe Expert Advisor dans un fichier d'en-tête séparé :

//+------------------------------------------------------------------+
//|                                                       moving.mqh |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Класс my_expert                                                  |
//+------------------------------------------------------------------+
class my_expert
  {                                                  // Creating a class
   // Closed class members
private:
   int               ma_red_per,ma_yel_per;          // Periods of MAs
   int               ma_red_han,ma_yel_han,macd_han; // Handles
   double            sl,ts;                          // Stop orders
   double            lots;                           // Lot
   double            MA_RED[],MA_YEL[],MACD[];       // Arrays for the indicator values
   MqlTradeRequest   request;                         // Structure of a trade request
   MqlTradeResult    result;                          // Structure of a server response
                                                    // Open class members   
public:
   void              ma_expert();                                   // Constructor
   void get_lot(double lot){lots=lot;}                               // Receiving a lot  
   void get_periods(int red,int yel){ma_red_per=red;ma_yel_per=yel;} // Receiving the periods of MAs
   void get_stops(double SL,double TS){sl=SL;ts=TS;}                  // Receiving the values of stops
   void              init();                                         // Receiving the indicator values
   bool              check_for_buy();                                // Checking for buy
   bool              check_for_sell();                               // Checking for sell
   void              open_buy();                                     // Open buy
   void              open_sell();                                    // Open sell
   void              position_modify();                              // Position modification
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
/* Function definition */
//---Constructor---
void my_expert::ma_expert(void)
  {
//--- Reset the values of variables
   ZeroMemory(ma_red_han);
   ZeroMemory(ma_yel_han);
   ZeroMemory(macd_han);
  }
//---The function for receiving the indicator values---
void  my_expert::init(void)
  {
   ma_red_han=iMA(_Symbol,_Period,ma_red_per,0,MODE_EMA,PRICE_CLOSE); // Handle of the slow MA
   ma_yel_han=iMA(_Symbol,_Period,ma_yel_per,0,MODE_EMA,PRICE_CLOSE); // Handle of the fast MA
   macd_han=iMACD(_Symbol,_Period,12,26,9,PRICE_CLOSE);               // Handle of MACDaka
//---Copy data into arrays and set indexing like in a time-series---
   CopyBuffer(ma_red_han,0,0,4,MA_RED);
   CopyBuffer(ma_yel_han,0,0,4,MA_YEL);
   CopyBuffer(macd_han,0,0,2,MACD);
   ArraySetAsSeries(MA_RED,true);
   ArraySetAsSeries(MA_YEL,true);
   ArraySetAsSeries(MACD,true);
  }
//---Function to check conditions to open buy---   
bool my_expert::check_for_buy(void)
  {
   init();  //Receive values of indicator buffers
/* If the fast MA has crossed the slow MA from bottom up between 2nd and 3rd bars, 
   and there was no crossing back. MACD-hist is below zero */
   if(MA_RED[3]>MA_YEL[3] && MA_RED[1]<MA_YEL[1] && MA_RED[0]<MA_YEL[0] && MACD[1]<0)
     {
      return(true);
     }
   return(false);
  }
//----Function to check conditions to open sell---
bool my_expert::check_for_sell(void)
  {
   init();  //Receive values of indicator buffers
/* If the fast MA has crossed the slow MA from up downwards between 2nd and 3rd bars,
  and there was no crossing back. MACD-hist is above zero */
   if(MA_RED[3]<MA_YEL[3] && MA_RED[1]>MA_YEL[1] && MA_RED[0]>MA_YEL[0] && MACD[1]>0)
     {
      return(true);
     }
   return(false);
  }
//---Open buy---
/* Form a standard trade request to buy */
void my_expert::open_buy(void)
  {
   request.action=TRADE_ACTION_DEAL;
   request.symbol=_Symbol;
   request.volume=lots;
   request.price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
   request.sl=request.price-sl*_Point;
   request.tp=0;
   request.deviation=10;
   request.type=ORDER_TYPE_BUY;
   request.type_filling=ORDER_FILLING_FOK;
   OrderSend(request,result);
   return;
  }
//---Open sell---
/* Form a standard trade request to sell */
void my_expert::open_sell(void)
  {
   request.action=TRADE_ACTION_DEAL;
   request.symbol=_Symbol;
   request.volume=lots;
   request.price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
   request.sl=request.price+sl*_Point;
   request.tp=0;
   request.deviation=10;
   request.type=ORDER_TYPE_SELL;
   request.type_filling=ORDER_FILLING_FOK;
   OrderSend(request,result);
   return;
  }
//---Position modification---
void my_expert::position_modify(void)
  {
   if(PositionGetSymbol(0)==_Symbol)
     {     //If a position is for our symbol
      request.action=TRADE_ACTION_SLTP;
      request.symbol=_Symbol;
      request.deviation=10;
      //---If a buy position---
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
/* if distance from price to stop loss is more than trailing stop
   and the new stop loss is not less than the previous one */
         if(SymbolInfoDouble(Symbol(),SYMBOL_BID)-PositionGetDouble(POSITION_SL)>_Point*ts)
           {
            if(PositionGetDouble(POSITION_SL)<SymbolInfoDouble(Symbol(),SYMBOL_BID)-_Point*ts)
              {
               request.sl=SymbolInfoDouble(Symbol(),SYMBOL_BID)-_Point*ts;
               request.tp=PositionGetDouble(POSITION_TP);
               OrderSend(request,result);
              }
           }
        }
      //---If it is a sell position---                
      else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
        {
/*  if distance from price to stop loss is more than the trailing stop value
   and the new stop loss is not above the previous one. Or the stop loss from the moment of opening is equal to zero */
         if((PositionGetDouble(POSITION_SL)-SymbolInfoDouble(Symbol(),SYMBOL_ASK))>(_Point*ts))
           {
            if((PositionGetDouble(POSITION_SL)>(SymbolInfoDouble(Symbol(),SYMBOL_ASK)+_Point*ts)) || 
               (PositionGetDouble(POSITION_SL)==0))
              {
               request.sl=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+_Point*ts;
               request.tp=PositionGetDouble(POSITION_TP);
               OrderSend(request,result);
              }
           }
        }
     }
  }
//+------------------------------------------------------------------

Mes humbles hommages à l'auteur de l'article "Writing an Expert Advisor using the MQL5 Object-Oriented Approach". Que ferais-je sans ! Je recommande la lecture de cet article à tous ceux qui ne connaissent pas très bien cette programmation orientée objet maléfique mais extrêmement fonctionnelle.

Ajoutez le fichier avec la classe au code principal de l'Expert Advisor ? créez un objet et initialisez les fonctions :

//+------------------------------------------------------------------+
//|                                                       Moving.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//---Include a file with the class---
#include <moving.mqh>
//---External Variables---
input int MA_RED_PERIOD=7; // The period of a slow MA
input int MA_YEL_PERIOD=2; // The period of a fast MA
input int STOP_LOSS=800;   // Stop loss
input int TRAL_STOP=800;   // Trailing stop
input double LOTS=0.1;     // Lot
//---Create an object---
my_expert expert;
//---Initialize the MqlDataTime structure---
MqlDateTime time;
int day_of_week;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---Initialize the EA
   expert.get_periods(MA_RED_PERIOD,MA_YEL_PERIOD);   // Set the MA periods
   expert.get_lot(LOTS);                              // Set the lot
   expert.get_stops(STOP_LOSS,TRAL_STOP);             // Set stop orders  
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   TimeToStruct(TimeCurrent(),time);
   day_of_week=time.day_of_week;
   if(PositionsTotal()<1)
     {
      if(day_of_week==5 && expert.check_for_buy()==true){expert.open_buy();}
      else if(day_of_week==1 && expert.check_for_sell()==true){expert.open_sell();}
     }
   else expert.position_modify();
  }
//+------------------------------------------------------------------+

Terminé Je voudrais noter quelques spécificités Pour identifier les jours de la semaine au niveau logiciel, j'ai utilisé la structureMqlDateTime . Tout d'abord, nous transformons l'heure actuelle du serveur en un format structuré. Nous obtenons un indice du jour en cours (1-lundi, ..., 5-vendredi) et le comparons avec la valeur que nous avons fixée.

Essayez-en! Afin de ne pas vous alourdir de recherches fastidieuses et de chiffres supplémentaires, j'apporte tous les résultats dans le tableau.

C'est ici: 

Tableau 1. Récapitulatif des achats tous les jours de la semaine

Tableau 1. Récap des achats tous les jours de la semaine

Tableau 2. Récapitulatif des ventes tous les jours de la semaine

Tableau 2. Récap des ventes tous les jours de la semaine

Les meilleurs résultats sont surlignés en vert, les pires sont en orange.

Je fais une réserve, qu'après les actions décrites ci-dessus, le système doit assurer un bénéfice en combinaison avec un faible tirage relatif, un bon pourcentage de trades gagnants (ici, moins il y a de transactions, mieux c'est) et un bénéfice par trade relativement élevé.

De toute évidence, le système le plus efficace consiste à acheter le vendredi et à vendre le lundi. Combinez ces deux conditions :

if(PositionsTotal()<1){
      if(day_of_week==5&&expert.check_for_buy()==true){expert.open_buy();}
      else if(day_of_week==1&&expert.check_for_sell()==true){expert.open_sell();}}
   else expert.position_modify();

Désormais, l'Expert Advisor ouvre des positions dans les deux sens, mais à des jours strictement définis. Pour plus de clarté, je vais dessiner les schémas obtenus sans et avec le filtre :

Figure 2. Les résultats des tests EA sans utiliser de filtre (EURUSD, H1, 01.01.2010-31.12.2010,)

Figure 2. Les résultats des tests EA sans utiliser de filtre (EURUSD, H1, 01.01.2010-31.12.2010,)

Figure 3. Les résultats des tests EA utilisant le filtre (EURUSD, H1, 01.01.2010-31.12.2010,)

Figure 3. Les résultats des tests EA utilisant le filtre (EURUSD, H1, 01.01.2010-31.12.2010)

Comment appréciez-vous le résultat? En utilisant le filtre, le système de trading est devenu plus stable. Avant les modifications, l'Expert Advisor augmentait principalement le solde dans la première moitié de la période de test, après la "mise à niveau", il augmente tout au long de la période.

Nous comparons les rapports :

Tableau 3. Résultats des tests avant et après utilisation du filtre

Tableau 3. Résultats des tests avant et après utilisation du filtre

Le seul facteur affligeant, qui ne peut être ignoré, est la chute du bénéfice net de près de 1000 USD (26%). Mais nous réduisons le nombre de trades presque à 3,5 fois, c'est-à-dire en réduisant considérablement, d'une part, le potentiel de faire un trade négatif et, d'autre part, les dépenses pour le spread (218*2-62*2=312 USD et c'est uniquement pour EUR/USD). Le pourcentage de gain est porté à 57%, ce qui est déjà considérable. Alors que le bénéfice par trade augmente de 14% à 113 USD. Comme dirait L. Williams : « C'est le montant qui vaut la peine d'être échangé ! »


Conclusion

Les prix ne se comportent pas au hasard - c'est un fait. Ce fait peut et doit être utilisé. Je n'ai donné qu'un seul exemple, qui n'est qu'une infime fraction des innombrables variations et techniques qui peuvent améliorer les performances de votre système de trading. Cependant, cette diversité cache un vice. Pas tous les filtres peuvent être intégrés, ils doivent donc être choisis avec soin, en pensant à tous les scénarios possibles.

N'oubliez pas que peu importe la perfection du filtre, il élimine également les trades rentables, c'est-à-dire votre bénéfice... Bonne chance!


Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/269

Fichiers joints |
explorer.mq5 (2.84 KB)
moving.mq5 (2.28 KB)
moving.mqh (6.98 KB)
3 Méthodes d'Accélération des Indicateurs par l'Exemple de la Régression Linéaire 3 Méthodes d'Accélération des Indicateurs par l'Exemple de la Régression Linéaire
L'article traite des méthodes d'optimisation des algorithmes de calcul des indicateurs. Chacun trouvera une méthode qui correspond le mieux à ses besoins. Trois méthodes sont décrites ici. L'une d'elles est assez simple, la suivante exige de solides connaissances en mathématiques et la dernière un peu d'esprit. Des indicateurs ou des caractéristiques de conception de terminal MetaTrader5 sont utilisés pour réaliser la plupart des méthodes décrites. Les méthodes sont assez universelles et peuvent être utilisées non seulement pour accélérer le calcul de la régression linéaire, mais aussi pour de nombreux autres indicateurs.
Le Rôle des Distributions Statistiques dans le Travail des Traders Le Rôle des Distributions Statistiques dans le Travail des Traders
Cet article est la suite logique de mon article Statistical Probability Distributions en MQL5 qui présente les classes pour travailler avec certaines distributions statistiques théoriques. Maintenant que nous disposons d'une base théorique, je suggère que nous procédions directement à des ensembles de données réelles et que nous essayions de faire un usage informatif de cette base.
Distributions de Probabilités Statistiques dans MQL5 Distributions de Probabilités Statistiques dans MQL5
L'article traite des distributions de probabilité (normale, log-normale, binomiale, logistique, exponentielle, distribution de Cauchy, distribution t de Student, distribution de Laplace, distribution de Poisson, distribution sécante hyperbolique, distribution bêta et gamma) des variables aléatoires utilisées en Statistique Appliquée. Il propose également des classes pour gérer ces distributions.
Utilisation de Pseudo-Modèles comme Alternative aux Modèles C++ Utilisation de Pseudo-Modèles comme Alternative aux Modèles C++
L'article décrit une façon de programmer sans utiliser de modèles mais en gardant le style de programmation iherenet pour eux. Il explique l’implémentation de modèles à l'aide de méthodes personnalisées et comporte un script prêt à l'emploi pour créer un code sur la base de modèles indiqués.