English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Libro de Recetas MQL5: Escribir el Historial de Transacciones y Crear Gráficos de Saldo para cada Símbolo en Excel

Libro de Recetas MQL5: Escribir el Historial de Transacciones y Crear Gráficos de Saldo para cada Símbolo en Excel

MetaTrader 5Ejemplos | 28 mayo 2014, 11:33
2 170 0
Anatoli Kazharski
Anatoli Kazharski

Introducción

Al explicar mis ideas en varios foros, a menudo utilizo ejemplos de mis resultados de simulación en forma de capturas de pantalla de gráficos de Microsoft Excel. Muchas veces me ha llegado la pregunta de cómo se pueden crear estos gráficos. Excel ofrece muchas prestaciones para crear gráficos y hay muchos libros sobre este tema. Para encontrar la información necesaria en un libro, es posible que tenga que leérselo entero. Ahora por fin tengo algo de tiempo para explicarlo todo en este artículo.

En los dos artículos anteriores MQL5 Cookbook: Multi-Currency Expert Advisor - Simple, Neat and Quick Approach (“Libro de Recetas MQL5: Asesor Experto Multidivisa – Enfoque Sencillo, Claro y Rápido”) y MQL5 Cookbook: Developing a Multi-Currency Expert Advisor with Unlimited Number of Parameters (“Libro de Recetas MQL5: Desarrollar un Asesor Experto Multidivisa con un Número de Parámetros Ilimitado”) tratamos el desarrollo de Asesores Expertos multidivisa en MQL5. Sabemos que los resultados de simulación en MetaTrader 5 se muestran como una curva general de Saldo/Beneficio, es decir, si necesita ver los resultados para cada símbolo por separado, debe ir una y otra vez a los parámetros externos del Asesor Experto para desactivar todos los símbolos excepto aquellos cuyos resultados necesitamos, y después ejecutar la simulación de nuevo. Esto resulta muy conveniente.

Hoy les presento un método sencillo para obtener gráficos de saldo para todos los símbolos junto con el resultado acumulativo de un Asesor Experto multidivisa en un solo diagrama de Excel simplemente con un par de clicks. Para reconstruir el ejemplo, tomaremos el Asesor Experto multidivisa del previous article. Lo reforzaremos con una función que escribirá el historial de transacciones y curvas de beneficio para todos los símbolos a un archivo .csv tras completarse la simulación. Además, añadiremos otra columna al informe para mostrar las reducciones de todos los máximos locales.

Creemos un libro Excel configurado para ser capaz de conectar el archivo de datos. El libro se puede abrir en cualquier momento, de modo que no deberá cerrarse antes de ejecutarse otra simulación. Después de que se complete la simulación, solo necesitará actualizar los datos pulsando una determinada tecla para poder ver los cambios en el informe y en el gráfico.


Desarrollo de Asesor Experto

No habrá ningún cambio significativo en nuestro Asesor Experto, simplemente añadiremos unas cuantas funciones. Empecemos añadiendo la estructura y el array para los saldos de símbolo al archivo principal.

//--- Arrays for balances
struct Balance
  {
   double            balance[];
  };
//--- Array of balances for all symbols
Balance symbol_balance[];

A continuación, crearemos el archivo include separado Report.mqh para funciones que generan informes de simulación y lo incluiremos en el archivo principal del Asesor Experto (vea la línea destacada en el código de abajo):

//--- Include custom libraries
#include "Include/Auxiliary.mqh"
#include "Include/Enums.mqh"
#include "Include/Errors.mqh"
#include "Include/FileFunctions.mqh"
#include "Include/InitializeArrays.mqh"
#include "Include/Report.mqh"
#include "Include/ToString.mqh"
#include "Include/TradeFunctions.mqh"
#include "Include/TradeSignals.mqh"

Creemos primero una estructura de propiedad de transacciones como la que ya tenemos en el proyecto para propiedades de posición y símbolo. Para ello, añadiremos la enumeración de identificadores de propiedad al archivo Enums.mqh:

//+------------------------------------------------------------------+
//| Enumeration of deal properties                                   |
//+------------------------------------------------------------------+
enum ENUM_DEAL_PROPERTIES
  {
   D_SYMBOL     = 0, // Deal symbol
   D_COMMENT    = 1, // Deal comment
   D_TYPE       = 2, // Deal type
   D_ENTRY      = 3, // Deal entry - entry in, entry out, reverse
   D_PRICE      = 4, // Deal price
   D_PROFIT     = 5, // Deal result (profit/loss)
   D_VOLUME     = 6, // Deal volume
   D_SWAP       = 7, // Cumulative swap on close
   D_COMMISSION = 8, // Deal commission
   D_TIME       = 9, // Deal time
   D_ALL        = 10 // All of the above mentioned deal properties
  };

Después crearemos la estructura de propiedad de transacción y la función GetHistoryDealProperties() en el archivo Report.mqh, que devuelve una propiedad de transacción. La función afecta a dos parámetros: ticket de transacción e identificador de propiedad.

Abajo puede ver el código de la estructura y la función GetHistoryDealProperties():

//--- Deal properties in the history
struct HistoryDealProperties
  {
   string            symbol;     // Symbol
   string            comment;    // Comment
   ENUM_DEAL_TYPE    type;       // Deal type
   ENUM_DEAL_ENTRY   entry;      // Direction
   double            price;      // Price
   double            profit;     // Profit/Loss
   double            volume;     // Volume
   double            swap;       // Swap
   double            commission; // Commission
   datetime          time;       // Time
  };
//--- Variable of deal properties
HistoryDealProperties  deal;
//+------------------------------------------------------------------+
//| Gets deal properties by ticket                                   |
//+------------------------------------------------------------------+
void GetHistoryDealProperties(ulong ticket_number,ENUM_DEAL_PROPERTIES history_deal_property)
  {
   switch(history_deal_property)
     {
      case D_SYMBOL     : deal.symbol=HistoryDealGetString(ticket_number,DEAL_SYMBOL);                 break;
      case D_COMMENT    : deal.comment=HistoryDealGetString(ticket_number,DEAL_COMMENT);               break;
      case D_TYPE       : deal.type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket_number,DEAL_TYPE);    break;
      case D_ENTRY      : deal.entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_number,DEAL_ENTRY); break;
      case D_PRICE      : deal.price=HistoryDealGetDouble(ticket_number,DEAL_PRICE);                   break;
      case D_PROFIT     : deal.profit=HistoryDealGetDouble(ticket_number,DEAL_PROFIT);                 break;
      case D_VOLUME     : deal.volume=HistoryDealGetDouble(ticket_number,DEAL_VOLUME);                 break;
      case D_SWAP       : deal.swap=HistoryDealGetDouble(ticket_number,DEAL_SWAP);                     break;
      case D_COMMISSION : deal.commission=HistoryDealGetDouble(ticket_number,DEAL_COMMISSION);         break;
      case D_TIME       : deal.time=(datetime)HistoryDealGetInteger(ticket_number,DEAL_TIME);          break;
      case D_ALL        :
         deal.symbol=HistoryDealGetString(ticket_number,DEAL_SYMBOL);
         deal.comment=HistoryDealGetString(ticket_number,DEAL_COMMENT);
         deal.type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket_number,DEAL_TYPE);
         deal.entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_number,DEAL_ENTRY);
         deal.price=HistoryDealGetDouble(ticket_number,DEAL_PRICE);
         deal.profit=HistoryDealGetDouble(ticket_number,DEAL_PROFIT);
         deal.volume=HistoryDealGetDouble(ticket_number,DEAL_VOLUME);
         deal.swap=HistoryDealGetDouble(ticket_number,DEAL_SWAP);
         deal.commission=HistoryDealGetDouble(ticket_number,DEAL_COMMISSION);
         deal.time=(datetime)HistoryDealGetInteger(ticket_number,DEAL_TIME);                           break;
         //---
      default: Print("The passed deal property is not listed in the enumeration!");                          return;
     }
  }

También necesitaremos varias funciones que convertirán algunas propiedades de transacción a valores de cadena de caracteres. Estas simples funciones devuelven un guión ("-") si el valor pasado está vacío o es igual a cero. Escribámoslas en el archivo ToString.mqh:

//+------------------------------------------------------------------+
//| Returns the symbol name, otherwise - dash                        |
//+------------------------------------------------------------------+
string DealSymbolToString(string deal_symbol)
  {
   return(deal_symbol=="" ? "-" : deal_symbol);
  }
//+------------------------------------------------------------------+
//| Converts deal type to string                                     |
//+------------------------------------------------------------------+
string DealTypeToString(ENUM_DEAL_TYPE deal_type)
  {
   string str="";
//---
   switch(deal_type)
     {
      case DEAL_TYPE_BUY                      : str="buy";                      break;
      case DEAL_TYPE_SELL                     : str="sell";                     break;
      case DEAL_TYPE_BALANCE                  : str="balance";                  break;
      case DEAL_TYPE_CREDIT                   : str="credit";                   break;
      case DEAL_TYPE_CHARGE                   : str="charge";                   break;
      case DEAL_TYPE_CORRECTION               : str="correction";               break;
      case DEAL_TYPE_BONUS                    : str="bonus";                    break;
      case DEAL_TYPE_COMMISSION               : str="commission";               break;
      case DEAL_TYPE_COMMISSION_DAILY         : str="commission daily";         break;
      case DEAL_TYPE_COMMISSION_MONTHLY       : str="commission monthly";       break;
      case DEAL_TYPE_COMMISSION_AGENT_DAILY   : str="commission agent daily";   break;
      case DEAL_TYPE_COMMISSION_AGENT_MONTHLY : str="commission agent monthly"; break;
      case DEAL_TYPE_INTEREST                 : str="interest";                 break;
      case DEAL_TYPE_BUY_CANCELED             : str="buy canceled";             break;
      case DEAL_TYPE_SELL_CANCELED            : str="sell canceled";            break;
      //--- Unknown deal type
      default : str="unknown";
     }
//---
   return(str);
  }
//+------------------------------------------------------------------+
//| Converts direction of deal to string                             |
//+------------------------------------------------------------------+
string DealEntryToString(ENUM_DEAL_ENTRY deal_entry)
  {
   string str="";
//---
   switch(deal_entry)
     {
      case DEAL_ENTRY_IN    : str="in";            break;
      case DEAL_ENTRY_OUT   : str="out";           break;
      case DEAL_ENTRY_INOUT : str="in/out";        break;
      case DEAL_ENTRY_STATE : str="status record"; break;
      //--- Unknown direction type
      default : str="unknown";
     }
//---
   return(str);
  }
//+------------------------------------------------------------------+
//| Converts volume to string                                        |
//+------------------------------------------------------------------+
string DealVolumeToString(double deal_volume)
  {
   return(deal_volume<=0 ? "-" : DoubleToString(deal_volume,2));
  }
//+------------------------------------------------------------------+
//| Converts price to string                                         |
//+------------------------------------------------------------------+
string DealPriceToString(double deal_price,int digits)
  {
   return(deal_price<=0 ? "-" : DoubleToString(deal_price,digits));
  }
//+------------------------------------------------------------------+
//| Converts deal result to string                                   |
//+------------------------------------------------------------------+
string DealProfitToString(string deal_symbol,double deal_profit)
  {
   return((deal_profit==0 || deal_symbol=="") ? "-" : DoubleToString(deal_profit,2));
  }
//+------------------------------------------------------------------+
//| Converts swap to string                                          |
//+------------------------------------------------------------------+
string DealSwapToString(double deal_swap)
  {
   return(deal_swap<=0 ? "-" : DoubleToString(deal_swap,2));
  }

Ahora está todo listo para escribir la función CreateSymbolBalanceReport(), que prepara los datos para el informe y los escribe en el archivo LastTest.csv. Es bastante sencillo: primero escribimos el encabezamiento (note cómo la cadena de caracteres se ajusta si la simulación se lleva a cabo para más de un símbolo), y después se concatenan las propiedades de transacción requeridas para el informe consecutivamente en cadenas de caracteres, que después se escriben en el artículo.

Abajo puede encontrar el código de la función CreateSymbolBalanceReport():

//+------------------------------------------------------------------+
//| Creates the test report on deals in .csv format                  |
//+------------------------------------------------------------------+
void CreateSymbolBalanceReport()
  {
   int    file_handle =INVALID_HANDLE; // File handle
   string path        ="";             // File path

//--- If an error occurred when creating/getting the folder, exit
   if((path=CreateInputParametersFolder())=="")
      return;
//--- Create file to write data in the common folder of the terminal
   file_handle=FileOpen(path+"\\LastTest.csv",FILE_CSV|FILE_WRITE|FILE_ANSI|FILE_COMMON);
//--- If the handle is valid (file created/opened)
   if(file_handle>0)
     {
      int    digits          =0;   // Number of decimal places in the price
      int    deals_total     =0;   // Number of deals in the specified history
      ulong  ticket          =0;   // Deal ticket
      double drawdown_max    =0.0; // Maximum drawdown
      double balance         =0.0; // Balance
      //---
      string delimeter       =","; // Delimiter
      string string_to_write ="";  // To generate the string for writing

      //--- Generate the header string
      string headers="TIME,SYMBOL,DEAL TYPE,ENTRY TYPE,VOLUME,PRICE,SWAP($),PROFIT($),DRAWDOWN(%),BALANCE";
      //--- If more than one symbol is involved, modify the header string
      if(SYMBOLS_COUNT>1)
        {
         for(int s=0; s<SYMBOLS_COUNT; s++)
            StringAdd(headers,","+InputSymbols[s]);
        }
      //--- Write the report headers
      FileWrite(file_handle,headers);
      //--- Get the complete history
      HistorySelect(0,TimeCurrent());
      //--- Get the number of deals
      deals_total=HistoryDealsTotal();
      //--- Resize the array of balances according to the number of symbols
      ArrayResize(symbol_balance,SYMBOLS_COUNT);
      //--- Resize the array of deals for each symbol
      for(int s=0; s<SYMBOLS_COUNT; s++)
         ArrayResize(symbol_balance[s].balance,deals_total);
      //--- Iterate in a loop and write the data
      for(int i=0; i<deals_total; i++)
        {
         //--- Get the deal ticket
         ticket=HistoryDealGetTicket(i);
         //--- Get all the deal properties
         GetHistoryDealProperties(ticket,D_ALL);
         //--- Get the number of digits in the price
         digits=(int)SymbolInfoInteger(deal.symbol,SYMBOL_DIGITS);
         //--- Calculate the overall balance
         balance+=deal.profit+deal.swap+deal.commission;
         //--- Generate a string for writing via concatenation
         StringConcatenate(string_to_write,
                           deal.time,delimeter,
                           DealSymbolToString(deal.symbol),delimeter,
                           DealTypeToString(deal.type),delimeter,
                           DealEntryToString(deal.entry),delimeter,
                           DealVolumeToString(deal.volume),delimeter,
                           DealPriceToString(deal.price,digits),delimeter,
                           DealSwapToString(deal.swap),delimeter,
                           DealProfitToString(deal.symbol,deal.profit),delimeter,
                           MaxDrawdownToString(i,balance,max_drawdown),delimeter,
                           DoubleToString(balance,2));

         //--- If more than one symbol is involved, write their balance values
         if(SYMBOLS_COUNT>1)
           {
            //--- Iterate over all symbols
            for(int s=0; s<SYMBOLS_COUNT; s++)
              {
               //--- If the symbols are equal and the deal result is non-zero
               if(deal.symbol==InputSymbols[s] && deal.profit!=0)
                 {
                  //--- Display the deal in the balance for the corresponding symbol
                  //    Take into consideration swap and commission
                  symbol_balance[s].balance[i]=symbol_balance[s].balance[i-1]+
                                               deal.profit+
                                               deal.swap+
                                               deal.commission;
                  //--- Add to the string
                  StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                 }
               //--- Otherwise write the previous value
               else
                 {
                  //--- If the deal type is "Balance" (the first deal)
                  if(deal.type==DEAL_TYPE_BALANCE)
                    {
                     //--- the balance is the same for all symbols
                     symbol_balance[s].balance[i]=balance;
                     StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                    }
                  //--- Otherwise write the previous value to the current index
                  else
                    {
                     symbol_balance[s].balance[i]=symbol_balance[s].balance[i-1];
                     StringAdd(string_to_write,","+DoubleToString(symbol_balance[s].balance[i],2));
                    }
                 }
              }
           }
         //--- Write the generated string
         FileWrite(file_handle,string_to_write);
         //--- Mandatory zeroing out of the variable for the next string
         string_to_write="";
        }
      //--- Close the file
      FileClose(file_handle);
     }
//--- If the file could not be created/opened, print the appropriate message
   else
      Print("Error creating file: "+IntegerToString(GetLastError())+"");
  }

La función MaxDrawdownToString(), destacada en el código de arriba, calcula todas las reducciones de los máximos locales y devuelve una representación del momento del máximo local en forma de cadena de caracteres. En todos los demás casos, la función devuelve una cadena de caracteres que contiene "-" (un guión).

//+------------------------------------------------------------------+
//| Returns the maximum drawdown from the local maximum              |
//+------------------------------------------------------------------+
string MaxDrawdownToString(int deal_number,double balance,double &max_drawdown)
  {
//--- The string to be displayed in the report
   string str="";
//--- To calculate the local maximum and drawdown
   static double max=0.0;
   static double min=0.0;
//--- If this is the first deal
   if(deal_number==0)
     {
      //--- No drawdown yet
      max_drawdown=0.0;
      //--- Set the initial point as the local maximum
      max=balance;
      min=balance;
     }
   else
     {
      //--- If the current balance is greater than in the memory
      if(balance>max)
        {
         //--- calculate the drawdown using the previous values
         max_drawdown=100-((min/max)*100);
         //--- update the local maximum
         max=balance;
         min=balance;
        }
      else
        {
         //--- Return zero value of the drawdown
         max_drawdown=0.0;
         //--- Update the minimum
         min=fmin(min,balance);
        }
     }
//--- Determine the string for the report
   if(max_drawdown==0)
      str="-";
   else
      str=DoubleToString(max_drawdown,2);
//--- Return result
   return(str);
  }

Con esto, todas las funciones de generación de informe están listas. Solo necesitamos ver cómo debemos usarlas. Esto requerirá una llamada a la función OnTester() después de que la simulación se haya completado. Asegúrese de que comprueba la descripción detallada de esta función en el Material de Referencia de MQL5.

Simplemente, escriba unas pocas líneas de código en el cuerpo de la función OnTester() para especificar la condición en la que se debe generar el informe. Abajo puede ver el fragmento de código correspondiente:

//+------------------------------------------------------------------+
//| Handler of the event of testing completion                       |
//+------------------------------------------------------------------+
double OnTester()
  {
//--- Write the report only after testing
   if(IsTester() && !IsOptimization() && !IsVisualMode())
      //--- Generate the report and write it to the file
      CreateSymbolBalanceReport();
//---
   return(0.0);
  }

Ahora, si ejecuta el Asesor Experto en el Probador de Estrategias, al final de la simulación verá una carpeta del Asesor Experto creada en la carpeta común del terminal C:\ProgramData\MetaQuotes\Terminal\Common\Files. Y el archivo del informe LastTest.csv se generará en la carpeta del Asesor Experto. Si abre el archivo con el bloc de notas, verá algo así:

Figura 1. El archivo de informe en formato .csv.

Figura 1. El archivo de informe en formato .csv.

Crear Gráficos en Excel

Podemos abrir el archivo creado en Excel y ver que cada tipo de datos se encuentra en una columna separada. De esta manera, los datos se muestran de una forma mucho más conveniente para su visualización. Técnicamente, ahora estamos listos para crear gráficos y guardar el archivo como un libro Excel en formato *.xlsx. Sin embargo, si después ejecutamos la simulación y abrimos el libro de nuevo, seguiremos viendo los datos antiguos.

Si tratamos de actualizar los datos mientras el archivo LastTest.csv todavía se está usando en Excel, el archivo no se actualizará, puesto que el Asesor Experto no será capaz de abrirlo para su escritura mientras se está usando por otra aplicación.

Figura 2. El archivo del informe en formato .csv en Excel 2010.

Figura 2. El archivo del informe en formato .csv en Excel 2010.

Hay una solución que se puede usar en este caso. Primero, creemos un libro Excel en formato *.xlsx en la carpeta que desee. A continuación, ábralo y vaya a la pestaña Data (“Datos”).

Figura 3. La pestaña Datos en Excel 2010.

Figura 3. La pestaña Datos en Excel 2010.

En la barra de herramientas de esta pestaña, seleccione la opción From Text (“Desde el texto”). Aparecerá el cuadro de diálogo Import Text File (“Importar archivo de texto”), en el que debe seleccionar el archivo "LastTest.csv". Selección el archivo y haga click en el botón Open (“Abrir”). Aparecerá el cuadro de diálogo Text Import Wizard - Step 1 of 3 (“Wizard de importación de texto – Paso 1 de 3”), tal y como se muestra abajo:

Figura 4. El cuadro de diálogo “Wizard de importación de texto – Paso 1 de 3”.

Figura 4. El cuadro de diálogo “Wizard de importación de texto – Paso 1 de 3”.

Ajuste la configuración tal y como se muestra arriba y haga click en Next > (“Siguiente >”). Aquí, en el paso 2 de 3, debe especificar el delimitador usado en el archivo de datos. En este archivo será "," (coma).

Figura 5. El cuadro de diálogo “Wizard de importación de texto – Paso 2 de 3”.

Figura 5. El cuadro de diálogo “Wizard de importación de texto – Paso 2 de 3”.

Haga click en Next > (“Siguiente >”) para avanzar al paso 3 de 3. Aquí, deje la opción General como el formato de datos para todas las columnas. Podrá cambiar el formato más adelante.

Figura 6. El cuadro de diálogo “Wizard de importación de texto – Paso 3 de 3”.

Figura 6. El cuadro de diálogo “Wizard de importación de texto – Paso 3 de 3”.

Tras hacer click en el botón Finish (“Finalizar”), aparecerá la ventana Import Data (“Importar datos”), donde deberá especificar la hoja de cálculo y las celdas para la importación de datos.

Figura 7. Seleccionar la celda para la importación de datos en Excel 2010.

Figura 7. Seleccionar la celda para la importación de datos en Excel 2010.

Generalmente, seleccionaremos la celda superior izquierda A1. Antes de hacer click en OK, haga click en el botón Properties... (“Propiedades…”) para configurar las propiedades de alcance de los datos externos. Verá un cuadro de diálogo como el que se muestra abajo:

Figura 8. Propiedades de alcance de los datos externos al importar datos de archivos de texto en Excel 2010.

Figura 8. Propiedades de alcance de los datos externos al importar datos de archivos de texto en Excel 2010.

Ajuste la configuración exactamente como se muestra arriba y haga click en OK en la ventana actual y en la siguiente.

Como resultado, sus datos aparecerán de la misma manera que si simplemente hubiera cargado el archivo .csv. Pero ahora puede ejecutar simulaciones en MetaTrader 5 repetidamente sin tener que cerrar el libro Excel. Todo lo que debe hacer después de ejecutar la simulación es, simplemente, actualizar los datos usando la combinación de teclas Ctrl+Alt+F5 o el botón Refresh All (“Actualizar todo”) en la barra de herramientas de la pestaña Data (“Datos”).

Si usa las opciones de formato condicional (Conditional Formatting), en la barra de herramientas de la pestaña Home (“Página principal”), podrá configurar las propiedades visuales requeridas para la representación de datos.

Figura 9. Formato condicional en Excel 2010.

Figura 9. Formato condicional de Excel 2010.

Ahora debemos mostrar los datos en gráficos de Excel. Un gráfico mostrará todos los tráficos de saldo, y el otro mostrará todas las reducciones de máximos locales en forma de histograma.

Creemos primero un diagrama para los gráficos de saldo. Seleccione los encabezamientos de todos los saldos y el array de datos entero de arriba a abajo (manteniendo pulsada la tecla Mayus, pulse la tecla Fin y después la tecla de Flecha hacia abajo). Ahora, en la pestaña Insert (“Insertar”), seleccione el tipo de gráfico deseado.

Figura 10. Seleccionar un tipo de gráfico en Excel 2010.

Figura 10. Seleccionar un tipo de gráfico en Excel 2010.

Como resultado, se creará un gráfico que se podrá mover a otra hoja de cálculo por motivos de conveniencia. Para ello, simplemente selecciónelo y pulse la combinación de teclas Ctrl+X (Cortar). A continuación, vaya a la hoja de cálculo recién creada, selecciona la celda A1 y pulse la combinación de teclas Ctrl+V (Pegar).

El gráfico creado con la configuración por defecto tendrá el siguiente aspecto:

Figura 11. Gráfico creado con la configuración por defecto.

Figura 11. Gráfico creado con la configuración por defecto.

Puede personalizar cualquier elemento del gráfico: cambiar su tamaño, color, estilo, etcétera.

En la imagen de arriba, el eje horizontal muestra el número de transacciones. Modifiquémoslo para que, en lugar de ello, muestre fechas. Para ello, haga clic con el botón derecho del ratón en el gráfico y seleccione la opción Select Data (“Seleccionar datos”) del menú de contexto. Aparecerá el cuadro de diálogo Select Data Source (“Seleccionar fuente de datos”). Haga click en el botón Edit (“Editar”), después seleccione el alcance de datos requerido en la columna TIME (“TIEMPO”) y haga click en OK.

Figura 12. El cuadro de diálogo "Seleccionar fuente de datos".

Figura 12. El cuadro de diálogo "Seleccionar fuente de datos".

Intente crear el gráfico de reducciones por su cuenta, y colóquelo debajo del primer gráfico. Ahora sus propiedades visuales deberán ser personalizadas, si es necesario. Personalmente, yo hago lo siguiente:

Figura 13. Gráficos personalizados en Excel 2010.

Figura 13. Gráficos personalizados en Excel 2010.


Conclusión

Con esto, hemos obtenido los gráficos Excel con resultados de simulaciones bastante aceptables. En uno de mis próximos artículos les mostraré cómo crear informes todavía más informativos. Adjunta al artículo puede encontrar la carpeta descargable con los archivos del Asesor Experto para su estudio personal.

Tras descomprimir los archivos de la carpeta, colóquela en el directorio ReportInExcelfolder to the MetaTrader 5\MQL5\Experts. Además, el indicador EventsSpy.mq5 se debe colocar en el directorio MetaTrader 5\MQL5\Indicators.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/651

Archivos adjuntos |
eventsspy__4.mq5 (7.59 KB)
reportinexcel.zip (26.73 KB)
Fundamentos de programación en MQL5 - Listas Fundamentos de programación en MQL5 - Listas
La nueva versión del lenguaje de programación de estrategias comerciales -MQL [MQL5]- dispone de un conjunto de herramientas más eficaz y potente en comparación con la versión anterior [MQL4]. En primer lugar, esta ventaja se refiere a los medios de programación orientada a objetos. Este artículo se ocupa de la posibilidad del uso del tipo de datos personalizado, correspondiente al tipo complejo, como los nodos y las listas. Se pone el ejemplo del uso de las listas durante la programación de las tareas prácticas en MQL5.
Libro de Recetas MQL5: Desarrollar un Asesor Experto Multidivisa con un Número Ilimitado de Parámetros Libro de Recetas MQL5: Desarrollar un Asesor Experto Multidivisa con un Número Ilimitado de Parámetros
En este artículo crearemos un patrón que usa un solo conjunto de parámetros para la optimización del sistema de trading, a la vez que permite un número ilimitado de parámetros. La lista de símbolo se creará en un archivo de texto estándar (*.txt). Los parámetros de entrada para cada símbolo también se almacenarán en archivos. De esta forma podremos evitar la restricción del terminal del número de parámetros centrada de un Asesor Experto.
Cómo ganar dinero cumpliendo con encargos en el servicio "Freelance" Cómo ganar dinero cumpliendo con encargos en el servicio "Freelance"
Freelance MQL5 es un servicio en línea en el que los desarrolladores escriben aplicaciones comerciales para los traders clientes, a cambio de una gratificación económica. Los traders en 2014 lo han comprendido perfectamente: si quieres conseguir un robot comercial ya listo para funcionar, tienes que recurrir a MetaTrader Market, y si necesitas un asesor único, capaz de comerciar según una estrategia establecida, lo mejor es echar un vistazo a "Freelance". Para cada solicitud hay presentes varios desarrolladores experimentados listos para ponerla en marcha. El trader puede elegir el que más le convenga y le asigna la tarea necesaria.
Libro de Recetas MQL5: Asesor Experto Multidivisa: un Enfoque Simple, Claro y Rápido Libro de Recetas MQL5: Asesor Experto Multidivisa: un Enfoque Simple, Claro y Rápido
Este artículo describirá la implementación de un enfoque sencillo y apropiado para un Asesor Experto multidivisa. Esto significa que será posible configurar el Asesor Experto para simular/realizar operaciones de trading bajo condiciones idénticas pero con parámetros diferentes para cada símbolo. Como ejemplo, crearemos un patrón para dos símbolos pero de forma que solo podamos añadir símbolos adicionales, si es necesario, haciendo pequeños cambios en el código.