![Integración del terminal de cliente de MetaTrader 4 con MS SQL Server](https://c.mql5.com/i/articles/overlay.png)
Integración del terminal de cliente de MetaTrader 4 con MS SQL Server
Introducción
El uso de integraciones con otros productos ofrece un reto adicional en el trading.
Puede haber muchos usos al respecto, por lo que daré solo algunos de ellos.
Puede recoger ticks y pasarlos a MS SQL SERVER para un análisis adicional. Tener un largo historial de ticks permite recoger cualquier periodo comenzando desde el mínimo espacio de tiempo y llegando hasta los periodos no estándar. Tener cotizaciones de tick reales permite depurar estrategias dependientes de datos de tick conocidas como 'especuladores'.
Puede usar un almacén para un análisis rápido de datos tomados de otras aplicaciones, por ejemplo, de MS Excel y otro software de terceros o de sus propios productos.
Por ejemplo, puede descargar todo el historial del Centro de Historial del terminal a MS SQL. Posteriormente no necesita almacenar el historial en MT4. Esto ayudará a aliviar la memoria del terminal.
Puede calcular redes neuronales usando cotizaciones almacenadas en MS SQL SERVER: por ejemplo, STATISTICA - 7.8 para poder descargar cotizaciones de SQL que puede resolverse en modo de tiempo real pasando las señales de red a MT4.
Puede desarrollar su propio programa en otro lenguaje y para otro símbolo y pasar las señales usando MS SQL SERVER, habiendo dejado solo las funciones de ejecución para el terminal de cliente y liberándolo de cálculos serios.
Los siguientes productos de software se usaron en este proyecto
- MS SQL SERVER 2000 Developer - BASE
- VISUAL C++ 6.0 SP5 - para crear la DLL "YZMSSQLExpertSample.dll"
- MDAC 7
El conjunto mínimo a instalar:
1 MS SQL SERVER 2000 Developer
2 MDAC 7
Depuré el programa usando MDAC 7. No obstante, es posible que todo funcione correctamente en algunas versiones anteriores. Si no va a compilar la DLL, no necesita instalar ni tener instalado Vicual C++ 6.0. Puede usar una DLL preparada. No obstante, he cableado el nombre de usuario en él, el nombre de DSN y las conexiones. Por lo que tendrá que repetir todo lo listado anteriormente en su versión del programa. No describiré aquí cómo instalar MS SQL SERVER o Visual C++ 6.0, esto queda fuera del alcance de este artículo concreto.
Después de instalar los productos de software necesarios, debemos crear una DSN:
dsn=MT4_SQL_BASE;", "yuraz", "qwerty"
Ejemplo de recepción de tick en MS SQL
Todos los experimentos se realizaron con MS SQL SERVER 2000 Developer. En Visual C++ 6.0, se creó YZMSSQLExpertSample.DLL usando el método de acceso a MS SQL a través de ADO. Debe instalarse MDAC 7 o MDAC 8. Solo describiré los ejemplos sobre cómo crear procedimientos y tablas. El conjunto mínimo de lo que tenemos que crear en MS SQL son la base, las tablas y los procedimientos. Vamos a considerar la tabla y los procedimientos de trabajo con cotizaciones de tick. Puede añadir algunas funciones adicionales si quiere.
Es necesario crear una base y las tablas en MS SQL. Yo creé una nueva base llamada MT4TRADE. Luego debemos crear las tablas en ella:
MT4TICK - Tabla de ticks
//----------------------------------------------------------------------------------- // // Structure of MT4TICK Base // // idc - formed automatically, unique number of record // ServerDateTime - Filled out automatically, when adding a record // Server local time - time when the quote was placed in the table // (it doesn't have anything in common with the date and time passed by MT4) // it is the time counted by the server itself - it will be the same as the time // of the machine, on which the server has been launched. //--- // iDateTime - date and time in MT4 format, passed from MT4 // sSymbol - symbol // cAsk - quote Ask // cBid - quote Bid // CREATE TABLE [dbo].[MT4TICK] ( [idc] [bigint] IDENTITY (1, 1) NOT NULL , [ServerDateTime] [datetime] NULL , [iDateTime] [bigint] NULL , [sSymbol] [char] (6) COLLATE SQL_Latin1_General_CP1251_CI_AS NULL , [cAsk] [numeric](18, 4) NULL , [cBid] [numeric](18, 4) NULL ) ON [PRIMARY] GO --- Include automated filling out the ServerDateTime field with the date and time of server MS SQL ALTER TABLE [dbo].[MT4TICK] ADD CONSTRAINT [DF_MT4TICK_ServerDateTime] DEFAULT (getdate()) FOR [ServerDateTime] GO
A continuación se muestra cómo aparece el procedimiento de recepción y tabulación de ticks:
// // @RetCode int out --- used for returning // ,@psSymbol char(6) --- symbol // ,@piDateTime bigint --- date and time of tick arrival // ,@pdAsk float --- Ask // ,@pdBid float --- Bid // // The procedure just returns 0 // if we analyze the code of returning to MQL4, we can see that the quote has reached the procedure and has been tabulated // // CREATE PROCEDURE dbo.YZ_MT4_TICK @RetCode int out ,@psSymbol char(6) ,@piDateTime bigint ,@pdAsk float ,@pdBid float AS insert into MT4TICK ( sSymbol, iDateTime, cAsk, cBid ) values ( @psSymbol , @piDateTime, @pdAsk , @pdBid ) select @RetCode=0 return @RetCode
Podemos ver a partir de la descripción anterior cuáles son los procedimientos que se usan y con qué finalidad.
@RetCode - no tiene ninguna funcionalidad cuando se pasa desde la DLL, sirve solo para recibir el código de finalización.
La configuración de MS SQL SERVER ha terminado. Se adjunta a este artículo un script para crear una configuración estándar.
Vamos a fantasear: Posibles soluciones y ventajas
Podemos crear un almacén de datos y colocar/extraer información de él. De esta forma, podemos liberar al terminal de cliente de MT 4 de la necesidad de guardar el historial de cotizaciones. Ahora el historial de cotizaciones se guarda en MS SQL Server y podemos operar con esta información, extraerla antes y exportarla a otras aplicaciones. Podemos utilizar los datos a analizar en paquetes NEURONALES, la mayoría de los cuales pueden trabajar con almacenes SQL.
En tiempo real, el terminal puede seguir formando señales de los indicadores pasándolas al almacén y fijándolas de esta forma. Una aplicación externa puede extraer la señal y el historial en tiempo real, analizarlos y formar señales realizando la ejecución y el almacenamiento del registro en MS SQL Server y enviarlos al terminal para su ejecución.
De este modo, podemos obtener la integración y distribución funcional entre las aplicaciones involucradas en un complejo de trading automatizado.
Bueno, si ya no es necesario almacenar las cotizaciones históricas podemos hacerlo de la forma siguiente. Establecemos las barras mínimas en Tools>Options>Charts, por ejemplo, para 5000. El terminal comienza a trabajar más rápido ya que no necesita asignar memoria para un historial grande.
Textos fuente
Código DLL:
//+------------------------------------------------------------------+ //| Sample DLL for MQL4 | //| Copyright c 2004-2008, MetaQuotes Software Corp. | //| https://www.metaquotes.net | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ // // YURAZ 2008 YZMSSQLExpertSample // // Example DLL Integrating MT4 with MS SQL 2000 // // ADO MS SQL SERVER // // software used // // VISUAL C++ 6 , SP5 , MDAC 7 , MS SQL2000 + SP4 // //+------------------------------------------------------------------+ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <windows.h> #include <stdlib.h> #include <stdio.h> //---- #define MT4_EXPFUNC __declspec(dllexport) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #pragma pack(push,1) struct RateInfo { unsigned int ctm; double open; double low; double high; double close; double vol; double vol1; double vol2; double vol3; double vol4; double vol5; }; #pragma pack(pop) struct MqlStr { int len; char *string; }; static int CompareMqlStr(const void *left,const void *right); static int SQLexecProcedure( char *nprc ); static int SQLexecProcedureSignal( char *sSymbol, char* sProcedure ); // static int _YZSQLsqlstrinsql( char *Symbol , unsigned int DateTime , double Ask, double Bid, char *NamePrc ); static int _YZSQLprocedure ( char *sSymbol, unsigned int pDateTime, double Ask, double Bid, char *NamePrc ); static int _YZSQLprocedureHISTORYPut(char *Symbol,unsigned int Period, unsigned int DateTime,double Open, double High,double Low, double Close ,double Volume, unsigned int Bar ,char *Procedure); //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) { //---- switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } //---- return(TRUE); } // place ticks in MS SQL // call the procedure as an SQL line passing parameters "exec YZ_MT4_TICK ?,?,?,?" /* MT4_EXPFUNC int __stdcall SQLsqlstringTickPut(char *Symbol,unsigned int DateTime,double Ask,double Bid,char *sSQLstring) { int ccc = _YZSQLsqlstrinsql( Symbol , DateTime , Ask , Bid , sSQLstring ); return(ccc); } */ // call as a procedure passing parameters MT4_EXPFUNC int __stdcall SQLProcedureTickPut(char *Symbol,unsigned int DateTime,double Ask,double Bid,char *Procedure) { int ccc = _YZSQLprocedure( Symbol , DateTime , Ask , Bid ,Procedure ); return(ccc); } // place a specific candlestick in MS SQL history MT4_EXPFUNC int __stdcall SQLProcedureHistoryPut(char *Symbol,unsigned int Period , unsigned int DateTime, double Open,double High,double Low, double Close ,double Volume,unsigned int Bar ,char *Procedure) { int ccc = _YZSQLprocedureHISTORYPut(Symbol,Period,DateTime,Open,High,Low,Close,Volume,Bar,Procedure); return(ccc); } // call procedure sProcedure // // return -1 error // MT4_EXPFUNC int __stdcall SQLProcedureGetInt(char *sProcedure) { int Ret = SQLexecProcedure( sProcedure ); return((int)Ret); } MT4_EXPFUNC int __stdcall SQLProcedureGetSignal (char *sSymbol, char *sProcedure) { int Ret = SQLexecProcedureSignal( sSymbol, sProcedure ); return((int)Ret); } ////////////////////////////////// #include "stdafx.h" #include <stdio.h> #import "C:\Program Files\Common Files\System\ado\msado20.tlb" \ rename("EOF","ADOEOF") rename("BOF","ADOBOF") using namespace ADODB; inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); }; // procedure call method int _YZSQLprocedure( char *sSymbol, unsigned int pDateTime, double Ask, double Bid, char *NamePrc ) { HRESULT hr = S_OK; _CommandPtr pCmd = NULL; _ConnectionPtr pConnection = NULL; _bstr_t strMessage, strAuthorID; ::CoInitialize(NULL); long codRet = -1; try { _ParameterPtr Par1; _ParameterPtr Par2; _ParameterPtr Par3; _ParameterPtr Par4; _ParameterPtr Par5; TESTHR(pConnection.CreateInstance(__uuidof(Connection))); hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified); pConnection->CursorLocation = adUseClient; TESTHR(pCmd.CreateInstance(__uuidof(Command))); pCmd->CommandText = NamePrc; // procedure name pCmd->CommandType = adCmdStoredProc; Par1 = pCmd->CreateParameter( _bstr_t("@P1"), adInteger, adParamOutput,0, codRet ); pCmd->Parameters->Append( Par1 ); Par1 = pCmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(sSymbol) ,sSymbol ); pCmd->Parameters->Append(Par1); Par2 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) , (double)pDateTime ); pCmd->Parameters->Append(Par2); Par3 = pCmd->CreateParameter("@pdAsk", adDouble, adParamInput, 4, Ask ); pCmd->Parameters->Append(Par3); Par4 = pCmd->CreateParameter("@pdBid", adDouble, adParamInput, 4, Bid ); pCmd->Parameters->Append(Par4); pCmd->ActiveConnection = pConnection; int hr = pCmd->Execute( 0, 0, adCmdStoredProc ); if( FAILED(hr) ) { codRet = -1; } else { Par1 = pCmd->Parameters->GetItem(_bstr_t("@P1")); // obtain from the procedure codRet = Par1->GetValue(); } } catch(_com_error ) { // // if necessary, process the execution error // codRet = -1; } if (pConnection) if (pConnection->State == adStateOpen) pConnection->Close(); ::CoUninitialize(); return((int)codRet); } // place in history Symbol , Period . DateTime, Open , High , Low , Close , Value , Bar int _YZSQLprocedureHISTORYPut(char *pSymbol,unsigned int pPeriod, unsigned int pDateTime,double pOpen,double pHigh, double pLow, double pClose ,double pVolume, unsigned int pBar ,char *pProcedure ) { HRESULT hr = S_OK; _CommandPtr pCmd = NULL; _ConnectionPtr pConnection = NULL; _bstr_t strMessage, strAuthorID; ::CoInitialize(NULL); long codRet = -1; try { _ParameterPtr ParReturn; // _ParameterPtr Par1; // SYMBOL _ParameterPtr Par2; // PERIOD _ParameterPtr Par3; // DATETIME _ParameterPtr Par4; // OPEN _ParameterPtr Par5; // HIGH _ParameterPtr Par6; // LOW _ParameterPtr Par7; // CLOSE _ParameterPtr Par8; // VOLUME _ParameterPtr Par9; // BAR TESTHR(pConnection.CreateInstance(__uuidof(Connection))); hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified); pConnection->CursorLocation = adUseClient; TESTHR(pCmd.CreateInstance(__uuidof(Command))); pCmd->CommandText = pProcedure; // procedure name pCmd->CommandType = adCmdStoredProc; ParReturn = pCmd->CreateParameter( _bstr_t("@P1"), adInteger, adParamOutput,0, codRet ); pCmd->Parameters->Append( ParReturn ); Par1 = pCmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(pSymbol) ,pSymbol ); pCmd->Parameters->Append(Par1); Par2 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) , (double)pPeriod ); pCmd->Parameters->Append(Par2); Par3 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) , (double)pDateTime ); pCmd->Parameters->Append(Par3); Par4 = pCmd->CreateParameter("@pdOpen", adDouble, adParamInput, 4, pOpen ); pCmd->Parameters->Append(Par4); Par5 = pCmd->CreateParameter("@pdHigh", adDouble, adParamInput, 4, pHigh ); pCmd->Parameters->Append(Par5); Par6 = pCmd->CreateParameter("@pdLow", adDouble, adParamInput, 4, pLow ); pCmd->Parameters->Append(Par6); Par7 = pCmd->CreateParameter("@pdClose", adDouble, adParamInput, 4, pClose ); pCmd->Parameters->Append(Par7); Par8 = pCmd->CreateParameter("@pdVolume", adDouble, adParamInput, 4, pVolume ); pCmd->Parameters->Append(Par8); Par9 = pCmd->CreateParameter("@piBar", adDouble , adParamInput, sizeof(double) , (double)pBar ); pCmd->Parameters->Append(Par9); pCmd->ActiveConnection = pConnection; int hr = pCmd->Execute( 0, 0, adCmdStoredProc ); if( FAILED(hr) ) { codRet = -1; } else { ParReturn = pCmd->Parameters->GetItem(_bstr_t("@P1")); // obtain from the procedure codRet = ParReturn->GetValue(); } } catch(_com_error ) { // // if necessary, process the execution error // codRet = -1; } if (pConnection) if (pConnection->State == adStateOpen) pConnection->Close(); ::CoUninitialize(); return((int)codRet); } // // return the value returned by the procedure // int SQLexecProcedure( char *nprc ) { HRESULT hr = S_OK; _CommandPtr pcmd = NULL; _ConnectionPtr pConnection = NULL; _bstr_t strMessage, strAuthorID; ::CoInitialize(NULL); long codRet = -1; try { TESTHR(pConnection.CreateInstance(__uuidof(Connection))); hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified); pConnection->CursorLocation = adUseClient; TESTHR(pcmd.CreateInstance(__uuidof(Command))); pcmd->CommandText = nprc; // procedure name pcmd->CommandType = adCmdStoredProc; _ParameterPtr pParm1 = pcmd->CreateParameter( _bstr_t("@P1"), adInteger, adParamOutput,0, codRet ); pcmd->Parameters->Append( pParm1 ); pcmd->ActiveConnection = pConnection; int hr = pcmd->Execute( 0, 0, adCmdStoredProc ); if( FAILED(hr) ) { codRet = -1; } else { pParm1 = pcmd->Parameters->GetItem(_bstr_t("@P1")); // obtain from the procedure codRet = pParm1->GetValue(); } } catch(_com_error ) { // // if necessary, process the execution error // codRet = -1; } if (pConnection) if (pConnection->State == adStateOpen) pConnection->Close(); ::CoUninitialize(); return((int)codRet); } // // // int SQLexecProcedureSignal( char *sSymbol, char* sProcedure ) { HRESULT hr = S_OK; _CommandPtr pcmd = NULL; _ConnectionPtr pConnection = NULL; _bstr_t strMessage; _bstr_t strAuthorID; ::CoInitialize(NULL); long codRet = 0; try { TESTHR(pConnection.CreateInstance(__uuidof(Connection))); hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified); pConnection->CursorLocation = adUseClient; TESTHR(pcmd.CreateInstance(__uuidof(Command))); pcmd->CommandText = sProcedure; // procedure name pcmd->CommandType = adCmdStoredProc; _ParameterPtr pParm1 = pcmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(sSymbol) ,sSymbol ); pcmd->Parameters->Append(pParm1); _ParameterPtr pParm2 = pcmd->CreateParameter( _bstr_t("@P1"), adInteger, adParamOutput,0, codRet ); pcmd->Parameters->Append( pParm2 ); pcmd->ActiveConnection = pConnection; int hr = pcmd->Execute( 0, 0, adCmdStoredProc ); if( FAILED(hr) ) { bool bSuccess = false; } pParm2 = pcmd->Parameters->GetItem(_bstr_t("@P1")); // obtain from the procedure codRet = pParm2->GetValue(); // printf("\n [%d] \n",codRet ); // OBTAINING from the procedure } catch(_com_error ) { // // if necessary, process the execution error // } if (pConnection) if (pConnection->State == adStateOpen) pConnection->Close(); ::CoUninitialize(); return((int)codRet); }
Ejemplo de llamada desde MQL4:
// Comments are reduced to make it appear simpler, the comments in the attached files are complete //+------------------------------------------------------------------+ //| | //| Copyright c 1999-2006, MetaQuotes Software Corp. | //| http://www.metaquotes.ru | //| YZMSSQLSample.mq4 | //| Yuriy Zaitsev | //+------------------------------------------------------------------+ // Example of integrating with MS SQL | //+------------------------------------------------------------------+ #property copyright "YURAZ Copyright(C) 2008" #property link "yzy @ mail.ru" //+------------------------------------------------------------------+ // DLL function library //+------------------------------------------------------------------+ #import "YZMSSQLExpertSample.dll" // Performing any actions on MS SQL Server, procedure is called SQLProcedureGetInt // Collecting ticks int SQLProcedureTickPut( string, int , double , double ,string ); int Prc = 0; int init() { // // SQLProcedureGetInt The function, once having called a certain procedure, // will return into MT4 int value, for example, parameters // stored on MS SQL server, formed by another software // Prc = SQLProcedureGetInt ("YZ_MT4_T1"); return(0); } int start() { int a; int RetCode = SQLProcedureTickPut( Symbol(), TimeCurrent() , Ask, Bid ,"YZ_MT4_TICK"); // call to the tick collecting procedure Print(" SQLProcedureTickPut (YZ_MT4_NEWDAY)"+ RetCode ); // Example: // on MS SQL server, you can filter signals formed using third-party software // neural networks // other software products // /* int Signal = SQLProcedureGetSignal (Symbol() , "YZ_MT4_SIGNAL" ); // procedure MS SQL , will return signal Print(" SQLProcedureGetSignal (Symbol() , YZ_MT4_SIGNAL )"+ Signal ); if ( Signal == OP_BUY ) { // the procedure has returned the signal and is recommending to buy } if ( Signal == OP_SELL ) { // the procedure has returned the signal and is recommending to sell } */ return(0); }
Script cargando el historial en MS SQL Server:
// // YURAZ 2008 yzh @ mail.ru // // script loading history onto MS SQL // reload all history for all currency pairs and for all TIMEFRAMES // in MS SQL // #import "YZMSSQLExpertSample.dll" int SQLProcedureHistoryPut( string, int , int, double , double ,double , double ,double ,int, string ); static int mPeriod[8]={PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1}; void start() { PutHistor("EURUSD"); PutHistor("USDCHF"); Comment(" LOADING COMPLETE " ); } void PutHistor(string sSymbol) { for ( int iPeriod = 0; iPeriod <= 8 ; iPeriod++ ) { int pPERIOD_XX = mPeriod[iPeriod]; int Bar = iBars(sSymbol,pPERIOD_XX ); // obtain the depth of history for the given timeframe // no progress bar organized for ( int iBar = Bar; iBar >= 0 ; iBar--) { Comment( "WAIT TIMEFRAME "+pPERIOD_XX+" SYMBOL "+sSymbol+" BARS "+iBar ); double o = iOpen (sSymbol,pPERIOD_XX,iBar); double h = iHigh (sSymbol,pPERIOD_XX,iBar); double l = iLow (sSymbol,pPERIOD_XX,iBar); double c = iClose (sSymbol,pPERIOD_XX,iBar); double v = iVolume(sSymbol,pPERIOD_XX,iBar); datetime d = iTime (sSymbol,pPERIOD_XX,iBar); int RetCode = SQLProcedureHistoryPut( sSymbol,pPERIOD_XX,d,o,h,l,c,v,iBar, "YZ_MT4_HISTORY"); // Print ( " YZ_MT4_HITSRY "+RetCode); } } }
Atención: Por desgracia, todo el historial se carga con bastante lentitud usando el script, pero fija claramente el número de barra y con gran calidad.
La mejor solución sería descargar las cotizaciones en un archivo de texto y cargarlas en MS SQL a través de IMPRT EXPORT DTS. La carga del historial M1 de 1999-2008 para cada símbolo tardará unos minutos.
El índice de la barra no se descarga durante la descarga al archivo de texto. Si decidimos que el índice de la barra será el número de barra, tendremos el problema de barras perdidas y, si modificamos o recargamos, los números de las barras descargadas pueden ser diferentes en MS SQL y en MT 4. No he resuelto este problema aún, pero supongo que puede resolverse recargando el historial después de la actualización del historial en alta calidad en el propio MT 4.
Descripción de los archivos adjuntos
![](https://c.mql5.com/2/16/txt.gif)
- Script en formato SQL como ejemplo de cómo crear bases, tablas y procedimientos en MS SQL Server.
![](https://c.mql5.com/2/16/mq4.gif)
- Script para cargar el historial en MS SQL
![](https://c.mql5.com/2/16/rar.gif)
- Proyecto DLL
![](https://c.mql5.com/2/16/mq4.gif)
Para adjuntarlo como un asesor experto al gráfico del símbolo, cuyos ticks deben recopilarse, podemos adjuntarlo a cualquier periodo de tiempo.
Conclusión
La integración con otros productos de software ampliará la funcionalidad de MetaTrader 4 y permitirá distribuir las tareas y funciones de un sistema de trading automatizado de manera más eficiente.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1533
![Indicadores de prueba de asesores expertos no de trading](https://c.mql5.com/2/16/627_11.gif)
![El espectáculo debe continuar, o una vez más sobre el ZigZag](https://c.mql5.com/2/16/620_30.gif)
![El análisis estadístico de los movimientos del mercado y su pronóstico](https://c.mql5.com/2/16/634_10.jpg)
![Falacias, Parte 2. La estadística es una pseudociencia o la "crónica de la caída en picado de cada día"](https://c.mql5.com/2/16/617_41.gif)
![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso