#property description "Expert Advisor qui envoie des demandes de trades "
" en utilisant la fonction OrderSendAsync().\r\n"
#property description "La gestion des évènements de trading gérés avec"
" les fonctions OnTrade() et OnTradeTransaction() est affichée\r\n"
#property description "Les paramètres de l'Expert Advisor permet de définir le Magic Number"
" (identifiant unique) "
#property description "et le mode d'affichage des messages dans le journal des Experts. Tous les détails sont affichés par défaut.\r\n"
//--- paramètres d'entrée
input int MagicNumber=1234567; // Identifiant de l'Expert Advisor
input bool DescriptionModeFull=true; // Mode de sortie détaillée
//--- variable à utiliser dans l'appel à HistorySelect()
datetime history_start;
//+------------------------------------------------------------------+
//| Fonction d'initialisation de l'expert |
//+------------------------------------------------------------------+
int OnInit()
{
//--- vérifie si le trading automatique est autorisé
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Alert("Le trading automatique dans le terminal est désactivé, l'Expert Advisor sera enlevé.");
ExpertRemove();
return(-1);
}
//--- impossible de trader sur un compte réel
if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
{
Alert("L'Expert Advisor ne peut pas trader sur un compte réel !");
ExpertRemove();
return(-2);
}
//--- vérifie s'il est possible de trader sur ce compte (par exemple, le trading est impossible lorsque le mot de passe investisseur est utilisé)
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
{
Alert("Le trading sur ce compte est désactivé");
ExpertRemove();
return(-3);
}
//--- sauvegarde l'heure de lancement de l'Expert Advisor pour récupérer l'historique de trading
history_start=TimeCurrent();
//---
CreateBuySellButtons();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Fonction de dé-initialisation de l'Expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- supprime tous les objets graphiques
ObjectDelete(0,"Buy");
ObjectDelete(0,"Sell");
//---
}
//+------------------------------------------------------------------+
//| Fonction TradeTransaction |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
//--- en-tête nommé d'après la fonction de gestion de l'évènement de trading
Print("=> ",__FUNCTION__," à ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- récupère le type de transaction sous la forme d'une valeur d'énumération
ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- si la transaction est le réstulat de la gestion de la demande
if(type==TRADE_TRANSACTION_REQUEST)
{
//--- affiche le nom de la transaction
Print(EnumToString(type));
//--- affiche ensuite la description de la requête traitée
Print("------------RequestDescription\r\n",
RequestDescription(request,DescriptionModeFull));
//--- et affiche la description du résultat de la requête
Print("------------ ResultDescription\r\n",
TradeResultDescription(result,DescriptionModeFull));
}
else // affiche la description complète de la transaction pour les transactions d'un autre type
{
Print("------------ TransactionDescription\r\n",
TransactionDescription(trans,DescriptionModeFull));
}
//---
}
//+------------------------------------------------------------------+
//| Fonction Trade |
//+------------------------------------------------------------------+
void OnTrade()
{
//--- membres statiques pour stocket l'état du compte de trading
static int prev_positions=0,prev_orders=0,prev_deals=0,prev_history_orders=0;
//--- récupère l'historique de trading
bool update=HistorySelect(history_start,TimeCurrent());
PrintFormat("HistorySelect(%s , %s) = %s",
TimeToString(history_start),TimeToString(TimeCurrent()),(string)update);
//--- en-tête nommé d'après la fonction de gestion de l'évènement de trading
Print("=> ",__FUNCTION__," à ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- affiche le nom de la fonction et le nombre d'ordre au moment de l'appel
int curr_positions=PositionsTotal();
int curr_orders=OrdersTotal();
int curr_deals=HistoryOrdersTotal();
int curr_history_orders=HistoryDealsTotal();
//--- affiche le nombre d'ordres, de positions, de transactions ainsi que les changements entre parenthèses
PrintFormat("PositionsTotal() = %d (%+d)",
curr_positions,(curr_positions-prev_positions));
PrintFormat("OrdersTotal() = %d (%+d)",
curr_orders,curr_orders-prev_orders);
PrintFormat("HistoryOrdersTotal() = %d (%+d)",
curr_deals,curr_deals-prev_deals);
PrintFormat("HistoryDealsTotal() = %d (%+d)",
curr_history_orders,curr_history_orders-prev_history_orders);
//--- insère une séparation pour aider à la lecture du journal
Print("");
//--- sauvegarde le statut du compte
prev_positions=curr_positions;
prev_orders=curr_orders;
prev_deals=curr_deals;
prev_history_orders=curr_history_orders;
//---
}
//+------------------------------------------------------------------+
//| Fonction ChartEvent |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- gère l'évènement CHARTEVENT_CLICK ("Clic sur le graphique")
if(id==CHARTEVENT_OBJECT_CLICK)
{
Print("=> ",__FUNCTION__,": sparam = ",sparam);
//--- volume minimum pour une transaction
double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
//--- si le bouton "Buy" est utilisé, alors achat
if(sparam=="Buy")
{
PrintFormat("Buy %s %G lot",_Symbol,volume_min);
BuyAsync(volume_min);
//--- relâche le bouton
ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
}
//--- si le bouton "Sell" est utilisé, alors vente
if(sparam=="Sell")
{
PrintFormat("Sell %s %G lot",_Symbol,volume_min);
SellAsync(volume_min);
//--- relâche le bouton
ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
}
ChartRedraw();
}
//---
}
//+------------------------------------------------------------------+
//| Retourne la description textuelle d'une transaction |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans,
const bool detailed=true)
{
//--- prépare une chaîne de caractère pour le retour de la fonction
string desc=EnumToString(trans.type)+"\r\n";
//--- toutes les données possibles sont ajoutées dans le mode détaillé
if(detailed)
{
desc+="Symbole : "+trans.symbol+"\r\n";
desc+="Ticket de la transaction : "+(string)trans.deal+"\r\n";
desc+="Type de la transaction : "+EnumToString(trans.deal_type)+"\r\n";
desc+="Ticket de l'ordre : "+(string)trans.order+"\r\n";
desc+="Type de l'ordre : "+EnumToString(trans.order_type)+"\r\n";
desc+="Etat de l'ordre : "+EnumToString(trans.order_state)+"\r\n";
desc+="Type d'heure de l'ordre : "+EnumToString(trans.time_type)+"\r\n";
desc+="Expiration de l'ordre : "+TimeToString(trans.time_expiration)+"\r\n";
desc+="Prix : "+StringFormat("%G",trans.price)+"\r\n";
desc+="Prix de déclenchement : "+StringFormat("%G",trans.price_trigger)+"\r\n";
desc+="Stop Loss : "+StringFormat("%G",trans.price_sl)+"\r\n";
desc+="Take Profit : "+StringFormat("%G",trans.price_tp)+"\r\n";
desc+="Volume : "+StringFormat("%G",trans.volume)+"\r\n";
}
//--- retourne la chaîne de caractères
return desc;
}
//+------------------------------------------------------------------+
//| Retourne la description textuelle de la demande de trade |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request,
const bool detailed=true)
{
//--- prépare une chaîne de caractère pour le retour de la fonction
string desc=EnumToString(request.action)+"\r\n";
//--- ajoute toutes les données disponibles en mode détaillé
if(detailed)
{
desc+="Symbole : "+request.symbol+"\r\n";
desc+="Magic Number : "+StringFormat("%d",request.magic)+"\r\n";
desc+="Ticket de l'ordre : "+(string)request.order+"\r\n";
desc+="Type de l'ordre : "+EnumToString(request.type)+"\r\n";
desc+="Remplissage de l'ordre : "+EnumToString(request.type_filling)+"\r\n";
desc+="Type d'heure de l'ordre : "+EnumToString(request.type_time)+"\r\n";
desc+="Expiration de l'ordre : "+TimeToString(request.expiration)+"\r\n";
desc+="Prix : "+StringFormat("%G",request.price)+"\r\n";
desc+="Points de déviation : "+StringFormat("%G",request.deviation)+"\r\n";
desc+="Stop Loss : "+StringFormat("%G",request.sl)+"\r\n";
desc+="Take Profit : "+StringFormat("%G",request.tp)+"\r\n";
desc+="Stop Limit : "+StringFormat("%G",request.stoplimit)+"\r\n";
desc+="Volume : "+StringFormat("%G",request.volume)+"\r\n";
desc+="Commentaire : "+request.comment+"\r\n";
}
//--- retourne la chaîne de caractères
return desc;
}
//+------------------------------------------------------------------+
//| Retourne la description du résultat du traitement de la demande |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result,
const bool detailed=true)
{
//--- prépare une chaîne de caractère pour le retour de la fonction
string desc="Retcode "+(string)result.retcode+"\r\n";
//--- ajoute toutes les données disponibles en mode détaillé
if(detailed)
{
desc+="Identifiant de la demande : "+StringFormat("%d",result.request_id)+"\r\n";
desc+="Ticket de l'ordre : "+(string)result.order+"\r\n";
desc+="Ticket de la transaction : "+(string)result.deal+"\r\n";
desc+="Volume : "+StringFormat("%G",result.volume)+"\r\n";
desc+="Prix : "+StringFormat("%G",result.price)+"\r\n";
desc+="Ask : "+StringFormat("%G",result.ask)+"\r\n";
desc+="Bid : "+StringFormat("%G",result.bid)+"\r\n";
desc+="Commentaire : "+result.comment+"\r\n";
}
//--- retourne la chaîne de caractères
return desc;
}
//+------------------------------------------------------------------+
//| Crée 2 boutons pour acheter et vendre |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
{
//--- vérifie l'objet nommé "Buy"
if(ObjectFind(0,"Buy")>=0)
{
//--- si l'objet trouvé n'est pas un bouton, le supprime
if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Buy");
}
else
ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // crée le bouton "Buy"
//--- configure le bouton "Buy"
ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);
//--- vérifie la présence de l'objet nommé "Sell"
if(ObjectFind(0,"Sell")>=0)
{
//--- si l'objet trouvé n'est pas un bouton, le supprime
if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Sell");
}
else
ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // crée le bouton "Sell"
//--- configure le bouton "Sell"
ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);
//--- force la mise à jour du graphique pour afficher les boutons immédiatement
ChartRedraw();
//---
}
//+------------------------------------------------------------------+
//| Achat avec la fonction asynchrone OrderSendAsync() |
//+------------------------------------------------------------------+
void BuyAsync(double volume)
{
//--- prépare la requête
MqlTradeRequest req={};
req.action =TRADE_ACTION_DEAL;
req.symbol =_Symbol;
req.magic =MagicNumber;
req.volume =0.1;
req.type =ORDER_TYPE_BUY;
req.price =SymbolInfoDouble(req.symbol,SYMBOL_ASK);
req.deviation =10;
req.comment ="Achat avec OrderSendAsync()";
MqlTradeResult res={};
if(!OrderSendAsync(req,res))
{
Print(__FUNCTION__," : erreur ",GetLastError(),", retcode = ",res.retcode);
}
//---
}
//+------------------------------------------------------------------+
//| Vente avec la fonction asynchrone OrderSendAsync() |
//+------------------------------------------------------------------+
void SellAsync(double volume)
{
//--- prépare la requête
MqlTradeRequest req={};
req.action =TRADE_ACTION_DEAL;
req.symbol =_Symbol;
req.magic =MagicNumber;
req.volume =0.1;
req.type =ORDER_TYPE_SELL;
req.price =SymbolInfoDouble(req.symbol,SYMBOL_BID);
req.deviation =10;
req.comment ="Vente avec OrderSendAsync()";
MqlTradeResult res={};
if(!OrderSendAsync(req,res))
{
Print(__FUNCTION__," : erreur ",GetLastError(),", retcode = ",res.retcode);
}
//---
}
//+------------------------------------------------------------------+
|