Addendum :
La pésentation du langage souffre également de l'absence des autres types de variables (string, color, datetime) ainsi que l'évocation des tableaux.
En ce qui concerne la création d'un EA il est dommage de ne pas avoir eu plus de détails sur l'assistant et notamment l'ajout de paramètres qui sont indispensables dans la plupart des cas.
De plus, on constate là encore l'absence de préparation globale puisque les fonctions auraient dû être présentées dans la vidéo des bases.
L'utilisation des variables globales est incorrecte, dans le cas d'un expert simpliste où seule la fonction start sera utilisée, il est préférable d'utiliser des variables locales (interne à la fonction start). L'utilité des variables globales étant de conserver certaines valeurs qui seront utilisées lors du tick suivant, les variables locales étant détruites à la fin de la fonction dans laquelle elles ont été déclarées.
Leur utilisation est d'autant plus erronée que les constantes ne doivent pas (sauf certains cas particuliers) être stockées dans des variables mais définies statiquement par la directive #define (cas d'école pour le MAGIC).
De mon point de vue (il ne s'agit là que de mon avis de programmeur), l'exemple de la fonction isTrade aurait pu faire l'objet d'une optimisation, le code suivant
Code
bool isTrade () {
if (OrdersTotal() >= 1)
{
return(true);
}
else
{
return(false);
}
}
d'une part peut être syntaxiquement simplifiée et la condition rendue plus efficace (la comparaison complexe ">=" consommant plus de ressource qu'un simple ">"
;) :
Code
bool isTrade () {
if (OrdersTotal() > 0)
return(true);
else
return(false);
}
et même considérablement réduite :
Code
bool isTrade() {
return(OrdersTotal() > 0);
}
L'utilisation des booléens dans les conditions est laborieuse, l'instruction if vérifiant si la condition est true ou false il est totalement inutile d'en faire la comparaison, le code suivant est amplement suffisant :
Code
if (! isTrade()) {
}
L'explication du MA shift est honteusement écartée, preuve supplémentaire de la méconnaissance du sujet. Le décalage de la moyenne mobile correspond à une translation de la courbe de n bougies vers la droite. En pratique elle est très rarement utilisée.
Les ticks et les bougies sont également confondus pour l'utilisation du dernier paramètre de la fonction de l'indicateur, un tick étant l'arrivée d'une nouvelle cotation de la paire, une bougie étant comme chacun sait un intervalle de temps caractérisé par les données OHLC (Open/High/Low/Close).
La sélection d'un ordre par OrderSelect en mode ticket n'utilise pas le pool, un numéro de ticket étant unique il sera correctement sélectionné s'il existe
Outre ces petites ombres il y a un problème plus général de conception de mon point de vue. Cependant, il n'y a pas de vérité absolue en programmation donc il ne s'agit là que de ma propre vision.
Je pense qu'il aurait été plus efficace de traiter de l'évènementiel, à savoir réagir uniquement lors d'un croisement des MA :
si croisement par le base des MA alors fermer l'ordre de vente s'il existe et ouvrir un ordre d'achat
si croisement par le haut des MA alors fermer l'ordre d'achat s'il existe et ouvrir un ordre de vente
Cela évite d'avoir à dupliquer les conditions d'entrée et de sortie qui deviendront source d'erreurs en cas de changement de celles-ci.
De plus, la vérification du magic n'est pas faite, l'expert fermera donc arbitrairement tous les ordres passés sur la plateforme même s'il n'en est pas l'auteur.
En conclusion, le programme est mal écrit, ne dispose d'aucun commentaire rendant difficile sa compréhension et sa maintenance, ne propose aucune vérification des erreurs et a des effets de bord catastrophiques. J'irai presque jusqu'à dire que c'est le bon exemple de ce qu'il ne faut pas faire.
Juste à titre d'exemple, voilà comment j'aurais programmé l'EA :
Code
//+------------------------------------------------------------------+
//| SMACross.mq4 |
//| Copyright 2012, N. Tuffier |
//| http://www.furyweb.fr/forex/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, N. Tuffier"
#property link "http://www.furyweb.fr/forex/"
#define MAGIC 375403
//--- input parameters
extern int MAPeriodSlow=10;
extern int MAPeriodFast=5;
extern double LotSize=0.1;
string s;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init() {
//----
s = Symbol();
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit() {
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start() {
//----
int cnt, i, ticket = 0;
bool signalBuy, signalSell;
double prevSlowMA, prevFastMA, curSlowMA, curFastMA;
// recherche de l'ordre en cours passé par le robot,
// si aucun ordre trouvé la variable ticket reste à 0
cnt = OrdersTotal();
for (i = 0; i < cnt; i++)
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
if (OrderMagicNumber() == MAGIC) {
ticket = OrderTicket();
break;
}
// détection des signaux d'achat/vente
prevSlowMA = iMA(s, 0, MAPeriodSlow, 0, MODE_SMA, PRICE_CLOSE, 1);
prevFastMA = iMA(s, 0, MAPeriodFast, 0, MODE_SMA, PRICE_CLOSE, 1);
curSlowMA = iMA(s, 0, MAPeriodSlow, 0, MODE_SMA, PRICE_CLOSE, 0);
curFastMA = iMA(s, 0, MAPeriodFast, 0, MODE_SMA, PRICE_CLOSE, 0);
signalBuy = prevFastMA < prevSlowMA && curFastMA > curSlowMA; // croisement par le bas
signalSell = prevFastMA > prevSlowMA && curFastMA < curSlowMA; // croisement par le haut
// ouverture et fermeture des ordres
if (signalBuy) {
// fermeture de l'ordre de vente s'il existe
if (ticket != 0 && OrderType() == OP_SELL)
OrderClose(ticket, OrderLots(), Ask, 3);
// ouverture d'un nouvel ordre
OrderSend(s, OP_BUY, LotSize, Ask, 3, 0.0, 0.0, "", MAGIC);
}
if (signalSell) {
// fermeture de l'ordre d'achat s'il existe
if (ticket != 0 && OrderType() == OP_BUY)
OrderClose(ticket, OrderLots(), Bid, 3);
// ouverture d'un nouvel ordre
OrderSend(s, OP_SELL, LotSize, Bid, 3, 0.0, 0.0, "", MAGIC);
}
//----
return(0);
}
//+------------------------------------------------------------------+