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:
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:
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:
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:
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.
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.
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;
}
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.