English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Creazione e Pubblicazione di Report di Trading e Notifiche SMS

Creazione e Pubblicazione di Report di Trading e Notifiche SMS

MetaTrader 5Esempi | 16 dicembre 2021, 10:08
123 0
Denis Zyatkevich
Denis Zyatkevich

Introduzione

Questo articolo descrive come generare un report dei risultati di trading (utilizzando Expert Advisor, Indicator o Script) come file HTML e caricarlo tramite FTP sul server WWW. Prenderemo in considerazione anche l'invio di notifiche di eventi commerciali come SMS al telefono cellulare.

Per essere più a suo agio con il materiale descritto in questo articolo, si consiglia al lettore di avere familiarità con l'HTML (HyperText Markup Language).

Per implementare i report di upload abbiamo bisogno di un server WWW (può essere qualsiasi computer), che possa accettare dati via FTP. Per implementare la possibilità di ricevere notifiche su eventi commerciali come SMS, abbiamo bisogno di un gateway EMAIL-SMS (questo servizio è fornito dalla maggior parte degli operatori mobili e dalle organizzazioni di terze parti).

1. Creazione di un report e invio tramite FTP

Creiamo un programma MQL5, che genera un report di trading e lo invia tramite protocollo FTP. Per prima cosa lo creiamo come uno Script. In futuro potremo utilizzarlo come blocco finito che potrà essere inserito in Expert Advisor e Indicatori. Ad esempio, in Expert Advisers è possibile utilizzare questo blocco come handler dell'evento Trade o Timer, per eseguire questo blocco dopo una richiesta di trade o per impostare alcune azioni per l'evento ChartEvent. In Indicatori puoi includere questo blocco negli handler di eventi Timer o ChartEvent.

L'esempio di report, creato dal programma, è mostrato nelle Figure 1, 2 e 3. Oppure puoi scaricare questo report tramite il link situato alla fine dell'articolo.

 Figura 1. Esempio di Report - Tabella delle Operazioni e delle Posizioni.

Figura 1. Esempio di Report - Tabella delle Operazioni e delle Posizioni.

Figura 2. Esempio di Report - Grafico Saldo.

Figura 2. Esempio di Report - Grafico del Saldo.

  Figura 3. Esempio di Report - Grafico dei Prezzi sullo Strumento Corrente.

Figura 3. Esempio di Report - Grafico dei Prezzi sullo Strumento Corrente.

Nella tabella delle offerte e delle posizioni (Figura 1) tutte le offerte per convenienza sono suddivise in posizioni. Il lato sinistro della tabella mostra il volume, il tempo e il prezzo per entrare nel mercato (di posizioni aperte e aggiunte). La parte destra della tabella mostra gli stessi parametri per uscire dal mercato (chiusura parziale o totale della posizione). In entrata/uscita l'accordo è suddiviso in due parti: la chiusura di una posizione e l'apertura della successiva.

Sotto la tabella delle operazioni e delle posizioni è mostrato il grafico del saldo (asse orizzontale - tempo), e in basso - il grafico dei prezzi sullo strumento corrente.

Il programma crea i file "report.html", "picture1.gif" e "picture2.gif" (file html del report, file immagine del grafico del saldo e del grafico dei prezzi) nella cartella MetaTarder5_istall_dir\MQL5\Files. E la pubblicazione FTP è abilitata nelle impostazioni del terminale: invia questi tre file al server specificato. Inoltre, avremo bisogno di altri due file - immagini con frecce che indicano la direzione della posizione aperta - Buy o Sell ("buy.gif" e "sell.gif"). Puoi prendere queste immagini (link per il download alla fine dell'articolo) o disegnarle tu stesso in qualsiasi editor grafico. Questi due file dovrebbero essere collocati nella stessa cartella del server WWW con il file "report.html".

Come parametri di input il programma accetta l'ora di inizio e di fine del periodo per il quale viene generato il report. Nel nostro esempio, la fine del periodo del report è l'ora corrente e l'utente seleziona la variante del periodo del report: intero periodo, ultimo giorno, ultima settimana, ultimo mese o ultimo anno.

Qualche parola su come viene creato il report. Il server di trading è richiesto per tutta la cronologia delle operazioni disponibili. Le offerte ottenute vengono elaborate una dopo l'altra. L'array deal_status[] memorizza informazioni sull'elaborazione o meno dell'accordo. Gli indici degli elementi di questo array sono i numeri delle offerte, ricevuti dall'elenco delle offerte del server di trading. E i valori degli elementi sono interpretati come segue: 0 - la trattativa non è stata ancora elaborata, 1 - la trattativa è già stata parzialmente elaborata (in/out), 127 - la trattativa è già stata elaborata (altri valori non vengono utilizzati e sono riservati per un utilizzo futuro).

L'array symb_list[] contiene l'elenco dei nomi degli strumenti finanziari, con cui è stata condotta l'operazione, e l'arraylot_list[] - i volumi delle posizioni aperte per ogni strumento al momento dell'elaborazione dell'operazione. Valori positivi di volume corrispondono a posizioni lunghe, negative - a posizioni corte. Se il volume è uguale a zero, significa che questo strumento non ha posizioni aperte. Se durante l'elaborazione delle operazioni viene rilevato uno strumento finanziario, che non è nell'elenco (nell'array symb_list[]), viene aggiunto lì e il numero di strumenti finanziari (la variabile symb_total) viene incrementato di 1.

Ad ogni elaborazione di operazione ogni operazione successiva viene analizzata dallo stesso strumento finanziario, fino alla chiusura della posizione o fino all'entrata/uscita. Vengono analizzate solo le offerte per le quali il valore dell'array deal_status[] è inferiore a 127. Dopo l'elaborazione dell'accordo, l'elemento corrispondente dell'array deal_status[] viene assegnato con il valore 127 e, se l'accordo è la posizione in/out, con il valore 1. Se l'ora in cui la posizione è stata aperta corrisponde al periodo del report (definito dalle variabili StartTime e EndTime), questa posizione viene registrata nel report (tutti gli input e gli output).

Oltre alla tabella delle operazioni, viene aperto un nuovo grafico per lo strumento finanziario corrente. Per questo grafico vengono fornite tutte le proprietà necessarie e utilizzando la funzione ChartScreenShot() viene creato uno screenshot, quindi otteniamo un file immagine con il grafico dei prezzi per lo strumento corrente. Successivamente, su questo grafico viene mascherato il grafico dei prezzi e viene disegnato il grafico delle modifiche del saldo, quindi viene creato un altro screenshot.

Quando vengono creati due file immagine con grafici e file HTML con report, viene verificata la possibilità di inviare file tramite FTP. Se consentito, i file "report.html", "picture1.gif" e "picture2.gif" vengono inviati utilizzando la funzione SendFTP(), in base alle impostazioni specificate in MetaTrader 5.

Avvia MetaQuotes Language Editor e inizia a creare uno script. Definisci le costanti: il timeout dell'aggiornamento del grafico (in secondi), la larghezza e l'altezza del grafico dei prezzi e la larghezza massima del grafico del saldo. Il periodo del grafico, che visualizzerà la curva di variazione del saldo, viene scelto in base alla durata del periodo di report e alla larghezza massima del grafico. La larghezza del grafico viene adattata alle dimensioni necessarie per il grafico del saldo.

L'altezza del grafico viene calcolata automaticamente come metà della larghezza. Inoltre, specificheremo la larghezza dell'asse verticale come costante: è il numero di pixel di cui l'area grafica viene ridotta rispetto alla larghezza dell'immagine a causa dell'asse verticale.

#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)

Specificare che i parametri di input verranno richiesti dall'utente.

// request input parameters
#property script_show_inputs

Creare l'enumerazione dei periodi del report.

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

Chiedi all'utente il periodo del report (per impostazione predefinita è l'intero periodo).

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

Scrivere il corpo della funzione OnStart().

void OnStart()
  {

Determinare l'inizio e la fine del periodo del rapporto.

  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)

Dichiarare le variabili che verranno utilizzate nel programma. Lo scopo delle variabili è descritto nei commenti.

   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

Apri un nuovo grafico e imposta le sue proprietà: questo è il grafico dei prezzi, che verrà visualizzato in fondo al report.

 // 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

Fate uno screenshot del grafico e salvatelo come "picture2.gif".

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

Richiedi la cronologia delle trattative per l'intero periodo di esistenza dell'account.

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

Aprire il file "report.html", in cui scriveremo la pagina HTML con il report (codifica ANSI).

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

Scrivi la parte iniziale del documento HTML:

  • inizio del documento html (<html>)
  • titolo che verrà visualizzato nella parte superiore della finestra del browser (<head><title>Expert Trade Report</title></head>)
  • inizio della parte principale del documento html con colore di sfondo (<body bgcolor='#EFEFEF'>)
  • allineamento al centro (<centro>)
  • titolo della tabella delle operazioni e delle posizioni (<h2>Rapporto sugli scambi</h2>)
  • inizio della tabella delle offerte e delle posizioni con allineamento, larghezza del bordo, colore di sfondo, colore del bordo, spaziatura e riempimento delle celle (<table align='center' border='1' bgcolor='#FFFFFF' bordercolor='#7F7FFF' cellpacing ='0' cellpadding='0'>)
  • intestazione della tabella 
// 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>");

Ottenere il numero di offerte nell'elenco.

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

Impostazione delle dimensioni per gli array symb_list[], lot_list[] e 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);

Inizializzazione di tutti gli elementi dell'array deal_status[] con valore 0 - tutte le offerte non vengono elaborate.

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

Impostazione dei valori iniziali di saldo e variabile, utilizzato per memorizzare il valore precedente del saldo.

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

Impostazione del valore iniziale della variabile, utilizzata per memorizzare il numero di strumenti finanziari nella lista.

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

Crea un ciclo, che elabori in sequenza ogni affare nell'elenco.

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

Seleziona l'offerta corrente e ottieni il suo biglietto.

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

Modifica del saldo in base all'importo del profitto nell'operazione corrente.

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

Ottenere il tempo dell'affare - sarà usato frequentemente ulteriormente.

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

Se è il primo affare nell'elenco, dobbiamo regolare i limiti del periodo del rapporto e selezionare il periodo per il grafico del saldo, a seconda della durata del periodo del rapporto e della larghezza della regione in cui verrà tracciato il grafico. Impostazione dei valori iniziali dei saldi massimo e minimo (queste variabili verranno utilizzate per impostare il massimo e il minimo del grafico).

// 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);
  }

Se questo affare non è il primo, crea l'oggetto "linea", utilizzando il quale viene tracciato il grafico della variazione del saldo. La linea viene tracciata solo se almeno una delle sue estremità è nel periodo del report. Se entrambe le estremità sono nel periodo del report, la linea sarà "spessa". Il colore della linea di equilibrio è verde. Se l'equilibrio è oltre l'intervallo di equilibrio minimo e massimo, questo intervallo viene regolato.

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

Assegna il valore precedente del tempo alla variabile corrispondente.

// changing the previous time value
time_prev=time_curr;

Se l'accordo non è stato ancora elaborato, elaboralo.

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

Se questa transazione è un addebito del saldo ed è nel periodo del report, la stringa corrispondente viene scritta nel report. L'accordo è contrassegnato come elaborato.

// 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;
  }

Se questo affare è Buy o Sell, controlla se questo strumento è nell'elenco (array symb_list[]). In caso contrario, mettilo lì. La variabile symb_pointer punta all'elemento dell'array symb_list[], che contiene il nome dello strumento dell'operazione corrente.

// 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++;
     }

Imposta i valori iniziali delle variabili position_StartTime e position_EndTime, che memorizzano la durata della posizione iniziale e 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;

Le variabili in_table_volume, in_table_time, in_table_price, out_table_volume, out_table_time, out_table_price, out_table_swap e out_table_profit memorizzeranno le tabelle, che saranno all'interno delle celle della tabella più grande: volume, tempo e prezzo di ingresso nel mercato; volume, tempo, prezzo, scambio e profitto dell'uscita dal mercato. La variabile in_table_volume memorizzerà anche il nome dello strumento finanziario e si collegherà a un'immagine, che corrisponde alla direzione della posizione aperta. Assegna a tutte queste variabili i valori iniziali.

// 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'>";

Elabora tutte le operazioni a partire dall'attuale fino alla chiusura della posizione. Elaborarli tutti, se non sono stati elaborati in precedenza.

// 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)
     {

Seleziona l'offerta e ottieni il suo biglietto.

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

Se l'operazione è sullo stesso strumento della posizione aperta, elaborala. Ottieni il tempo dell'affare. Se il tempo di negoziazione va oltre l'intervallo del tempo di posizione, estendi l'intervallo. Ottieni il volume dell'affare.

// 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);

Le offerte di Buy e Sell vengono elaborate separatamente. Inizia con le offerte Buy.

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

Se hai già aperto una posizione Sell, questa operazione Buy uscirà dal mercato. E se il volume dell'operazione sarà maggiore del volume della posizione corta aperta, questo sarà l'in/out. Assegna variabili stringa con i valori richiesti. Assegna l'array deal_status[] con il valore 127, se l'operazione è completamente elaborata, o con il valore 1 se è l'entrata/uscita e questa operazione deve essere analizzata per un'altra posizione.

// 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>");
  }

Se hai già aperto una posizione lunga, il buy in questa operazione sarà l'ingresso nel mercato (il primo o l'aggiunta). Se l'elemento dell'array deal_status[], che corrisponde a questo deal, ha il valore 1, significa che è stato effettuato un ingresso/uscita. Assegna le variabili stringa con i valori richiesti e contrassegna l'affare come elaborato (assegna l'elemento corrispondente dell'array deal_status[] con il valore 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;
   }

Modifica il volume della posizione in base al volume dell'operazione corrente. Se la posizione è chiusa (il volume è uguale a zero), ferma l'elaborazione di questa posizione (esci dal ciclo con la variabile j) e cerca il prossimo affare non elaborato (nel ciclo con la variabile 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;
}

Le operazioni di vendita vengono elaborate in modo simile, quindi usciamo dal ciclo con la variabile 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;
         }
      }
   }
}

Se l'ora in cui la posizione è stata aperta è nel periodo di report (almeno parzialmente), la voce corrispondente viene emessa nel file "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>");

Assegna la variabile balance_prev con il valore del saldo. Uscire dal ciclo con la variabile i.

   }
 // changing balance
 balance_prev=balance;
}

Scrivi la fine del file HTML (link alle immagini, la fine dell'allineamento al centro, la fine della parte principale, la fine del documento HTML). Chiudi il file "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);

In attesa dell'aggiornamento del grafico non oltre il tempo specificato nella costante di timeout.

// 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);

Impostazione del massimo e del minimo fissi del grafico.

// 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);

Impostazione delle proprietà del grafico del saldo.

// 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

Ridisegnare il grafico del saldo.

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

Screenshot del grafico (salva l'immagine "picture1.gif"). La larghezza del grafico si adatta alla larghezza del periodo del report (ma a causa delle festività spesso si verificano imprecisioni e il grafico diventa più ampio della curva di variazione del bilanciamento), l'altezza viene calcolata come metà della larghezza.

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

Elimina tutti gli oggetti dal grafico e chiudilo.

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

Se l'invio di file tramite FTP è consentito, inviare tre file: "report.html", picture1.gif "e" 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");
   }
}

Per ora la descrizione del programma è completa. Per inviare file tramite FTP è necessario regolare le impostazioni di MetaTrader 5 - andare al menu Strumenti, quindi Opzioni e aprire la scheda Publisher (Figura 4).

Figura 4. Opzioni di pubblicazione del report tramite FTP.

Figura 4. Opzioni di pubblicazione del report tramite FTP.

Nella finestra di dialogo Opzioni è necessario selezionare l'opzione "Abilita", specificare il numero di account, l'indirizzo FTP, il percorso, il login e la password per l'accesso. La periodicità di aggiornamento non ha importanza.

Ora puoi eseguire lo script. Dopo l'esecuzione il grafico del saldo appare sullo schermo per alcuni secondi e poi scompare. Nel Journal puoi trovare possibili errori e vedere se i file sono stati inviati tramite FTP. Se tutto funziona correttamente, verranno visualizzati tre nuovi file sul server nella cartella specificata. Se inserisci due file con immagini di frecce e se il server WWW è configurato e funzionante, puoi aprire un report tramite browser web.

2. Invio di notifiche come SMS al cellulare

Ci sono momenti in cui sei lontano dal tuo computer e altri dispositivi elettronici e hai solo un telefono cellulare a portata di mano. Ma vuoi controllare il commercio sul tuo conto o monitorare le quotazioni per lo strumento finanziario. In questo caso è possibile impostare l'invio di notifiche via SMS al cellulare. Molti operatori di telefonia mobile (e terze parti) forniscono il servizio EMAIL-SMS, che consente di ricevere messaggi come lettere, inviati a uno specifico indirizzo di posta elettronica.

Per questo è necessario disporre di una casella di posta elettronica (in particolare, è necessario conoscere il proprio server SMTP). Regola le impostazioni di MetaTrader 5: vai al menu Strumenti, quindi Opzioni e apri la scheda Email (Figura 5).

Figura 5. Impostazione dell'invio di notifiche tramite e-mail

Figura 5. Configurazione dell'invio di notifiche via e-mail

Seleziona l'opzione "Abilita", specifica l'indirizzo del server SMTP, login e password, indirizzo del mittente (la tua e-mail) e indirizzo del destinatario - l'indirizzo e-mail utilizzato per inviare messaggi come SMS (verifica con il tuo operatore di telefonia mobile). Se tutto è corretto, quando si fa clic sul pulsante "Test" verrà inviato un messaggio di verifica (vedere ulteriori informazioni nel Journal).

Il modo più semplice per essere avvisati quando il prezzo raggiunge un certo livello è creare un avviso. Per fare ciò, aprire la scheda "Casella degli strumenti" appropriata, fare clic con il pulsante destro del mouse e selezionare "Crea" (Figura 6).

Figura 6. Creazione dell'avviso.

Figura 6. Creazione avviso.

In questa finestra seleziona l'opzione "Abilita", seleziona l'azione "Posta", seleziona strumento finanziario, condizione, inserisci il valore per la condizione e scrivi il testo del messaggio. In "Massime iterazioni" inserisci 1 se non vuoi che il messaggio arrivi ripetutamente. Quando tutti i campi sono stati compilati, fare clic su OK.

Se inviamo un messaggio da un programma MQL5, avremo più possibilità. Useremo la funzione SendMail(). Ha due parametri. Primo - il titolo, secondo - il corpo del messaggio.

È possibile chiamare la funzione SendMail() dopo la richiesta commerciale (funzione OrderSend()) o nell’handler dell'evento Trade. Quindi avremo notifiche di eventi di trade: ingresso nel mercato, immissione di ordini, chiusura di posizioni. Oppure puoi inserire SendMail() all'interno della funzione OnTimer() - riceveremo notifiche periodiche sulle quotazioni correnti. Puoi organizzare l'invio di notifiche quando vengono visualizzati determinati segnali di trading - quando le linee dell'indicatore si intersecano, quando il prezzo raggiunge alcune righe e livelli, ecc.

Consideriamo alcuni esempi.

Se in Expert Advisor o in Script sostituisci

OrderSend(request,result};

 con il seguente

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);

quindi dopo la richiesta di trading la funzione OrderSend() invierà un messaggio utilizzando la funzione SendMail(). Includerà informazioni sul numero di conto di trading, il nome di un broker e le azioni intraprese (buy, sell, immissione di un ordine in sospeso, modifica o eliminazione dell'ordine), come le seguenti:

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

E se in qualsiasi Expert Advisor o Indicatore all'interno del corpo di OnInit() avvierai il timer usando la funzione EventSetTimer() (ha un solo parametro: il periodo del timer in secondi):

void OnInit()
  {
   EventSetTimer(3600);
  }

 in OnDeinit() non dimenticare di disattivarlo usando EventKillTimer():

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

e in OnTimer() per inviare messaggi utilizzando SendMail():

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

quindi riceverai messaggi sul prezzo dello strumento finanziario corrente con il periodo specificato.

Conclusione

Questo articolo descrive come utilizzare il programma MQL5 per creare file HTML e immagine e come caricarli sul server WWW tramite FTP. descrive anche come configurare l'invio di notifiche al telefono cellulare come SMS.  

Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/61

File allegati |
report.zip (33.08 KB)
sendreport_en.mq5 (32.06 KB)
Creazione di Pannelli di Controllo Attivi in MQL5 per il Trading Creazione di Pannelli di Controllo Attivi in MQL5 per il Trading
L'articolo tratta il problema dello sviluppo dei pannelli di controllo attivi in MQL5. Gli elementi dell'interfaccia sono gestiti dal meccanismo di gestione degli eventi. Inoltre, è disponibile l'opzione di un'impostazione flessibile delle proprietà degli elementi di controllo. Il pannello di controllo attivo consente di lavorare con le posizioni, nonché di impostare, modificare ed eliminare ordini di mercato e in sospeso.
Un Esempio di Strategia di Trading Basata sulle Differenze di Fuso Orario nei Diversi Continenti Un Esempio di Strategia di Trading Basata sulle Differenze di Fuso Orario nei Diversi Continenti
Navigando in Internet, è facile trovare molte strategie che ti daranno vari consigli. Prendiamo l'approccio di un insider e esaminiamo il processo di creazione della strategia, basato sulle differenze nei fusi orari nei diversi continenti.
Collegamento di Expert Advisor con ICQ in MQL5 Collegamento di Expert Advisor con ICQ in MQL5
Questo articolo descrive il metodo di scambio di informazioni tra l'Expert Advisor e gli utenti ICQ, vengono presentati diversi esempi. Il materiale fornito sarà interessante per coloro che desiderano ricevere informazioni di trading in remoto da un terminale del cliente, tramite un client ICQ nel proprio telefono cellulare o PDA.
Algoritmi Genetici - È Facile! Algoritmi Genetici - È Facile!
In questo articolo, l'autore parla di calcoli evolutivi con l'uso di un algoritmo genetico sviluppato personalmente. Dimostra il funzionamento dell'algoritmo, usando esempi e fornisce consigli pratici per il suo utilizzo.