English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Création et publication des rapports de trade et de notifications par SMS

Création et publication des rapports de trade et de notifications par SMS

MetaTrader 5Exemples | 16 novembre 2021, 15:37
138 0
Denis Zyatkevich
Denis Zyatkevich

Introduction

Cet article décrit comment générer un rapport des résultats du trade (à l'aide d'Expert Advisor, d'un indicateur ou d'un script) sous forme de fichier HTML et le télécharger via FTP sur le serveur WWW. Nous envisagerons également d'envoyer des notifications d'événements de trade sous forme de SMS sur un téléphone mobile.

Pour être plus à l'aise avec le matériel décrit dans cet article, il est recommandé au lecteur de se familiariser avec le langage HTML (HyperText Markup Language).

Pour implémenter les rapports de téléchargement, nous avons besoin d'un serveur WWW (cela peut être n'importe quel ordinateur), qui peut accepter les données via FTP. Pour mettre en œuvre la possibilité de recevoir des notifications sur les événements de trade sous forme de SMS, nous avons besoin d'une passerelle EMAIL-SMS (ce service est fourni par la plupart des opérateurs mobiles et des organisations tierces).

1. Créer un Rapport et l' Envoyer via FTP

Créons un programme MQL5, qui génère un rapport de trade et l'envoie via le protocole FTP. D'abord, nous le rédigeons comme un script. À l'avenir, nous pouvons l'utiliser comme un bloc fini, qui peut être introduit dans les Expert Advisors et les Indicateurs. Par exemple, dans Expert Advisers, vous pouvez utiliser ce bloc comme gestionnaire d'événement du Trade ou Timer, pour exécuter ce bloc après la demande de trade, ou pour définir certaines actions pour l'événement ChartEvent. Dans Indicateurs, vous pouvez inclure ce bloc dans les gestionnaires d'événements Timer ou ChartEvent.

L'exemple de rapport, créé par programme, est illustré dans les figures 1, 2 et 3. Ou vous pouvez télécharger ce rapport via un lien qui se trouve à la fin de l’article.

Figure 1. Exemple de rapport - Tableau des deals et des positions.

Figure 1. Exemple de rapport - Tableau des Deals et des Positions.

 Figure 2. Exemple de rapport - Tableau de solde.

Figure 2. Exemple de rapport - Tableau de solde.

 Figure 3. Exemple de rapport - Graphique des prix sur l'instrument actuel.

Figure 3. Exemple de rapport - Graphique des prix sur l'instrument actuel.

Dans le tableau des deals et des positions (Figure 1), tous les deals par commodité sont divisées en positions. Le côté gauche du tableau indique le volume, le temps et le prix pour entrer sur le marché (des positions d'ouverture et des additions). La partie droite du tableau indique les mêmes paramètres pour quitter le marché (clôture partielle ou totale de la position). Lors de l'entrée/sortie, le deal est divisé en deux parties - la clôture d'une position et l'ouverture de la suivante.

Sous le tableau des deals et des positions apparaît le graphique du solde (axe horizontal - temps), et en bas - le graphique des prix de l'instrument actuel.

Le programme crée les fichiers "report.html", "picture1.gif" et "picture2.gif" (fichier html du rapport, fichiers image du tableau de solde et du tableau des prix) dans le dossier MetaTarder5_istall_dir\MQL5\Files. Et la publication FTP est activée dans les paramètres du terminal - elle envoie ces trois fichiers au serveur indiqué. De plus, nous aurons besoin de deux autres fichiers - des images avec des flèches désignant la position ouverte - Acheter ou Vendre ("buy.gif" et "sell.gif"). Vous pouvez prendre ces images (lien de téléchargement en fin d'article) ou les dessiner vous-même dans n'importe quel éditeur graphique. Ces deux fichiers doivent être placés dans le même dossier du serveur WWW avec le fichier "report.html".

Comme paramètres d'entrée, le programme accepte l'heure de début et de fin de la période pour laquelle le rapport est généré. Dans notre exemple, la fin de la période du rapport est l'heure actuelle et l'utilisateur sélectionne la variante de la période du rapport : période entière, dernier jour, semaine dernière, mois dernier ou année dernière.

Quelques mots sur la façon dont le rapport est créé. Le serveur du trade est demandé pour tout l'historique disponible des deals. Les deals obtenus sont traités les uns après les autres. Le tableau deal_status[] stocke des informations indiquant si le deal est traité ou pas. Les index d'éléments de ce tableau sont les numéros de deals, reçus de la liste des deals depuis le serveur du trade. Et les valeurs des éléments sont interprétées comme suit : 0 - le deal n'a pas encore été traité, 1 - le deal a déjà été partiellement traité (entrée/sortie), 127 - le deal a déjà été traité (les autres valeurs ne sont pas utilisées et réservées pour une utilisation future).

Le tableau symb_list[] comporte la liste des noms d'instruments financiers, par lesquels le trade a été effectué, et le tableau lots_list[] - volumes des positions ouvertes pour chaque instrument au moment du traitement du deal. Les valeurs positives du volume correspondent aux positions longues, négatives - aux positions courtes. Si le volume est égal à zéro, cela indique que cet outil n'a pas de positions ouvertes. Si, lors du traitement des deals, un instrument financier qui n'est pas dans la liste (dans le tableau symb_list[]) est rencontré - il y est ajouté et le nombre d'instruments financiers (la variable symb_total) est incrémenté par 1.

Sur chaque traitement de deal, chaque deal suivant est analysé par le même instrument financier, jusqu'à la clôture de la position ou jusqu'à l'entrée/sortie. Seuls les deals sont analysés, pour lesquels la valeur du tableau deal_status[] est inférieure à 127. Après le traitement du deal, l'élément correspondant du tableau deal_status[] est affecté avec la valeur 127, et si le deal est l'entrée/sortie de position - avec la valeur 1. Si l'heure, lorsque la position a été ouverte, correspond à la période du rapport (définie par les variables StartTime et EndTime) - cette position est enregistrée dans le rapport (toutes les entrées et sorties).

En plus du tableau des deals, un nouveau graphique pour l'instrument financier actuel est ouvert. Pour ce graphique, toutes les propriétés nécessaires sont fournies et, à l'aide de la fonction ChartScreenShot(), une capture d'écran est réalisée - nous obtenons donc un fichier image avec le graphique des prix pour l'instrument actuel. Ensuite, sur ce graphique, le graphique des prix est masqué et le graphique des variations du solde est dessiné, puis une autre capture d'écran est créée.

Lorsque deux fichiers image avec des graphiques et un fichier HTML avec rapport sont créés, la possibilité d'envoyer des fichiers via FTP est vérifiée. Si cela est autorisé - les fichiers "report.html", "picture1.gif" et "picture2.gif" sont envoyés à l'aide de la fonction SendFTP(), conformément aux paramètres indiqués dans MetaTrader 5.

Lancez l'éditeur de langue MetaQuotes et commencez la création du script. Définissez des constantes : le délai d'expiration de l'actualisation du graphique (en secondes), la largeur et la hauteur du graphique des prix et la largeur maximale du graphique de solde. La période du graphique, qui affichera la courbe d'évolution du solde, est choisie en fonction de la durée de la période du rapport et de la largeur maximale du graphique. La largeur du graphique est ajustée à la taille, nécessaire pour le graphique du solde.

La hauteur du graphique est automatiquement calculée comme la moitié de la largeur. De plus, nous indiquerons la largeur de l'axe vertical comme constante - c'est le nombre de pixels par lequel la zone graphique est réduite par rapport à la largeur de l'image en raison de l'axe vertical.

#define timeout 10           // chart refresh timeout
#define Picture1_width 800   // max width of chart in report
#define Picture2_width 800   // width of price chart in report
#define Picture2_height 600  // height of price chart in report
#define Axis_Width 59        // width of vertical axis (in pixels)

Précisez que les paramètres d'entrée seront demandés à l'utilisateur.

// request input parameters
#property script_show_inputs

Créez une énumération des périodes de rapport.

// enumeration of report periods
enum report_periods
  {
   All_periods,
   Last_day,
   Last_week,
   Last_month,
   Last_year
  };

Demandez à l'utilisateur la période du rapport (par défaut, il s'agit de la période entière).

// ask for report period
input report_periods ReportPeriod=0;

Écrivez le corps de la fonction OnStart().

void OnStart()
  {

Déterminez le début et la fin de la période de rapport.

  datetime StartTime=0;           // beginning of report period
  datetime EndTime=TimeCurrent(); // end of report period

  // calculating the beginning of report period
  switch(ReportPeriod)
    {
     case 1:
        StartTime=EndTime-86400;    // day
        break;
     case 2:
        StartTime=EndTime-604800;   // week
        break;
     case 3:
        StartTime=EndTime-2592000;  // month
        break;
     case 4:
        StartTime=EndTime-31536000; // year
        break;
    }
  // if none of the options is executed, then StartTime=0 (entire period)

Déclarez les variables qui seront utilisées dans le programme. Le but des variables est décrit dans les commentaires.

   int total_deals_number;  // number of deals for history data
   int file_handle;         // file handle
   int i,j;                 // loop counters 
   int symb_total;          // number of instruments, that were traded
   int symb_pointer;        // pointer to current instrument
   char deal_status[];      // state of deal (processed/not processed)
   ulong ticket;            // ticket of deal
   long hChart;             // chart id

   double balance;           // current balance value
   double balance_prev;      // previous balance value
   double lot_current;       // volume of current deal
   double lots_list[];       // list of open volumes by instruments
   double current_swap;      // swap of current deal
   double current_profit;    // profit of current deal
   double max_val,min_val;   // maximal and minimal value
   
   string symb_list[];       // list of instruments, that were traded
   string in_table_volume;   // volume of entering position
   string in_table_time;     // time of entering position
   string in_table_price;    // price of entering position
   string out_table_volume;  // volume of exiting position
   string out_table_time;    // time of exiting position
   string out_table_price;   // price of exiting position
   string out_table_swap;    // swap of exiting position
   string out_table_profit;  // profit of exiting position

   bool symb_flag;           // flag that instrument is in the list

   datetime time_prev;           // previous value of time
   datetime time_curr;           // current value of time
   datetime position_StartTime;  // time of first enter to position
   datetime position_EndTime;    // time of last exit from position
   
   ENUM_TIMEFRAMES Picture1_period;  // period of balance chart

Ouvrez un nouveau graphique et définissez ses propriétés - il s'agit du graphique des prix, qui sera affiché au bas du rapport.

 // open a new chart and set its properties
hChart=ChartOpen(Symbol(),0);
ChartSetInteger(hChart,CHART_MODE,CHART_BARS);            // bars chart
ChartSetInteger(hChart,CHART_AUTOSCROLL,true);            // autoscroll enabled
ChartSetInteger(hChart,CHART_COLOR_BACKGROUND,White);     // white background
ChartSetInteger(hChart,CHART_COLOR_FOREGROUND,Black);     // axes and labels are black
ChartSetInteger(hChart,CHART_SHOW_OHLC,false);            // OHLC are not shown
ChartSetInteger(hChart,CHART_SHOW_BID_LINE,true);         // show BID line
ChartSetInteger(hChart,CHART_SHOW_ASK_LINE,false);        // hide ASK line
ChartSetInteger(hChart,CHART_SHOW_LAST_LINE,false);       // hide LAST line
ChartSetInteger(hChart,CHART_SHOW_GRID,true);             // show grid
ChartSetInteger(hChart,CHART_SHOW_PERIOD_SEP,true);       // show period separators
ChartSetInteger(hChart,CHART_COLOR_GRID,LightGray);       // grid is light-gray
ChartSetInteger(hChart,CHART_COLOR_CHART_LINE,Black);     // chart lines are black
ChartSetInteger(hChart,CHART_COLOR_CHART_UP,Black);       // up bars are black
ChartSetInteger(hChart,CHART_COLOR_CHART_DOWN,Black);     // down bars are black
ChartSetInteger(hChart,CHART_COLOR_BID,Gray);             // BID line is gray
ChartSetInteger(hChart,CHART_COLOR_VOLUME,Green);         // volumes and orders levels are green
ChartSetInteger(hChart,CHART_COLOR_STOP_LEVEL,Red);       // SL and TP levels are red
ChartSetString(hChart,CHART_COMMENT,ChartSymbol(hChart)); // comment contains instrument <end segm

Faites une capture d’écran et enregistrez-la sous le nom "picture2.gif".

// save chart as image file
ChartScreenShot(hChart,"picture2.gif",Picture2_width,Picture2_height);

Demandez l'historique des deals pour toute la durée d'existence du compte.

// request deals history for entire period
HistorySelect(0,TimeCurrent());

Ouvrez le fichier "report.html", dans lequel nous écrirons la page HTML avec le rapport (encodage ANSI).

// open report file
file_handle=FileOpen("report.html",FILE_WRITE|FILE_ANSI);

Écrivez le début du document HTML :

  • début du document html (<html>)
  • titre qui sera affiché en haut de la fenêtre de votre navigateur (<head><title>Expert Trade Report</title></head>)
  • début de la partie principale du document html avec la couleur d'arrière-plan (<body bgcolor='#EFEFEF'>)
  • alignement du centre (<center>)
  • titre du tableau des deals et des positions (<h2>Trade Report</h2>)
  • début du tableau des deals et des positions avec alignement, largeur de la bordure, couleur d'arrière-plan, couleur de la bordure, espacement des cellules et remplissage des cellules (<table align='center' border='1' bgcolor='#FFFFFF' bordercolor='#7F7FFF' cellspacing ='0' cellpadding='0'>)
  • en-tête de tableau 
// write the beginning of HTML
   FileWrite(file_handle,"<html>"+
                           "<head>"+
                              "<title>Expert Trade Report</title>"+
                           "</head>"+
                              "<body bgcolor='#EFEFEF'>"+
                              "<center>"+
                              "<h2>Trade Report</h2>"+
                              "<table align='center' border='1' bgcolor='#FFFFFF' bordercolor='#7F7FFF' cellspacing='0' cellpadding='0'>"+
                                 "<tr>"+
                                    "<th rowspan=2>SYMBOL</th>"+
                                    "<th rowspan=2>Direction</th>"+
                                    "<th colspan=3>Open</th>"+
                                    "<th colspan=3>Close</th>"+
                                    "<th rowspan=2>Swap</th>"+
                                    "<th rowspan=2>Profit</th>"+
                                 "</tr>"+
                                 "<tr>"+
                                    "<th>Volume</th>"+
                                    "<th>Time</th>"+
                                    "<th>Price</th>"+
                                    "<th>Volume</th>"+
                                    "<th>Time</th>"+
                                    "<th>Price</th>"+
                                 "</tr>");

Obtenir le nombre des deals dans la liste.

// number of deals in history
total_deals_number=HistoryDealsTotal();

Définition des dimensions des tableaux symb_list[], lots_list[] et deal_status[].

// setting dimensions for the instruments list, the volumes list and the deals state arrays
ArrayResize(symb_list,total_deals_number);
ArrayResize(lots_list,total_deals_number);
ArrayResize(deal_status,total_deals_number);

Initialisation de tous les éléments du tableau deal_status[] avec la valeur 0 - tous les deals ne sont pas traités.

// setting all elements of array with value 0 - deals are not processed
ArrayInitialize(deal_status,0);

Réglage des valeurs initiales du solde et de la variable, utilisé pour stocker la valeur précédente du solde.

balance=0;       // initial balance
balance_prev=0;  // previous balance

Réglage de la valeur initiale de la variable, utilisé pour stocker le nombre d'instruments financiers dans la liste.

// number of instruments in the list
symb_total=0;

Créez une boucle qui traite séquentiellement chaque deal de la liste.

// processing all deals in history
for(i=0;i<total_deals_number;i++)
  {

Sélectionnez le deal en cours et obtenez son billet.

//select deal, get ticket
ticket=HistoryDealGetTicket(i);

Modification du solde par le montant du profit dans le deal en cours.

// changing balance
balance+=HistoryDealGetDouble(ticket,DEAL_PROFIT);

Obtenir l'heure du deal -elle sera utilisée fréquemment plus loin.

// reading the time of deal
time_curr=HistoryDealGetInteger(ticket,DEAL_TIME);

S'il s'agit du premier deal de la liste, nous devons ajuster les limites de la période du rapport et sélectionner la période pour le graphique du solde, en fonction de la durée de la période du rapport et de la largeur de la région dans laquelle le graphique sera tracé. Définition des valeurs initiales, des soldes maximal et minimal (ces variables seront utilisées pour définir le maximum et le minimum du graphique.)

// if this is the first deal
if(i==0)
  {
   // if the report period starts before the first deal,
   // then the report period will start from the first deal
   if(StartTime<time_curr) StartTime=time_curr;
   // if report period ends before the current time,
   // then the end of report period corresponds to the current time
   if(EndTime>TimeCurrent()) EndTime=TimeCurrent();
   // initial values of maximal and minimal balances
   // are equal to the current balance
   max_val=balance;
   min_val=balance;
   // calculating the period of balance chart depending on the duration of
   // report period
   Picture1_period=PERIOD_M1;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)) Picture1_period=PERIOD_M2;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*120) Picture1_period=PERIOD_M3;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*180) Picture1_period=PERIOD_M4;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*240) Picture1_period=PERIOD_M5;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*300) Picture1_period=PERIOD_M6;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*360) Picture1_period=PERIOD_M10;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*600) Picture1_period=PERIOD_M12;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*720) Picture1_period=PERIOD_M15;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*900) Picture1_period=PERIOD_M20;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*1200) Picture1_period=PERIOD_M30;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*1800) Picture1_period=PERIOD_H1;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*3600) Picture1_period=PERIOD_H2;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*7200) Picture1_period=PERIOD_H3;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*10800) Picture1_period=PERIOD_H4;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*14400) Picture1_period=PERIOD_H6;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*21600) Picture1_period=PERIOD_H8;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*28800) Picture1_period=PERIOD_H12;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*43200) Picture1_period=PERIOD_D1;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*86400) Picture1_period=PERIOD_W1;
   if(EndTime-StartTime>(Picture1_width-Axis_Width)*604800) Picture1_period=PERIOD_MN1;
   // changing the period of opened chart
   ChartSetSymbolPeriod(hChart,Symbol(),Picture1_period);
  }

Si ce deal n'est pas le premier, créez l'objet "ligne", à l'aide duquel le graphique de l'évolution du solde est tracé. La ligne n'est tracée que si au moins une de ses extrémités se situe dans la période du rapport. Si les deux extrémités se trouvent dans la période du rapport, la ligne sera « épaisse ». La couleur de la ligne de l’équilibre est verte. Si l'équilibre est au-delà de la plage d'équilibre minimal et maximal - cette plage est ajustée.

else
  // if this is not the first deal
  {
   // plotting the balance line, if the deal is in the report period,
   // and setting properties of the balance line
   if(time_curr>=StartTime && time_prev<=EndTime)
     {
      ObjectCreate(hChart,IntegerToString(i),OBJ_TREND,0,time_prev,balance_prev,time_curr,balance);
      ObjectSetInteger(hChart,IntegerToString(i),OBJPROP_COLOR,Green);
      // if both ends of line are in the report period,
      // it will be "thick"
      if(time_prev>=StartTime && time_curr<=EndTime)
        ObjectSetInteger(hChart,IntegerToString(i),OBJPROP_WIDTH,2);
     }
   // if new value of balance exceeds the range
   // of minimal and maximal values, it must be adjusted
   if(balance<min_val) min_val=balance;
   if(balance>max_val) max_val=balance;
  }

Attribuez la valeur précédente du temps à la variable correspondante.

// changing the previous time value
time_prev=time_curr;

Si le deal n'a pas encore été traité, traitez-le.

// if the deal has not been processed yet
if(deal_status[i]<127)
  {

Si ce deal est une charge de solde et qu'il se situe dans la période du rapport, la chaîne correspondante est écrite pour le rapport. La deal est marqué comme traité.

// If this deal is balance charge
if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BALANCE)
  {
   // if it's in the report period - write the corresponding string to report.
   if(time_curr>=StartTime && time_curr<=EndTime)
     FileWrite(file_handle,"<tr><td colspan='9'>Balance:</td><td align='right'>",HistoryDealGetDouble(ticket,DEAL_PROFIT),
     "</td></tr>");
   // mark deal as processed
   deal_status[i]=127;
  }

Si ce deal est Acheter ou Vendre, vérifiez si cet instrument est dans la liste (tableau symb_list[]). Sinon, mettez-le là-bas La variable symb_pointer pointe vers l'élément du tableau symb_list[], qui contient le nom de l'instrument du deal en cours.

// if this deal is buy or sell
if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BUY || HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_SELL)
  {
   // check if there is instrument of this deal in the list
   symb_flag=false;
   for(j=0;j<symb_total;j++)
     {
      if(symb_list[j]==HistoryDealGetString(ticket,DEAL_SYMBOL))
        {
         symb_flag=true;
         symb_pointer=j;
        }
     }
   // if there is no instrument of this deal in the list
   if(symb_flag==false)
     {
      symb_list[symb_total]=HistoryDealGetString(ticket,DEAL_SYMBOL);
      lots_list[symb_total]=0;
      symb_pointer=symb_total;
      symb_total++;
     }

Définissez les valeurs initiales des variables position_StartTime et position_EndTime, qui stockent la durée de vie de la position initiale et finale.

// set the initial value for the beginning time of deal
position_StartTime=time_curr;
// set the initial value for the end time of deal
position_EndTime=time_curr;

Les variables in_table_volume, in_table_time, in_table_price, out_table_volume, out_table_time, out_table_price, out_table_swap et out_table_profit stockeront des tableaux, qui seront à l'intérieur des cellules d'un tableau plus grand : volume, heure et prix d'entrée sur le marché ; volume, temps, prix, swap et profit de la sortie du marché. La variable in_table_volume stockera également le nom de l'instrument financier et un lien vers une image, qui correspond à la direction de la position ouverte. Attribuez à toutes ces variables des valeurs initiales.

// creating the string in report - instrument, position direction, beginning of table for volumes to enter the market
if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BUY)
   StringConcatenate(in_table_volume,"<tr><td align='left'>",symb_list[symb_pointer],
   "</td><td align='center'><img src='buy.gif'></td><td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>");

if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_SELL)
   StringConcatenate(in_table_volume,"<tr><td align='left'>",symb_list[symb_pointer],
   "</td><td align='center'><img src='sell.gif'></td><td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>");
// creating the beginning of time table to enter the market
in_table_time="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of price table to enter the market
in_table_price="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of volume table to exit the market
out_table_volume="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of time table to exit the market
out_table_time="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of price table to exit the market
out_table_price="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of swap table to exit the market
out_table_swap="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";
// creating the beginning of profit table to exit the market
out_table_profit="<td><table border='1' width='100%' bgcolor='#FFFFFF' bordercolor='#DFDFFF'>";

Traitez tous les deals en commençant par le deal actuel jusqu'à ce que la position soit clôturée. Traitez-les tous, s'ils n'ont pas été traités plus tôt.

// process all deals for this position starting with the current(until position is closed)
for(j=i;j<total_deals_number;j++)
  {
   // if the deal has not been processed yet - process it
   if(deal_status[j]<127)
     {

Sélectionnez le deal et obtenez son billet.

// select deal, get ticket
ticket=HistoryDealGetTicket(j);

Si le deal porte sur le même instrument que la position ouverte, traitez-le. Obtenez le temps du deal. Si le temps de deal dépasse la plage de temps de position, étendez la plage. Obtenez le volume du deal.

// if the instrument of deal matches the instrument of position, that is processed
if(symb_list[symb_pointer]==HistoryDealGetString(ticket,DEAL_SYMBOL))
  {
   // get the deal time
   time_curr=HistoryDealGetInteger(ticket,DEAL_TIME);
   // If the deal time goes beyond the range of position time
   // - extend position time
   if(time_curr<position_StartTime) position_StartTime=time_curr;
   if(time_curr>position_EndTime) position_EndTime=time_curr;
   // get the volume of deal
   lot_current=HistoryDealGetDouble(ticket,DEAL_VOLUME);

Les deals d'achat et de vente sont traités séparément. Commencez par les deals d'achat.

// if this deal is buy
if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BUY)
  {

Si vous avez déjà ouvert une position pour la vente, ce deal pour l'achat quittera le marché. Et si le volume du deal est supérieur au volume de la position courte ouverte, ce sera l'entrée/sortie. Attribuez des variables de chaîne avec les valeurs requises. Affectez au tableau deal_status[] la valeur 127, si le deal est entièrement traité, ou la valeur 1 s'il s'agit de l'entrée/sortie, et ce deal doit être analysé pour une autre position.

// if position is opened for sell - this will be exit from market
if(NormalizeDouble(lots_list[symb_pointer],2)<0)
  {
   // if buy volume is greater than volume of opened short position - then this is in/out
   if(NormalizeDouble(lot_current+lots_list[symb_pointer],2)>0)
     {
      // creating table of volumes to exit the market - indicate only volume of opened short position
      StringConcatenate(out_table_volume,out_table_volume,"<tr><td align='right'>",DoubleToString(-lots_list[symb_pointer],2),"</td></tr>");
      // mark position as partially processed
      deal_status[j]=1;
     }
   else
     {
      // if buy volume is equal or less than volume of opened short position - then this is partial or full close
      // creating the volume table to exit the market
      StringConcatenate(out_table_volume,out_table_volume,"<tr><td align='right'>",DoubleToString(lot_current,2),"</td></tr>");
      // mark deal as processed
      deal_status[j]=127;
     }

   // creating the time table to exit the market
   StringConcatenate(out_table_time,out_table_time,"<tr><td align='center'>",TimeToString(time_curr,TIME_DATE|TIME_SECONDS),"</td></tr>");

   // creating the price table to exit the market
   StringConcatenate(out_table_price,out_table_price,"<tr><td align='center'>",DoubleToString(HistoryDealGetDouble(ticket,DEAL_PRICE),
   (int)SymbolInfoInteger(symb_list[symb_pointer],SYMBOL_DIGITS)),"</td></tr>");

   // get the swap of current deal
   current_swap=HistoryDealGetDouble(ticket,DEAL_SWAP);

   // if swap is equal to zero - create empty string of the swap table to exit the market
   if(NormalizeDouble(current_swap,2)==0) StringConcatenate(out_table_swap,out_table_swap,"<tr></tr>");
   // else create the swap string in the swap table to exit the market
   else StringConcatenate(out_table_swap,out_table_swap,"<tr><td align='right'>",DoubleToString(current_swap,2),"</td></tr>");

   // get the profit of current deal
   current_profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);

   // if profit is negative (loss) - it is displayed as red in the profit table to exit the market
   if(NormalizeDouble(current_profit,2)<0) StringConcatenate(out_table_profit,out_table_profit,"<tr><td align=right><SPAN style='COLOR: #EF0000'>",
   DoubleToString(current_profit,2),"</SPAN></td></tr>");
   // else - it is displayed as green
   else StringConcatenate(out_table_profit,out_table_profit,"<tr><td align='right'><SPAN style='COLOR: #00EF00'>",
        DoubleToString(current_profit,2),"</SPAN></td></tr>");
  }

Si vous avez déjà ouvert une position longue, l'achat de ce deal sera l'entrée sur le marché (le premier ou l'ajout). Si l'élément de tableau deal_status[], qui correspond à ce deal, a la valeur 1 - cela indique que l'entrée/sortie a été effectuée. Affectez des variables de chaîne avec les valeurs requises et marquez le deal comme traité (affectez l'élément correspondant du tableau deal_status[] avec la valeur 127).

else
   // if position is opened for buy - this will be the enter to the market
   {
    // if this deal has been already partially processed (in/out)
    if(deal_status[j]==1)
      {
       // create the volume table of entering the market (volume, formed after in/out, is put here)
       StringConcatenate(in_table_volume,in_table_volume,"<tr><td align='right'>",DoubleToString(lots_list[symb_pointer],2),"</td></tr>");
       // indemnity of volume change, which will be produced (the volume of this deal is already taken into account)
       lots_list[symb_pointer]-=lot_current;
      }
    // if this deal has not been processed yet, create the volume table to enter the market
    else StringConcatenate(in_table_volume,in_table_volume,"<tr><td align='right'>",DoubleToString(lot_current,2),"</td></tr>");

    // creating the time table of entering the market
    StringConcatenate(in_table_time,in_table_time,"<tr><td align center>",TimeToString(time_curr,TIME_DATE|TIME_SECONDS),"</td></tr>");

    // creating the price table of entering the market
    StringConcatenate(in_table_price,in_table_price,"<tr><td align='center'>",DoubleToString(HistoryDealGetDouble(ticket,DEAL_PRICE),
    (int)SymbolInfoInteger(symb_list[symb_pointer],SYMBOL_DIGITS)),"</td></tr>");

    // mark deal as processed
    deal_status[j]=127;
   }

Remplacez le volume de la position par le volume du deal actuelle. Si la position est fermée (le volume est égal à zéro) - arrêtez le traitement de cette position (sortez de la boucle avec la variable j) et recherchez le prochain deal non traité (dans la boucle avec la variable i).

 // change of position volume by the current instrument, taking into account the volume of current deal
 lots_list[symb_pointer]+=lot_current;
 // if the volume of opened position by the current instrument became equal to zero - position is closed
 if(NormalizeDouble(lots_list[symb_pointer],2)==0 || deal_status[j]==1) break;
}

Les deals de vente sont traitées de la même manière, puis nous sortons de la boucle avec la variable j.

       // if this deal is sell
       if(HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_SELL)
         {
          // if position has been already opened for buy - this will be the exit from market
          if(NormalizeDouble(lots_list[symb_pointer],2)>0)
            {
             // if sell volume is greater than volume of opened long position - then this is in/out
             if(NormalizeDouble(lot_current-lots_list[symb_pointer],2)>0)
               {
                // creating table of volumes to exit the market - indicate only volume of opened long position
                StringConcatenate(out_table_volume,out_table_volume,"<tr><td align='right'>",DoubleToString(lots_list[symb_pointer],2),"</td></tr>");
                // mark position as partially processed
                deal_status[j]=1;
               }
             else
               {
                // if sell volume is equal or greater than volume of opened short position - then this is partial or full close
                // creating the volume table to exit the market
                StringConcatenate(out_table_volume,out_table_volume,"<tr><td align='right'>",DoubleToString(lot_current,2),"</td></tr>");
                // mark deal as processed
                deal_status[j]=127;
               }

             // creating the time table to exit the market
             StringConcatenate(out_table_time,out_table_time,"<tr><td align='center'>",TimeToString(time_curr,TIME_DATE|TIME_SECONDS),"</td></tr>");

             // creating the price table to exit the market
             StringConcatenate(out_table_price,out_table_price,"<tr><td align='center'>",DoubleToString(HistoryDealGetDouble(ticket,DEAL_PRICE),
             (int)SymbolInfoInteger(symb_list[symb_pointer],SYMBOL_DIGITS)),"</td></tr>");

             // get the swap of current deal
             current_swap=HistoryDealGetDouble(ticket,DEAL_SWAP);

             // if swap is equal to zero - create empty string of the swap table to exit the market
             if(NormalizeDouble(current_swap,2)==0) StringConcatenate(out_table_swap,out_table_swap,"<tr></tr>");
             // else create the swap string in the swap table to exit the market
             else StringConcatenate(out_table_swap,out_table_swap,"<tr><td align='right'>",DoubleToString(current_swap,2),"</td></tr>");

             // get the profit of current deal
             current_profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);

             // if profit is negative (loss) - it is displayed as red in the profit table to exit the market
             if(NormalizeDouble(current_profit,2)<0) StringConcatenate(out_table_profit,out_table_profit,"<tr><td align='right'>
             <SPAN style='COLOR: #EF0000'>",DoubleToString(current_profit,2),"</SPAN></td></tr>");
             // else - it is displayed as green
             else StringConcatenate(out_table_profit,out_table_profit,"<tr><td align='right'><SPAN style='COLOR: #00EF00'>",
                  DoubleToString(current_profit,2),"</SPAN></td></tr>");
            }
          else
            // if position is opened for sell - this will be the enter to the market
            {
             // if this deal has been already partially processed (in/out)
             if(deal_status[j]==1)
               {
                // create the volume table of entering the market (volume, formed after in/out, is put here)
                StringConcatenate(in_table_volume,in_table_volume,"<tr><td align='right'>",DoubleToString(-lots_list[symb_pointer],2),"</td></tr>");

                // indemnity of volume change, which will be produced (the volume of this deal is already taken into account)
                lots_list[symb_pointer]+=lot_current;
               }
             // if this deal has not been processed yet, create the volume table to enter the market
             else StringConcatenate(in_table_volume,in_table_volume,"<tr><td align='right'>",DoubleToString(lot_current,2),"</td></tr>");

             // creating the time table of entering the market
             StringConcatenate(in_table_time,in_table_time,"<tr><td align='center'>",TimeToString(time_curr,TIME_DATE|TIME_SECONDS),"</td></tr>");

             // creating the price table of entering the market
             StringConcatenate(in_table_price,in_table_price,"<tr><td align='center'>",DoubleToString(HistoryDealGetDouble(ticket,DEAL_PRICE),
             (int)SymbolInfoInteger(symb_list[symb_pointer],SYMBOL_DIGITS)),"</td></tr>");

             // mark deal as processed
             deal_status[j]=127;
            }
          // change of position volume by the current instrument, taking into account the volume of current deal
          lots_list[symb_pointer]-=lot_current;
          // if the volume of opened position by the current instrument became equal to zero - position is closed
          if(NormalizeDouble(lots_list[symb_pointer],2)==0 || deal_status[j]==1) break;
         }
      }
   }
}

Si l'heure, lorsque la position a été ouverte, est dans la période du rapport (au moins partiellement) - l'entrée correspondante est sortie dans le fichier "report.html".

// if the position period is in the the report period - the position is printed to report
if(position_EndTime>=StartTime && position_StartTime<=EndTime) FileWrite(file_handle,
in_table_volume,"</table></td>",
in_table_time,"</table></td>",
in_table_price,"</table></td>",
out_table_volume,"</table></td>",
out_table_time,"</table></td>",
out_table_price,"</table></td>",
out_table_swap,"</table></td>",
out_table_profit,"</table></td></tr>");

Attribuez à la variable balance_prev la valeur du solde. Quittez la boucle avec la variable i.

   }
 // changing balance
 balance_prev=balance;
}

Écrivez la fin du fichier HTML (liens vers les images, la fin de l'alignement du centre, la fin de la partie principale, la fin du document HTML). Clôturez le fichier "report.html".

// create the end of html-file
   FileWrite(file_handle,
         "</table><br><br>"+
            "<h2>Balance Chart</h2><img src='picture1.gif'><br><br><br>"+
            "<h2>Price Chart</h2><img src='picture2.gif'>"+
         "</center>"+
         "</body>"+
   "</html>");
// close file
   FileClose(file_handle);

Attente de la mise à jour du graphique ne dépassant pas le temps indiqué dans la constante de délai d'attente.

// get current time
time_curr=TimeCurrent();
// waiting for chart update
while(SeriesInfoInteger(Symbol(),Picture1_period,SERIES_BARS_COUNT)==0 && TimeCurrent()-time_curr<timeout) Sleep(1000);

Réglage du maximum et du minimum fixes du graphique.

// setting maximal and minimal values for the balance chart (10% indent from upper and lower boundaries)
ChartSetDouble(hChart,CHART_FIXED_MAX,max_val+(max_val-min_val)/10);
ChartSetDouble(hChart,CHART_FIXED_MIN,min_val-(max_val-min_val)/10);

Définition des propriétés du tableau de solde.

// setting properties of the balance chart
ChartSetInteger(hChart,CHART_MODE,CHART_LINE);                // chart as line
ChartSetInteger(hChart,CHART_FOREGROUND,false);               // chart on foreground
ChartSetInteger(hChart,CHART_SHOW_BID_LINE,false);            // hide BID line
ChartSetInteger(hChart,CHART_COLOR_VOLUME,White);             // volumes and orders levels are white
ChartSetInteger(hChart,CHART_COLOR_STOP_LEVEL,White);         // SL and TP levels are white
ChartSetInteger(hChart,CHART_SHOW_GRID,true);                 // show grid
ChartSetInteger(hChart,CHART_COLOR_GRID,LightGray);           // grid is light-gray
ChartSetInteger(hChart,CHART_SHOW_PERIOD_SEP,false);          // hide period separators
ChartSetInteger(hChart,CHART_SHOW_VOLUMES,CHART_VOLUME_HIDE); // hide volumes
ChartSetInteger(hChart,CHART_COLOR_CHART_LINE,White);         // chart is white
ChartSetInteger(hChart,CHART_SCALE,0);                        // minimal scale
ChartSetInteger(hChart,CHART_SCALEFIX,true);                  // fixed scale on vertical axis
ChartSetInteger(hChart,CHART_SHIFT,false);                    // no chart shift
ChartSetInteger(hChart,CHART_AUTOSCROLL,true);                // autoscroll enabled
ChartSetString(hChart,CHART_COMMENT,"BALANCE");               // comment on chart

Redessiner le tableau de solde

// redraw the balance chart
ChartRedraw(hChart);
Sleep(8000);

Capture d'écran de la carte (enregistrez l'image "picture1.gif"). La largeur du graphique s'ajuste à la largeur de la période du rapport (mais à cause des jours fériés, des inexactitudes se produisent souvent et le graphique devient plus large que la courbe de variation du solde), la hauteur est calculée comme la moitié de la largeur.

// screen shooting the balance chart
ChartScreenShot(hChart,"picture1.gif",(int)(EndTime-StartTime)/PeriodSeconds(Picture1_period),
(int)(EndTime-StartTime)/PeriodSeconds(Picture1_period)/2,ALIGN_RIGHT);

Supprimez tous les objets du graphique et clôturez-le.

// delete all objects from the balance chart
ObjectsDeleteAll(hChart);
// close chart
ChartClose(hChart);

Si l'envoi de fichiers via FTP est autorisé, envoyez trois fichiers : "report.html", picture1.gif "et" picture2.gif ".

// if report publication is enabled - send via FTP
// HTML-file and two images - price chart and balance chart
if(TerminalInfoInteger(TERMINAL_FTP_ENABLED))
   {
    SendFTP("report.html");
    SendFTP("picture1.gif");
    SendFTP("picture2.gif");
   }
}

Pour l'instant, la description du programme est achevée Pour envoyer des fichiers via FTP, vous devez ajuster les paramètres de MetaTrader 5 - allez dans le menu Outils, puis Options et ouvrez l'onglet Éditeur (Figure 4).

 FTP.Figure 4. Options de publication de rapport via FTP.

Figure 4. Options de publication de rapport via FTP.

Dans la boîte de dialogue Options, vous devez cocher l'option "Activer", indiquer le numéro de compte, l'adresse FTP, le chemin, l’identifiant et le mot de passe pour l'accès. La périodicité d'actualisation n'a pas d'importance.

Vous pouvez maintenant exécuter le script. Après avoir exécuté le tableau de solde ce dernier apparaît à l'écran pendant quelques secondes puis disparaît. Dans le Journal, vous pouvez trouver une éventuelle erreur et voir si les fichiers ont été envoyés via FTP. Si tout fonctionne correctement, trois nouveaux fichiers apparaîtront sur le serveur, dans le dossier indiqué. Si vous y placez deux fichiers avec des images de flèches et si le serveur WWW est configuré et opérationnel, vous pouvez ouvrir un rapport via un navigateur Web.

2. Envoi de notifications sous forme de SMS vers un téléphone mobile

Il y a des moments où vous êtes loin de votre ordinateur et d'autres appareils électroniques, et vous n'avez qu'un téléphone portable à portée de main. Mais vous souhaitez contrôler le trade sur votre compte ou surveiller les cotations d'instruments financiers. Dans ce cas, vous pouvez définir l'envoi de notifications par SMS vers le téléphone mobile. De nombreux opérateurs mobiles (et tiers) fournissent un service EMAIL-SMS, qui vous permet de recevoir des messages sous forme de lettres, envoyées à une adresse e-mail spécifique.

Pour cela, vous devez disposer d'une boîte e-mail (vous devez notamment connaître votre serveur SMTP). Ajustez vos paramètres MetaTrader 5 - allez dans le menu Outils, puis Options et ouvrez l'onglet E-mail (Figure 5).

Figure 5. Configuration de l'envoi de notifications par e-mail

Figure 5. Configuration l'envoi de notifications par email

Cochez l'option "Activer", indiquez l'adresse du serveur SMTP, l’identifiant et le mot de passe, l'adresse de l'expéditeur (votre e-mail) et l'adresse du destinataire - l'adresse e-mail utilisée pour envoyer des messages sous forme de SMS (vérifiez auprès de votre opérateur mobile). Si tout est bon, lorsque vous cliquez sur le bouton "Test", un message de vérification sera envoyé (voir les informations supplémentaires dans le Journal).

Le moyen le plus simple de recevoir les notifications lorsque le prix atteint un certain niveau est de créer une alerte. Pour se faire, ouvrez l'onglet "Boîte à outils" approprié, faites un clic droit et sélectionnez "Créer" (Figure 6).

Figure 6. Création d'une alerte.

Figure 6. Création d'alerte.

Dans cette fenêtre, cochez l'option "Activer", sélectionnez l'action "Courrier", sélectionnez l'instrument financier, la condition, entrez la valeur de la condition et écrivez le texte du message. Dans les « itérations maximales », entrez 1 si vous ne souhaitez pas que le message revienne à plusieurs reprises. Lorsque tous les champs sont remplis, cliquez sur OK.

Si nous envoyons un message depuis un programme MQL5, nous aurons plus de possibilités. Nous utiliserons la fonction SendMail(). Il dispose de deux paramètres. Premièrement - le titre, deuxièmement - le corps du message.

Vous pouvez appeler la fonction SendMail() après la demande d'échange (fonction OrderSend()) ou dans le gestionnaire d'événements Trade. Nous aurons donc des notifications d'événements de trade - entrée sur le marché, passation de commandes, clôture de positions. Ou vous pouvez placer SendMail() dans la fonction OnTimer() - nous recevrons des notifications périodiques sur les cotations en cours. Vous pouvez organiser l'envoi de notifications lorsque certains signaux de trade apparaissent - lorsque les lignes indicatrices se croisent, lorsque le prix atteint certaines lignes et niveaux, etc.

Examinons ces quelques exemples.

Si en Expert Advisor ou en Script vous remplacez

OrderSend(request,result};

 avec ce qui suit

string msg_subj,msg_text;
if(OrderSend(request,result))
  {
   switch(request.action)
     {
      case TRADE_ACTION_DEAL:
         switch(request.type)
           {
            case ORDER_TYPE_BUY:
               StringConcatenate(msg_text,"Buy ",result.volume," ",request.symbol," at price ",result.price,", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_SELL:
               StringConcatenate(msg_text,"Sell ",result.volume," ",request.symbol," at price ",result.price,", SL=",request.sl,", TP=",request.tp);
               break;
           }
         break;
      case TRADE_ACTION_PENDING:
         switch(request.type)
           {
            case ORDER_TYPE_BUY_LIMIT:
               StringConcatenate(msg_text,"Set BuyLimit ",result.volume," ",request.symbol," at price ",request.price,", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_SELL_LIMIT:
               StringConcatenate(msg_text,"Set SellLimit ",result.volume," ",request.symbol," at price ",request.price,", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_BUY_STOP:
               StringConcatenate(msg_text,"Set BuyStop ",result.volume," ",request.symbol," at price ",request.price,", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_SELL_STOP:
               StringConcatenate(msg_text,"Set SellStop ",result.volume," ",request.symbol," at price ",request.price,", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_BUY_STOP_LIMIT:
               StringConcatenate(msg_text,"Set BuyStopLimit ",result.volume," ",request.symbol," at price ",request.price,", stoplimit=",request.stoplimit,
               ", SL=",request.sl,", TP=",request.tp);
               break;
            case ORDER_TYPE_SELL_STOP_LIMIT:
               StringConcatenate(msg_text,"Set SellStop ",result.volume," ",request.symbol," at price ",request.price,", stoplimit=",request.stoplimit,
               ", SL=",request.sl,", TP=",request.tp);
               break;
           }
         break;
       case TRADE_ACTION_SLTP:
          StringConcatenate(msg_text,"Modify SL&TP. SL=",request.sl,", TP=",request.tp);
          break;
       case TRADE_ACTION_MODIFY:
          StringConcatenate(msg_text,"Modify Order",result.price,", SL=",request.sl,", TP=",request.tp);
          break;
       case TRADE_ACTION_REMOVE:
          msg_text="Delete Order";
          break;
     }
  }
  else msg_text="Error!";
StringConcatenate(msg_subj,AccountInfoInteger(ACCOUNT_LOGIN),"-",AccountInfoString(ACCOUNT_COMPANY));
SendMail(msg_subj,msg_text);

puis après la demande du trade, la fonction OrderSend() enverra un message à l'aide de la fonction SendMail(). Il comprendra des informations sur le numéro de compte de trade, le nom d'un courtier et les actions effectuées (achat, vente, commande en attente, modification ou suppression d'ordre), comme les suivantes :

59181-MetaQuotes Software Corp. Buy 0.1 EURUSD at price 1.23809, SL=1.2345, TP=1.2415

Et si dans n'importe quel Expert Advisor ou Indicateur à l'intérieur du corps de OnInit(), vous démarrez la minuterie en utilisant la fonction EventSetTimer() (elle n'a qu'un seul paramètre - la période de minuterie en secondes):

void OnInit()
  {
   EventSetTimer(3600);
  }

 dans le OnDeinit(), n'oubliez pas de le désactiver à l'aide de EventKillTimer() :

void OnDeinit(const int reason)
  {
   EventKillTimer();
  }

et dans OnTimer() pour envoyer des messages à l'aide de SendMail() :

void OnTimer()
  {
   SendMail(Symbol(),DoubleToString(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits));
  }

alors vous recevrez des messages sur le prix de l'instrument financier actuel avec une période indiquée.

Conclusion

Cet article décrit comment utiliser le programme MQL5 pour créer des fichiers HTML et image et comment les télécharger sur un serveur WWW via FTP. il décrit également comment configurer l'envoi de notifications sur votre téléphone mobile sous forme de SMS.  

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

Fichiers joints |
report.zip (33.08 KB)
sendreport_en.mq5 (32.06 KB)
Création de Panneaux de Contrôle Actifs dans MQL5 pour le Trading Création de Panneaux de Contrôle Actifs dans MQL5 pour le Trading
L'article traite du problème d’élaboration de panneaux de contrôle actifs en MQL5. Les éléments d'interface sont gérés par le mécanisme de gestion des événements. En outre, l'option d'une configuration flexible des propriétés des éléments de contrôle est disponible. Le panneau de contrôle actif permet de travailler avec des positions, ainsi que de définir, modifier et supprimer des commandes de marché et en cours.
Un Exemple de Stratégie de Trading Axée sur les Différences de Fuseau Horaire sur Différents Continents Un Exemple de Stratégie de Trading Axée sur les Différences de Fuseau Horaire sur Différents Continents
En surfant sur Internet, il est facile de trouver de nombreuses stratégies, qui vous donneront un certain nombre de recommandations diverses. Adoptons une approche d'initié et examinons le processus de création d'une stratégie, axée sur les différences de fuseaux horaires sur les différents continents.
Connexion de l'Expert Advisor avec ICQ en MQL5 Connexion de l'Expert Advisor avec ICQ en MQL5
Cet article décrit la méthode d'échange d'informations entre l'Expert Advisor et les utilisateurs d' ICQ, plusieurs exemples sont présentés. La documentation fournie sera intéressante pour ceux qui souhaitent recevoir des informations de trading à distance depuis un terminal client, via un client ICQ dans leur téléphone mobile ou PDA.
Algorithmes Génétiques - C'est Facile ! Algorithmes Génétiques - C'est Facile !
Dans cet article, l'auteur parle de calculs évolutifs à l'aide d'un algorithme génétique personnellement élaboré . Il démontre le fonctionnement de l'algorithme, à l'aide d'exemples, et fournit des recommandations pratiques pour son utilisation.