web-dev-qa-db-fra.com

Comment puis-je écrire du code mql4 (EA) qui marque les modèles de bougies répertoriés avec des rectangles

Je suis assez nouveau pour écrire mql4 code et serait reconnaissant si je pouvais obtenir de l'aide pour dessiner des rectangles lorsque les motifs de chandelier suivants se produisent:

FIG1:

image taken from https://imgur.com/a/fRoPzsm

Run code snippet

<blockquote class="imgur-embed-pub" lang="en" data-id="a/fRoPzsm"><a href="//imgur.com/a/fRoPzsm">Demand Zone 1</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>

FIG2:

image taken from https://imgur.com/a/4E8KE1R

Run code snippet

<blockquote class="imgur-embed-pub" lang="en" data-id="a/4E8KE1R" data-context="false"><a href="//imgur.com/a/4E8KE1R">Demand Zone 2</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>

et

FIG3:

image taken from https://imgur.com/a/h6D6o6R

Run code snippet

<blockquote class="imgur-embed-pub" lang="en" data-id="a/h6D6o6R"><a href="//imgur.com/a/h6D6o6R">Hidden Demand Zone</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>

et zones d'approvisionnement respectives
et l'ouverture d'une commande en attente avec les pips Stop Loss et Take Profit spécifiés.

Pardonnez-moi de ne pas avoir inclus les images directement. Je n'ai pas assez de votes positifs pour le faire.

Voici une explication des motifs de chandelier dans les images liées:

Zone de demande

Le général candlestick pattern (Zone de demande) se produit lorsqu'au moins deux bougies haussières consécutives ou plus (la dernière bougie haussière étant la plus élevée de la période) sont suivies par une ou plusieurs bougies baissières dont le haut et le bas sont inférieurs à la dernière bougie haussière . Puis finalement suivi d'une bougie haussière qui forme le nouveau sommet. La zone rectangulaire qui est la zone de demande est prise de l'ouverture au bas de la dernière dernière bougie baissière.

Zone de demande cachée

Lorsqu'une série de bougies haussières consécutives a une bougie avec son bas, inférieur à la bougie précédente et son haut coïncidant avec sa fermeture, la zone de demande cachée est prise du bas à l'ouverture de la bougie haussière.

L'explication complète est disponible ici pour les zones de demande et d'approvisionnement.

Je sais que les bougies bullish et bearish peuvent être déterminées par


    if ( ( Open[1] - Close[1] ) > 0)
    {
      // candle is bearish
    }
    else
    {
      // candle is bullish
    }

J'apprécierais volontiers de l'aide.

14
TopLeft

Il semble que ces modèles ne soient pas entièrement décrits, il n'est donc pas possible de les coder correctement. Ok, essayons avec le modèle # 1. Les conditions utilisées pour le motif (ce qui semble raisonnable sur la photo):
1. vérifier au début de la nouvelle barre (barre # 0).
2. la barre 1 (qui est la barre n ° 3 dans MQL4 si nous calculons 0 comme courant) doit être haussière.
3. la barre 2 (barre n ° 2) est baissière. (ou N barres dans le cas du modèle # 2, N peut être 2 ou plus) 4. la barre 3 (barre # 1 dans MT4) est haussière.
5. son haut = proche.
6. son haut> haut de la barre # 3.

enum EnmDir
 {
  LONG = 1,
  SHORT=-1,
  NONE = 0,
 };
int getCandleDirection(const int shift)
{
   const double open=iOpen(_Symbol,0,shift), close=iClose(_Symbol,0,shift);
   if(close-open>_Point/2.)
      return LONG;      //bullish
   if(open-close>_Point/2.)
      return SHORT;     //bearish
   return NONE;     //doji
}
bool isPattern1Detected(const EnmDir dir)
{
   if(dir==0)return(false);
   if(getCandleDirection(3)!=dir)
      return false; //rule#2
   if(getCandleDirection(2)+dir!=0)
      return false; //rule#3
   if(getCandleDirection(1)!=dir)
      return false; //rule#4
   if(dir>0)
   {
      if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
         return false;  //rule#5 for long
      if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,3)>_Point/2.)
         return true;   //rule#6 for long
      return false;     //if rule#6 is not hold
   }
   else
   {
      if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
         return false;  //rule#5 for short
      if(iLow(_Symbol,0,3)-iLow(_Symbol,0,1)>_Point/2.)
         return true;   //rule#6 for short
      return false;     //if rule#6 is not hold
   }
}
bool isPattern2Detected(const EnmDir dir,const int numCandlesAgainst=1)
{
   if(dir==NONE)return(false);
   if(getCandleDirection(1)!=dir)
      return false; //rule#4
   for(int i=1;i<=numCandlesAgainst;i++)
   {
      if(getCandleDirection(1+i)!=dir)
         return(false); //rule#3 - checking that all numCandlesAgainst must be bearish
   }
   if(getCandleDirection(2+numCandlesAgainst)!=dir)
       return false; //rule#2
   if(dir>0)
   {
     if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
        return false;  //rule#5 for long
     if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,2+numCandlesAgainst)>_Point/2.)
        return true;   //rule#6 for long
     return false;     //if rule#6 is not hold
   }
   else
   {
     if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
        return false;  //rule#5 for short
     if(iLow(_Symbol,0,2+numCandlesAgainst)-iLow(_Symbol,0,1)>_Point/2.)
        return true;   //rule#6 for short
     return false;     //if rule#6 is not hold
   }
}

De quoi d'autre avez-vous besoin ici? Pour détecter HL du rectangle? C'est simple, les règles sont claires. Supposons qu'ils soient: pour LONG, haut = Ouverture de la barre # 2, bas = bas de cette barre. Ensuite,

void detectRangeOfZone(double &top,double &bottom,const EnmDir dir)
{
    if(dir>0)
    {
        top=iOpen(_Symbol,0,2);
        bottom=iLow(_Symbol,0,2);
    }
    else if(dir<0)
    {
        top=iClose(_Symbol,0,2);
        bottom=iHigh(_Symbol,0,2);
    }
}

Avez-vous besoin de dessiner un rectangle? Ok mais comment décideriez-vous quel est le temps d'arrêter de dessiner? Supposons que N barres à droite soient suffisantes, et ignorons les week-ends pour l'instant (un peu plus compliqué si l'on garde à l'esprit week-end lorsque le marché est fermé).

bool drawRectangle(const int dir,const double top,const double bottom)
{
    const datetime starts=iTime(_Symbol,0,2), ends=starts+PeriodSeconds()*N_bars;//time of start and end of the rectangle
    const string name=prefix+"_"+(dir>0?"DEMAND":"SUPPLY")+"_"+TimeToString(starts);//name would be unique sinse we use time of start of the range. DO NOT FORGET about prefix - it should be declared globally, you would be able to delete all the objects with 'ObjectsDeleteAll()' function that accepts prefix in one of its implementations.

    if(!ObjectCreate(0,name,OBJ_RECTANGLE,0,0,0,0,0))
    {
        printf("%i %s: failed to create %s. error=%d",__LINE__,__FILE__,name,_LastError);
        return false;
    }
    ObjectSetInteger(0,name,OBJPROP_TIME1,starts);
    ObjectSetInteger(0,name,OBJPROP_TIME2,ends);
    ObjectSetDouble(0,name,OBJPROP_PRICE1,top);
    ObjectSetDouble(0,name,OBJPROP_PRICE2,bottom);
    //add color, width, filling color, access modifiers etc, example is here https://docs.mql4.com/ru/constants/objectconstants/enum_object/obj_rectangle
    return true;
}

voici le bloc principal, n'oubliez pas d'ajouter une nouvelle barre de contrôle, sinon l'outil vérifierait les objets à chaque tick ce qui est une perte de temps. string prefix = ""; // ajoute un préfixe unique pour tous vos objets const int N_bars = 15; // 15 bars dans cet exemple

void OnDeinit(const int reason){ObjectsDeleteAll(0,prefix);}
void OnTick()
{
    if(!isNewBar())
        return;     //not necessary but waste of time to check every second

    const bool pattern1Up=isPattern1Detected(1), pattern1Dn=isPattern1Detected(-1);
    if(pattern1Up)
    {
        double top,bottom;
        detectRangeOfZone(top,bottom,1);
        drawRectangle(1,top,bottom);
        PlacePendingOrder(1,top,bottom);
    }
    if(pattern1Dn)
    {
        double top,bottom;
        detectRangeOfZone(top,bottom,-1);
        drawRectangle(-1,top,bottom);
        PlacePendingOrder(-1,top,bottom);
    }
}

int PlacePendingOrder(const EnmDir dir,const double oop,const double suggestedSl)
{
   const double lot=0.10;                  //FOR EXAMPLE, PUT YOUR DATA HERE
   const string comment="example for SOF";
   const int magicNumber=123456789;

   int cmd=dir>0 ? OP_BUY : OP_SELL;
   double price=(dir>0 ? Ask : Bid), spread=(Ask-Bid);
   if(dir*(oop-price)>spread)
      cmd+=(OP_BUYSTOP-OP_BUY);
   else if(dir*(price-oop)>spread)
      cmd+=(OP_BUYLIMIT-OP_BUY);

   int attempt=0, ATTEMPTS=5, SLEEP=25, SLIPPAGE=10, result=-1, error=-1;
   while(attempt<ATTEMPTS)
     {
      attempt++;
      RefreshRates();
      if(cmd<=OP_SELL)
        {
         price=dir>0 ? Ask : Bid;
         result=OrderSend(_Symbol,cmd,lot,price,SLIPPAGE,0,0,comment,magicNumber);
        }
      else
        {
         result=OrderSend(_Symbol,cmd,lot,oop,SLIPPAGE,0,0,comment,magicNumber);
        }
      if(result>0)
         break;
      error=_LastError;
      Sleep(SLEEP);
    }
  if(result>0)
    {
     if(OrderSelect(result,SELECT_BY_TICKET))
       {
        price=OrderOpenPrice();
        if(!OrderModify(result,price,suggestedSl,0,OrderExpiration()))
           printf("%i %s: failed to modify %d. error=%d",__LINE__,__FILE__,result,_LastError);
           //tp is zero, sl is suggested SL, put yours when needed
       }
     return result;
    }
    printf("%i %s: failed to place %s at %.5f. error=%d",__LINE__,__FILE__,EnumToString((ENUM_ORDER_TYPE)cmd),(cmd>OP_SELL ? oop : price),error);
    return -1;
}
1
Daniel Kniaz

Je suis en retard: '(Le travail m'a empêché de StackOverflow:' (Quoi qu'il en soit, je ne serai pas en mesure de fournir un programme complet selon la prime, ni de fournir le code complet pour résoudre cette question de la zone de demande.

Cependant, je voudrais toujours fournir un "terrain de départ" pour que chacun puisse construire son propre Pattern Recognizer sur MT4 (MQL4).

Pour garder le texte court, j'ai enregistré une vidéo YouTube pour le décrire. https://youtu.be/WSiyY52QyBI

Quoi qu'il en soit, voici les codes:

//+------------------------------------------------------------------+
//|                                                   SO56854700.mq4 |
//|                 Copyright 2019, Joseph Lee, TELEGRAM JosephLee74 |
//|               https://stackoverflow.com/users/1245195/joseph-lee |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Joseph Lee, TELEGRAM JosephLee74"
#property link      "https://stackoverflow.com/users/1245195/joseph-lee"
#property version   "1.00"
#property strict

#include <clsBar.mqh>
#include <stderror.mqh> 
#include <stdlib.mqh> 

//==========================================================================

//-------------------------------------------------------------------
// System Variables
//-------------------------------------------------------------------
double  viPipsToPrice               = 0.0001;
double  viPipsToPoint               = 1;
string  vsDisplay                   = "";

//-------------------------------------------------------------------

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
    ObjectsDeleteAll(); Comment("");
    // Caclulate PipsToPrice & PipsToPoints (old sytle, but works)
    if((Digits == 2) || (Digits == 3)) {viPipsToPrice=0.01;}
    if((Digits == 3) || (Digits == 5)) {viPipsToPoint=10;}

    return(INIT_SUCCEEDED);
}


//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
    ObjectsDeleteAll();
    return(0);
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
    if(!isNewBar())
        return;

    clsCandlestickPattern   voPatterns[];
    clsPatternRecognizer        voRec(Symbol(), true), PERIOD_CURRENT, 0);
    voRec.sbRecognizePatterns(voPatterns);
    for(...
       Display the content with Comment() ...
}
//+------------------------------------------------------------------+

Plus important encore, est le clsBar.mqh . Notez qu'il s'agit d'un "fichier include" et qu'il doit se trouver dans le dossier include. Le fichier d'inclusion nous aide à réduire l'encombrement de notre programme et nous aide à écrire des codes réutilisables. Très utile lors de l'écriture de classes OOP.

clsBar.mqh: Télécharger (OneDrive) https://1drv.ms/u/s!AoLFy6fRYNsvjTU-xSzAADCwGjPQ

Malheureusement, le fichier est trop volumineux pour être inclus dans ce post. Je dois donc le télécharger sur OneDrive.

1
Joseph Lee