MQL4 - automated forex trading   /  

Статьи

Cтатьи  Возможности  Интеграция MetaTrader 4 с MS SQL-сервером Авторизуйтесь или зарегистрируйтесь , чтобы добавить новую статью


Эта статья о возможностях
MetaTrader 4

Мобильный трейдинг!
Купите лицензию и торгуйте мобильно

Интеграция MetaTrader 4 с MS SQL-сервером [ en ]

Введение

Использование интеграции с другими продуктами открывает дополнительные возможности в трейдинге.


Способов применения может быть множество, приведу некоторые из них.

Вы можете собирать тики и передавать их в MS SQL SERVER для дальнейшего анализа. Имея большую историю тиков, можно собрать любой период начиная от самого минимального кванта времени до самого нестандартного периода. Имея реальные тиковые котировки, желающие могут отлаживать стратегии зависимые от тиковых данных - известные как пипсовщики.

Можно использовать хранилище для быстрого анализа данных из других приложений, например, EXCEL, и других сторонних программных продуктов или собственных.

К примеру, можно выгрузить всю историю из History Center терминала в MS SQL, и не хранить историю в MT4, тем самым разгрузив терминал от хранения большой истории.

Вы можете выполнять расчеты нейросети, используя хранимые котировки в MS SQL SERVER: к примеру STATISTICA - 7,8 позволяют загружать котировки из SQL, можно решить в реальном времени, передавая сигналы сети в MT4.

Вы можете разработать собственную программу на другом языке и инструменте и передавать сигналы и котировки, используя SQL SERVER, оставив терминалу лишь исполнительские функции и разгрузив его от серьезных расчетов.


При реализации проекта использовалось программное обеспечение

  • MS SQL SERVER 2000 Developer - БАЗА
  • VISUAL C++ 6.0 SP5 - для создания DLL "YZMSSQLExpertSample.dll"
  • MDAC 7


Минимум который необходимо инсталировать:

1 MS SQL SERVER 2000 Developer
2 MDAC 7

Я отлаживал на MDAC 7, возможно на более низких версиях тоже все будет работать. Если вы не собираетесь компилировать DLL, то инсталяция или наличие Visual C++ 6.0 не обязательно, можете использовать готовую DLL. Но я жестко прописал в ней имя пользователя, название DSN, соединения - их в этом случае прийдется повторить. Я не буду подробно описывать как инсталировать MS SQL SERVER или Visual C++ 6.0, это выходит за рамки темы.

После инсталяции ПО необходимо создать DSN,

dsn=MT4_SQL_BASE;", "yuraz", "qwerty"


Рассмотрим пример реализации приема тиков в MS SQL

Все опыты проводились с MS SQL SERVER 2000 Developer. На Visual C++ 6.0 была создана YZMSSQLExpertSample.DLL, используется метод доступа к MS SQL через ADO. Необходимо инсталлировать MDAC 7 или MDAC 8. Опишу лишь примеры создания процедур и таблиц. Минимально что нам потребуется - это создать на MS SQL базу, таблицы, процедуры; рассмотрим таблицу и процедуры для работы с тиковыми котировками. Далее функционал можно нарастить.


В MS SQL необходимо создать базу и таблицы, я сделал новую базу MT4TRADE. Далее в ней необходимо создать таблицы:

MT4TICK - таблица тиков


//-----------------------------------------------------------------------------------
//
//  Структура базы MT4TICK
//
//    idc             - Формируется автоматически, уникальный номер записи
//    ServerDateTime  - Заполняется автоматически, при добавлении записи
//                        Серверное локальное время - время помещения котировки в таблицу 
//                        ( не имеет ничего общего с датой в временем - которые передает МТ)
//                        это время которое отсчитывает сам сервер - оно будет совпадать с временем
//                        машины на котором запущен сервер. 
//--- 
//    iDateTime       - дата и время в формате MT4, передается из MT4
//    sSymbol         - инструмент
//    cAsk            - котировка Ask
//    cBid            - Котировка 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
 
--- Пропишем автоматическое заполнение поля ServerDateTime датой и временем сервера MS SQL
ALTER TABLE [dbo].[MT4TICK] ADD 
    CONSTRAINT [DF_MT4TICK_ServerDateTime] DEFAULT (getdate()) FOR [ServerDateTime]
GO

Процедура приема тика и записи в таблицу выглядит так:


// 
//    @RetCode int out          --- используется для возврата
//   ,@psSymbol char(6)         --- инструмент
//   ,@piDateTime  bigint       --- дата и время прихода тика
//   ,@pdAsk  float             --- Ask 
//   ,@pdBid  float             --- Bid
//  
//   Процедура просто возвращает 0 
//     если проанализировать код возврата в MQL4 то можно понять что  котировка дошла до процедуры и записана в таблицу
//     
//
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


по описанию видно какие параметры для чего используются.

@RetCode - при передаче из DLL он не несет функционала, он служит лишь для получения кода завершения.

Настройка MS SQL SERVER окончена. Скрипт по созданию типовой конфигурации прилагается.


Немного пофантазируем, возможные решения и плюсы.

Мы можем создать хранилище данных, помещать в него и извлекать информацию. Тем самым мы можем разгрузить терминал от функции хранения истории котировок в самом MT4. Теперь история котировок находится в SQL сервере в хранилище и мы можем оперировать этой информацией с большой скоростью извлекать ее в другие приложения. Мы можем использовать данные для аналитики в НЕЙРОННЫХ пакетах, большинство из которых умеет работать с хранилищами SQL.

В реальном времени можно оставить за терминалом функционал формирования сигналов от индикаторов с передачей их в хранилище, для фиксации, далее внешнее приложение в реальном времени может извлекать сигнал и историю, анализировать ее и формировать сигналы, фиксируя исполнение и хранение лога в SQL сервере, отправлять терминалу для исполнения.

Мы получаем интеграцию и распределение функционала между приложениями, задействованными в автоматизированном торговом комплексе.

Если в MT4 теперь нет надобности в хранении котировок, можно настроить его следующим образом. В интерфейсе MT4 сервис->настройки->графики выставить минимальное количество баров, например, 5000 баров. Терминал значительно быстрее работает так как не выделяет память под хранение большой истории.





Исходные тексты

Код DLL

//+------------------------------------------------------------------+
//|                                              Sample DLL for MQL4 |
//|                 Copyright c 2004-2006, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
 
//+------------------------------------------------------------------+
//
//  YURAZ 2008  YZMSSQLExpertSample
//
//  Пример  DLL интеграция  MT4  с MS SQL 2000
//
//  ADO  MS SQL SERVER
//
//  используемое программное обеспечение
//
//  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);
  }
 
 // укладываем тики в MS SQL
 // вызываем процедуру как SQL строку  передавая параметры   "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);
 }
*/
 
 // вызываем как процедуру передавая параметры
  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);
 }
 
 // уложить в историю MS SQL конкретную свечу
 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);
 }
 
 
 // вызываем процедуру sProcedure
 // 
 // возврат -1 ошибка
 //
 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); };
 
// метод вызова процедуры
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;  // имя  процедуры
      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"));     // получим из процедуры
         codRet = Par1->GetValue();
      }
   }
   catch(_com_error  ) {
       //
       // при необходимости обработаем ошибку исполнения
          //
       codRet = -1;
 
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}
 
 
 
// поместить в историю 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;  // имя  процедуры
      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"));     // получим из процедуры
         codRet = ParReturn->GetValue();
      }
   }
   catch(_com_error  ) {
       //
       // при необходимости обработаем ошибку исполнения
          //
       codRet = -1;
 
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}
 
 
//
// вернем значение возвращаемое процедурой
//
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;  // имя  процедуру
      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"));     // получим из процедуры
         codRet = pParm1->GetValue();
      }
   }
   catch(_com_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;  // имя  процедуру
      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"));     // получим из процедуры
            codRet = pParm2->GetValue();
 
//             printf("\n [%d] \n",codRet );       // ПОЛУЧАЕМ из процедуры
   }
   catch(_com_error  ) {
       //
       // при необходимости обработаем ошибку исполнения
          //
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}


Пример вызова из MQL4 -

// Помещаю с сокращениями комментариев для простоты восприятия, в прикрепленных файлах комментарии полные
 
//+------------------------------------------------------------------+
//|                                                                  |
//|                 Copyright c 1999-2006, MetaQuotes Software Corp. |
//|                                         http://www.metaquotes.ru |
//|                                                YZMSSQLSample.mq4 |
//|                                                   Yuriy Zaitsev  |
//+------------------------------------------------------------------+
// Пример интеграции с MS SQL                                        |
//+------------------------------------------------------------------+
 
#property copyright "YURAZ Copyright(C) 2008"
#property link      "yzн @ mail.ru"
 
//+------------------------------------------------------------------+
// Библиотека функций DLL 
//+------------------------------------------------------------------+
#import "YZMSSQLExpertSample.dll"
// Выполнение каких либо действий на MS SQL сервере, вызывается процедура
SQLProcedureGetInt 
// Сбор тиков
int SQLProcedureTickPut( string,  int , double , double ,string );  
 
int Prc = 0;
int init()
  {
 
//
// SQLProcedureGetInt Функция вызвав определенную процедуру , 
// вернет в MT4 int значение к примеру параметры
// сохраненные на MS SQL сервере , сформронанные иным программным обеспечением
//
   Prc =     SQLProcedureGetInt ("YZ_MT4_T1"); 
   return(0);
  }
 
int start()
  {
   int a;
 
   int RetCode = SQLProcedureTickPut( Symbol(), TimeCurrent() , Ask, Bid ,"YZ_MT4_TICK"); // вызываем процедуру сбора тиков
   Print(" SQLProcedureTickPut (YZ_MT4_NEWDAY)"+ RetCode );
 
// Как пример:
//    на сервере MS SQL возможно формировать сигналы  сформированные с помощью стороннего программного обеспечения
//    нейронных сетей 
//    других программных продуктов 
//
/*
   int Signal = SQLProcedureGetSignal (Symbol() , "YZ_MT4_SIGNAL" ); // процедура MS SQL , вернет сигнал
   Print(" SQLProcedureGetSignal (Symbol() , YZ_MT4_SIGNAL )"+ Signal );
   if ( Signal == OP_BUY )
   {
       // процедура вернула сигнал,  рекомендует покупку
   }
   if ( Signal == OP_SELL )
   {
       // процедура вернула сигнал,  рекомендует продажу
   }
*/
 
   return(0);
  }

Скрипт по загрузки истории в MS SQL сервер:

//
// YURAZ  2008 yzh @ mail.ru
//
// скрипт загрузки истории в MS SQL
// перегрузить всю историю по всем парам  по всем ТАЙМФРЕМАМ
// в 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(" ЗАГРУЗКА  ПРОИЗВЕДЕНА " );
}
 
void PutHistor(string sSymbol)
{
  for ( int iPeriod = 0; iPeriod <= 8 ; iPeriod++ )
  {
     int pPERIOD_XX = mPeriod[iPeriod];
      int Bar = iBars(sSymbol,pPERIOD_XX ); // получим глубину истории по данному тф
 // не организован прогресс бар 
     for ( int iBar = Bar; iBar >= 0 ; iBar--)
     {
     Comment( "ЖДИТЕ  Период "+pPERIOD_XX+" СИМВОЛ "+sSymbol+" БАРОВ "+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);
      }
  }
}

Внимание: к сожалению загрузка всей истории через скрипт происходит не быстро, но она четко и качественно фиксирует номер бара.

Лучшее решение - это выгрузка котировок в текстовый файл и загрузка в MS SQL через IMPRT EXPORT DTS. По времени загрузка минутки 1999-2008 занимает несколько минут по инструменту.
При выгрузке в текстовый файл не выгружается индекс бара. Если принять решение, что индексом бара будет просто порядковый номер строки, то нас ожидает проблема пропущенных баров, и при изменении - перезагрузки номера выгруженных баров в MS SQL и MT4 могут не совпасть. Пока я не решил эту проблему, но думаю, что ее решение вполне возможно перезагрузкой истории после качественного обновления истории в самом MT4.


Описание списка прикрепленных файлов

CreateSQLallDate.txt (9.0 Kb)

- Скрипт в формате SQL как пример создания баз, таблиц, процедур на MS SQL сервере

SQLGETHISTORY.mq4 (1.4 Kb)

- Скрипт для загрузки истории в MS SQL

YZMSSQLExpertSample.rar (89.9 Kb)

- проект DLL

YZMSSQLSample.mq4 (13.1 Kb) -

Вешается как советник на график инструмента, тики которого необходимо собирать, вешать можно на любой таймфрейм.


Заключение

Интеграция с другими продуктами расширяет функциональность MetaTrader 4, позволяет более качественно распределить задачи и функции автоматизированной торговой системы.

Прикрепленные файлы:
CreateSQLallDate.txt (9.0 Kb)
SQLGETHISTORY.mq4 (1.4 Kb)
YZMSSQLExpertSample.rar (89.9 Kb)
YZMSSQLSample.mq4 (13.1 Kb)
Создана: 26.05.2008  Автор: Yuriy Zaytsev
Предупреждение: все права на данные материалы принадлежат MetaQuotes Software Corp. Полная или частичная перепечатка запрещена.
Неторгующий эксперт тестирует индикаторы
Неторгующий эксперт тестирует индикаторы

Все индикаторы можно разделить на две группы: статические - изображение которых на истории остается статичным и не меняется с приходом новых котировок, и динамические - которые отображают свое состояние только для текущего момента времени и полностью переририсовываются при приходе новой цены. Работопригодность статического индикатора видна сразу на графике, а вот как проверить, что динамический индиктор работает правильно? Этому вопросу и посвящена данная статья.

Статистический анализ рыночных движений и их прогнозов
Статистический анализ рыночных движений и их прогнозов

В данной статье рассматриваются широкие возможности статистического подхода к изучению рынка. К сожалению, трейдеры-новички сознательно не используют эту поистине могущественную науку – статистику. А ведь, во-первых, это - единственное, чем они пользуются подсознательно при анализе рынка, а во-вторых, статистика может дать ответы на многие вопросы.

21 комментарий: 1 2 3   Авторизуйтесь или зарегистрируйтесь

Все отлично работает под SQL 2000 на ХР - оч. полезная и нужная штучка - СПАСИБО ЮРЕ БОЛЬШОЕ.

Но пришлось пересесть под SQL 2008 под Vista - и...

Коллеги, пжл, у кого есть возможность перекомпилить сборку YuraZ-а

с учетом написанного им 'В общем старая как мир тема. MQL MSSQL2005.'

ПОЖАЛУЙСТА сделайте

оч. нужно законнектиться к SQL 2008 под Vista

YuraZ писал(а) >>

проблема скорее всего тут

  • MDAC 7

и возможно тут

#import "C:\Program Files\Common Files\System\ado\msado20.tlb" \
rename("EOF","ADOEOF") rename("BOF","ADOBOF")

попробуйте обновить обертку

Заранее СПАСИБО.

25.05.2009 22:33 M1kha1l

'В общем старая как мир тема. MQL MSSQL2005.'

некоторые проблемы SQL 2005 2008

прошу подключиться всех. кто может оказать помощь

07.12.2008 01:16 YuraZ
chv писал(а):

Тестов производительности SQL я не проводил, не могу сказать об этом ничего. Лучше поискать готовые е-публикации.

Что касается FreeBSD и Unix - один знакомый админ сказал мне, что знает хорошо FreeBSD, немного Unix и не знает Linux. Из этого я и заключил, что это именно клоны, и знание одного не гарантирует знаний другого.

А Вы знаете такие толковые публикации на русском?
07.11.2008 10:49 OZ0
chv писал(а):

Тестов производительности SQL я не проводил, не могу сказать об этом ничего. Лучше поискать готовые е-публикации.

Что касается FreeBSD и Unix - один знакомый админ сказал мне, что знает хорошо FreeBSD, немного Unix и не знает Linux. Из этого я и заключил, что это именно клоны, и знание одного не гарантирует знаний другого.

 


Я не хочу ничего плохого сказать

 

но вывод немного неверный

 

из систем которые я описал Linix,  FreeBSD , UNIX-6, UNIX-7 , AIN,SUN OS,SCO,IBM (AIX) , SYSTEM-5...

мне не довелось видеть   AIN,  IBM (AIX), SYSTEM-5

но приходилось даже на EC1045 работать в  VMS  с какой то реализацией UNIX даже название не помню 

но после знаний UNIX-6 UNIX-7 и INMOS который был русcким клоном UNIX,  работа c этим UNIX проблем не представила

 

все это семейство UNIX

 

в том то и вся прелесть что в каждом клоне UNIX к примеру есть команда ls   с  типовыми ключами   которы во всех клонах  присутвуют

и переучиваться не надо - лишь некоторые тонкости могут отличаться 

практически во всех UNIX есть каталоги  /BIN /ETC /TMP  /USR

почти во всех UNIX в каталоге /ETC/PASSWORD живет

во всех /BIN/LS живет

 

поэтому если Ваш знакомый  отлично знает один из клонов UNIX  , а именно  FreeBSD ,

то он знает  семейство UNIX  в принципе  , а значит с клонами типа  LINUX разобраться сумеет без проблем

 

если Вы говорите о знаниях которые уже отложились на уровне подсознания - типа разбуди админа юниксоида

он без труда перечислит в каком каталоге какие системыне файлы лежат - но именно в том юнихе который он сопровождает

но дайте ему недельку другую - хороший админ освоит и другой юних без проблем -  потому,

что это не сложно и потому, что они принципиально не расходятся

проблемы сесть за штурвал любого клона никакой

 

было дело , изменил подсказку с > на #

подошел ко мне тогда начальник и спросил а ты откуда пароль рута знаешь?

я ему показал шутку - как меняется подсказка в окружении :-) он похихикал и успокоился

правда к тому времени у меня лежал в каталоге shell с битом супервизора

но в каталг этот системные утилиты попадать не могли , от того и не знал начальник как я реально изучал ЮНИХ  , ;-)

начальник не любил если кто то знал чуточку больше чем он, пресекал если кто то вдруг

образовываться начинал... боялся наверно за место свое... вот и пресекал

тогда в стране персоналок не было... дома не поизучать -  а он гад не давал

 

системные утилиты не видели мой PS как рутовый , потому как исходники у юниха есть

и все утилиты  начиная с ps login ls find who и многие другие  ,

 которые могли обнаружить и залогировать мое присутвие

были перекомпилированны что бы мой PS не показывать как PS рута и не видеть мои скрытые каталоги

---

так что исходники с одной стороны это хорошо

а с другой попав разок в систему

она  потом практически может не видеть кто в ней находится

только лампочки на модемах или  концентраторах мигают диски шуршат ну мало ли что там юних делает

---

отрытые операционки достаточно уязвимы

имеют  клонов

т к  имеют открытые исходники

 

 

03.06.2008 00:27 YuraZ

Тестов производительности SQL я не проводил, не могу сказать об этом ничего. Лучше поискать готовые е-публикации.

Что касается FreeBSD и Unix - один знакомый админ сказал мне, что знает хорошо FreeBSD, немного Unix и не знает Linux. Из этого я и заключил, что это именно клоны, и знание одного не гарантирует знаний другого.

 

02.06.2008 16:58 chv
chv писал(а):
YuraZ писал(а):

Шустродейсвие MySQL повыше..  но необходимо ставить UNIX машину...  ( со слов коллег, сам не работал с MySQL )

реализация под MySQL была описана и путь пройден , под MS SQL описанной реализации не было.


Это не совсем так, MySql работает на разных платформах. Дома у меня локальная копия сайта с базой под MySql + Apache работает в составе пакета Denwer на Windows XP SP3. У хостера сайт и MySql база работает под FreeBSD, тоже не совсем Unix.

..

Итог.

Делайте базы на чём хотите и что знаете :)
главное - избежать в будущем миграции огромном по размеру базы с одной СУБД на другую.

на WIN XP  MySQL так же бодр  как и на UNIX машине ?

---

2 Вы пишите что FreeBSD не совсем UNIX...

  а что Вы подразумеваете под тогда если убрать приставку "НЕ"


вообще то UNIX в моем понимании это не конкретная  операционная система

это некий КЛОН ...

т е Linix,  FreeBSD , UNIX-6, UNIX-7 , AIN,SUN OS,SCO,IBM (AIX) , SYSTEM-5... и т д   все это  клоны UNIX

кроме того у каждого клона своя реализация - версия


точно так же как и WINDOWS имеет несколько реализаций да и любая ОС


MS DOS имела к примеру клон DR-DOS...




02.06.2008 14:35 YuraZ
YuraZ писал(а):

Шустродейсвие MySQL повыше..  но необходимо ставить UNIX машину...  ( со слов коллег, сам не работал с MySQL )

реализация под MySQL была описана и путь пройден , под MS SQL описанной реализации не было.


Это не совсем так, MySql работает на разных платформах. Дома у меня локальная копия сайта с базой под MySql + Apache работает в составе пакета Denwer на Windows XP SP3. У хостера сайт и MySql база работает под FreeBSD, тоже не совсем Unix.

Чего мне не хватает в базах MySql, это ограничения некоторого синтаксиса и функций. Например, написать так в MySql нельзя:

SELECT * 
FROM `catalog` 
WHERE ID
IN (

SELECT ID
FROM `catalog` 
ORDER BY id DESC 
LIMIT 3
)

Получим ошибку: "#1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'".

В MS SQL запросто (таблица только другая в примере):

SELECT *
  FROM [dbo].[Terminal]
where
    ID IN (
        select top 3
        [ID]
        from [dbo].[Terminal]
        order by [ID] desc
    )

Не работал лично с MySql выше 4-й версии (5-я на хостерах мало где есть), но в 4-й и ниже версиях MySql нет ни триггеров, ни views, ни хранимых процедур. Для сайта пока хватает, мирюсь с этим, PHP+MySql более дешёвый хостинг, быстрее что-то поменять по мелочи. Но в целом для профессиональных баз предпочитаю выбор из Oracle или MS SQL. Рабочей базы под MySql на 50 Гб вживую пока не видел, хотя это не значит, что их нет.

Вообще это дело вкуса.

По поводу производительности - однозначного ответа нет, можете посмотреть статьи "MySQL vs MS SQL Server", это сайт о MySql, там сравнивают в основном MS SQL 2000 и MySql 5.0, упоминая о том, что по тестам июня 2006г. MS SQL 2005 x64 занял 1-е место. Там же сравнивается и функциональность СУБД. Нашёл и такую статью: "Производительность и масштабируемость: SQL Server Benchmarks", обратите внимание на фразу "существует масса доказательств того, что SQL Server более производителен, масштабируем и дешев чем любой из конкурентов". Имеется ввиду сравнение коммерческих (платных) версий MySQL и MS SQL серверов.

Итог.

Делайте базы на чём хотите и что знаете :)
главное - избежать в будущем миграции огромном по размеру базы с одной СУБД на другую.

28.05.2008 23:29 chv
YuSP писал(а):

При выгрузке в текстовый файл не выгружается индекс бара. Если принять решение, что индексом бара будет просто порядковый номер строки,

то нас ожидает проблема пропущенных баров, и при изменении - перезагрузки номера выгруженных баров в MS SQL и MT4 могут не совпасть.

Пока я не решил эту проблему, но думаю, что ее решение вполне возможно перезагрузкой истории после качественного обновления истории

в самом MT4.

  Если в качестве индекса бара (первичного ключа) использовать строковое представление времени этого бара, то проблема решается. Для нескольких символов и/или таймфреймов в одной таблице можно использовать сложный индекс (первичный ключ) - время бара + символ [+ обозначение таймфрейма]. 

отчасти эта проблема надумана мной, согласен... имея время открытия бара по сути индекс бара не нужен.
28.05.2008 06:41 YuraZ
YuSP писал(а):

 А почему MS-SQL - для MySQL эта же задача выглядит существенно проще и, по-моему, реализация более универсальна (TicksInMySQL).-

Можно использовать любой SQL-запрос, не возвращающий данных от SQL-сервера. Хоть структуру данных составляй и привилегии пользователей прописывай прямо из MQL4, не говоря уже об обновлении или добавлении данных в таблицы.

 Сразу скажу, 10Gb сам не пробовал загонять в MySQL, но по документации размер таблиц в нем ограничивается только операционной системой на которой он стоит + кластеризация + партиционирование (одну таблицу можно на несколько серверов разнести). Что касается скорости выборки данных (а это важно для тестирования стратегий при таких объемах данных), MySQL, установленный на легковесной системе типа FreeBSD или QNX будет пошустрее MS-SQL (правда ничего не могу сказать насчет последнего MS-SQL на платформе MS Windows Server 2008, работающем в режиме ядра - говорят что он ощутимо быстрее своих предшественников). С другой стороны, может ли себе начинающий трейдер позволить купить  MS-SQL + MS Windows Server 2008, или ждать пока поломают?

 A MySQL - LGPL-продукт, законно можно качать новейшие версии и использовать для некоммерческих целей, таких как тестирование стратегий. 

 Еще один плюс MySQL - за умеренную плату можно использовать вычислительные мощности серверов Интернет-провайдеров.  

Шустродейсвие MySQL повыше..  но необходимо ставить UNIX машину...  ( со слов коллег, сам не работал с MySQL )

реализация под MySQL была описана и путь пройден , под MS SQL описанной реализации не было.

кроме того у кого то есть под рукой MS SQL у кого то MySQL.  Хотя используя принцип не важно по сути какой сервер.

При написании статьи преследовал цели, привести простой пример использования связки MT с MS SQL,  просто показать интеграцию.

28.05.2008 06:39 YuraZ

При выгрузке в текстовый файл не выгружается индекс бара. Если принять решение, что индексом бара будет просто порядковый номер строки,

то нас ожидает проблема пропущенных баров, и при изменении - перезагрузки номера выгруженных баров в MS SQL и MT4 могут не совпасть.

Пока я не решил эту проблему, но думаю, что ее решение вполне возможно перезагрузкой истории после качественного обновления истории

в самом MT4.

  Если в качестве индекса бара (первичного ключа) использовать строковое представление времени этого бара, то проблема решается. Для нескольких символов и/или таймфреймов в одной таблице можно использовать сложный индекс (первичный ключ) - время бара + символ [+ обозначение таймфрейма]. 

28.05.2008 01:33 YuSP
21 комментарий: 1 2 3