Integration von MetaTrader 4 Client Terminal mit MS SQL Server
Yuriy Zaytsev | 25 März, 2016
Einführung
Die Verwendung von Integrationen mit anderen Produkten bietet eine zusätzliche Herausforderung in Trading.
Es kann so viele Verwendungen davon geben, also werde ich einige von ihnen unten angeben
Sie können Ticks sammeln und diese an MS SQL SERVER zur weiteren Analyse übergeben. Mit einer großen Tick Historie, können Sie jede Periode sammeln, beginnend von dem minimalen Zeitschnitt und bis zu atypischen Perioden. Mit realen Tick Kursen können Sie Tick-Daten abhängige Strategien debuggen, bekannt als 'Scalper'.
Sie können einen Speicher für eine schnelle Analyse der von Anwendungen entnommenen Daten verwenden, zum Beispiel von MS Excel oder anderer Drittanbieter Software oder von Ihren eigenen Produkten.
Zum Beispiel, Sie können die gesamte Historie aus der Historiendatenbank des Terminals in MS SQL herunterladen. Dann müssen Sie nicht die Historie in MQL4 speichern. Dies wird helfen den Terminal-Speicher zu entlasten.
Sie können neuronale Netze mit in MS SQL SERVER gespeicherten Kursen berechnen: zum Beispiel, STATISTICA - 7.8 um Ihnen zu ermöglichen Kurse von SQL herunterzuladen, kann im Echtzeit-Modus gelöst werden, durch übergeben der Netz-Signale in MT4.
Sie können Ihr eigenes Programm in einer anderen Sprache oder für ein anderes Symbol entwickeln, und Signale mit MS SQL SERVVER übergeben, nur ausführende Funktionen für das Client Terminal belassen und es von ernsthaften Berechnungen entlasten.
Die folgende Software-Produkte wurden für dieses Projekt verwendet
- MS SQL SERVER 2000 Developer - BASE
- VISUAL C++ 6.0 SP5 - zum Erzeugen von DLL "YZMSSQLExpertSample.dll"
- MDAC 7
Der minimale zu installierende Satz:
1 MS SQL SERVER 2000 Developer
2 MDAC 7
Ich habe das Programm mit MDAC 7 debugged. Allerdings ist es möglich, dass alles mit einigen älteren Versionen ok funktioniert. Wenn Sie die DLL nicht kompilieren möchten, müssen Sie Visual C++ 6.0 nicht installieren oder installiert haben. Sie können eine fertige DLL verwenden. Allerdings habe ich den Benutzernamen in ihm, den Namen von DSN und Verbindungen festverdrahtet. Also müssen Sie alles oben aufgelistete in Ihrer Version des Programms wiederholen. Ich werde hier nicht beschrieben wie MS SQL SERVER oder Visual C++ 6.0 installiert werden, das liegt außerhalb des Bereichs dieses spezifischen Artikels.
Nachdem die notwendigen Software-Produkte installiert wurden, müssen mir ein DSN erstellen:
dsn=MT4_SQL_BASE;", "yuraz", "qwerty"
Beispiel von Tick-Empfang in MS SQL
Alle Experimente wurden mit MS SQL SERVER 2000 Developer durchgeführt. In Visual C++ 6.0, wurde YZMSSQLExpertSample.DLL erzeugt mit der Methode des Zugangs zu MS SQL via ADO. MDAC 7 oder MDAC 8 muss installiert sein. Ich werde nur die Beispiele beschreiben, wie man Verfahren und Tabellen erstellt. Der minimale Satz, den wir in MS SQL erstellen müssen ist die Datenbank, Tabellen und Verfahren. Betrachten wir die Tabelle und Prozeduren die mit Tick Kursen arbeiten. Sie können einige Funktionen hinzufügen, wenn Sie möchten.
Es ist notwendig eine Datenbank und Tabellen in MS SQL zu erstellen. Ich habe eine neue Datenbank mit dem Namen MT4TRADE erstellt. Dann müssen wir die Tabellen in ihr erstellen:MT4TICK - Tabelle der 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
Unten ist wie Tick-Empfang und Tabellierungsverfahren ersccheinen:
// // @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
Wir können aus der obigen Beschreibung erkennen welche Verfahren zu welchem Zweck verwendet werden.
@RetCode - es bringt keine Funktionalität, wenn von der DLL übergeben wird, es dient nur dem Empfang des Terminierungscode.
Die MS SQL SERVER Einrichtung ist abgeschlossen. Ein Skript zum Erstellen der Standard-Konfiguration ist an den Artikel angehangen.
Lassen Sie uns Fantasieren: Mögliche Lösungen und Pluspunkte
Wir können einen Datenspeicher erstellen und Informationen in/aus ihm platzieren/extrahieren. Auf diese Art können wir das MT4 Client Terminal von der Notwendigkeit die Kurs-Historie zu speichern entlasten. Jetzt ist die Kurs-Historie auf dem MS SQL SERVER gespeichert und wir können mit diesen Informationen arbeiten, sie schneller entnehmen und sie zu anderen Anwendungen exportieren. Wir können die Daten in NEURONALEN Paketen analysieren, von denen die meisten mit SQL Speichern arbeiten.
In der Echtzeit kann das Terminal fortfahren Signale von Indikatoren zu bilden und diese an den Speicher übergeben und auf diese Art fixieren. Eine externe Anwendung kann die Signale und die Historie in Echtzeit entnehmen, sie analysieren und Signale bilden, festlegen der Ausführung und die Speicherung der Protokolldatei auf dem MS SQL Server, und diese zur Ausführung an das Terminal senden.
Folglich erhalten wir Integration und funktionelle Verteilung unter beteiligten Anwendungen in einem automatisierten Handelskomplex.
Nun, wenn es keine Notwendigkeit zum Speichern der historischen Kurse mehr gibt, können wir es auf die folgende Weise einrichten. Setzen Sie die Mindest-Balken in Extras>Options>Charts, zum Beispiel, auf 5000. Das Terminal startet schneller, da es keinen Speicher für die große Historie zuweisen muss.
Quelltexte
DLL Code:
//+------------------------------------------------------------------+ //| 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); }
Beispiel des Aufrufs von 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); }
Skript zum Laden der Historie auf 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); } } }
Achtung: Leider wird die gesamte Historie mit dem Skript eher langsam geladen, aber es fixiert die Balkenanzahl klar und mit hoher Qualität.
Die beste Lösung wäre die Kurse in eine Textdatei zu entladen und diese über IMPRT EXPORT DTS in MS SQL zu laden. Das Laden der M1 Historie von 1999-2008 wird für jedes Symbol ein paar Minuten dauern.
Der Balken-Index wird nicht entladen, wenn Sie in eine Textdatei entladen. Wenn Sie entscheiden, dass der Balken-Index nur eine Zeilen-Nummer ist, werden Sie das Problem verpasster Balken haben und, wenn Sie ändern oder neu laden, kann die Anzahl der Balken in MS SQL und MT4 unterschiedlich sein. Ich habe das Problem noch nicht gelöst, aber ich vermute es kann gelöst werden durch neu-Laden der Historie nach einer hochwertigen Aktualisierung der Historie in MT4 selbst.
Beschreibung angehangener Dateien
CreateSQLallDate.txt (9.0 Kb)- Skript in SQL Format als ein Beispiel, wie Datenbanken, Tabellen und Verfahren in MS SQL Server erstellt.
SQLGETHISTORY.mq4 (1.4 Kb)- Skript zum Laden der Historie in MS SQL
YZMSSQLExpertSample.rar (89.9 Kb)
- DLL Projekt
Um als EA an ein Symbol-Chart angehangen zu werden, dessen Ticks gesammelt werden sollen: Sie können es an jeden Zeitrahmen anhängen.
Fazit
Integration mit anderen Software-Produkten wird die Funktionalität von MetaTrader 4 erweitern und ermöglichen die Verteilung von Aufgaben und Funktionen eines automatisierten Handelssystems effizienter zu verteilen.