Compare commits

...

64 Commits

Author SHA1 Message Date
DW 5b76bf0547 Merge master fixed conflict. 2017-01-05 21:36:55 +02:00
DW 1c269f7339 Issue #32: Added function ObjectName into test client 2017-01-05 02:14:13 +02:00
DW 21fb790d8c Issue #32: Fixed small bugs in EA MtApi.mq4 2017-01-05 01:02:55 +02:00
DW 7c9a0aa8cc Issue #32: Implement object functions in EA MtApi.mq4 2017-01-03 21:29:41 +02:00
DW 18ddf3df1c Issue #32: Added c# implementations of most object functions in MtApi client 2016-12-30 17:16:48 +02:00
DW a8832b79ba Issue #32: Added function ObjectCreate in MtApi (MT4) 2016-12-27 17:41:11 +02:00
vdemydiuk 39146d68b2 Starting work on Object Functions 2016-12-26 17:49:06 +02:00
DW 5b03f01e9b Clear unnecessary witespaces in MtApi.mq4 2016-12-21 14:26:37 +02:00
vdemydiuk 8f5a1c8222 Refactored MtApi.mq4 2016-12-21 12:01:15 +02:00
vdemydiuk f5f13a13cc Issue #32: Added function ChartRedraw 2016-12-12 17:29:52 +02:00
vdemydiuk 9ef970cf1e Refactoring TestApiUiClient (Account Information tab) 2016-11-30 10:57:33 +02:00
vdemydiuk b5878ccb62 Refactoring TestApiUiClient (Check Status tab) 2016-11-29 19:08:53 +02:00
DW 4a7bb6f2cb MtApi (MT5) ver. 1.0.11.1 HotFix 2016-11-29 10:20:55 +02:00
vdemydiuk 5abfeebc90 Issue #32: Added function ChartId 2016-11-28 16:03:40 +02:00
vdemydiuk e333164552 Issue #32: Added ExecutorHandle property to determine which expert will be used for execution command 2016-11-28 14:45:33 +02:00
vdemydiuk 9a6968f618 Refactoring MtApi 2016-11-26 19:27:09 +02:00
DW d63a53b8a9 MtApi (MT4) version 1.0.32.1 (HotFix) 2016-11-25 16:06:11 +02:00
DW 7e821fcade Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-25 15:50:56 +02:00
DW 88e2d22abe Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-23 13:09:47 +02:00
DW fcfd741e5b Issue #37: Used ConcurrencyMode.Multiple for server and client side to avoid deadlocks and freezes of MtApiService 2016-11-23 10:51:50 +02:00
DW c722511c03 Refactored MtApiService (ver. 1.0.24): Added ExpertHandle to MtQuote and MtEvent. Added event QuoteUpdate to MtApiClient. 2016-11-18 15:47:55 +02:00
DW 39599436ab Started version 1.0.33 of MtApi MT4 2016-11-18 12:13:00 +02:00
vdemydiuk 8e3f206c76 Issue #35: Implemented function TerminalInfoDouble in MtApi MT4 2016-11-15 11:06:43 +02:00
vdemydiuk 8e5dcbd2ee Issue #31: Implemented function TerminalInfoInteger in MtApi MT4 2016-11-15 10:02:30 +02:00
vdemydiuk 563a5a895b Issue #31: Implemented function SymbolInfoTick in MtApi MT4 2016-11-14 16:31:01 +02:00
vdemydiuk 32f6018858 Issue #31: Implemented function SymbolInfoDouble in MtApi MT4 2016-11-14 14:04:31 +02:00
vdemydiuk c64417474a Issue #33: Implemented function SeriesInfoInteger (MtApi MT4) 2016-11-13 23:24:38 +02:00
vdemydiuk 6d4b5f4c00 Issue #27: Created bootstrapper project for MtApi MT4 with vcredist package 2016-11-11 17:56:17 +02:00
vdemydiuk 601c95369e Recovered MtApi.ex4 2016-11-11 17:54:33 +02:00
vdemydiuk 0542dd3e71 Started MtApi (MT4) version 1.0.32 2016-11-11 17:53:43 +02:00
vdemydiuk 15068ca99c Issue #30: Added MtApi5 Bootstrapper project to merge installer and vcredist packages 2016-11-08 17:38:51 +02:00
vdemydiuk c3617549f8 Updated version of MtApiService to 1.0.23 2016-11-08 14:16:09 +02:00
vdemydiuk aa91196e31 Updated license text in MtApi5 installer 2016-11-07 13:45:18 +02:00
vdemydiuk ba7b50e241 Issue #29: Added process Id into name of log file 2016-11-07 13:05:36 +02:00
vdemydiuk ddcd6fa2d5 Issue #25: Implemented function CopyTicks. Used json request 2016-11-05 00:52:52 +02:00
vdemydiuk ad55740bc7 Started MtApi (MT5) version 1.0.11 2016-11-03 13:07:48 +02:00
vdemydiuk 26a3db9ae1 Small refactoring testing application (MT4) 2016-11-02 11:25:47 +02:00
DW 7d3af82e1f Updated testing application (MT4) to test functions: SymbolsTotal, SymbolName, SymbolSelect, SymbolInfoInteger 2016-11-01 18:43:49 +02:00
DW 09b72fc64d Added function SymbolInfoInteger into MtApi (MT4). Added function sendLongResponse into library MTConnector 2016-11-01 12:49:39 +02:00
DW 834b0af430 Started version 1.0.31 MtApi (MT4) 2016-11-01 10:32:29 +02:00
DW 5dd1e4831d Merge branch Add_sessions 2016-11-01 10:28:24 +02:00
DW 39f11bfc34 Merge branch Manage_symbols 2016-11-01 10:18:22 +02:00
vdemydiuk c6faaf0602 Issue #26: Use tick event function to perform MtApi commands in testing mode 2016-10-31 17:59:55 +02:00
vdemydiuk c14726bdba Issue #23: Added empty constructor to class MqlRates, made public setters of properties 2016-10-24 11:58:14 +03:00
vdemydiuk 05452e3b90 Issue #21: Added function Print to MtApi (MT5) 2016-10-21 17:52:54 +03:00
vdemydiuk 094cdcc448 Issue #13: changed timeout values of SendTime and ReceiveTime on client side and server sides (12 hours) 2016-10-20 10:19:52 +03:00
vdemydiuk a63e628124 Updated test application for working with MtApi (MT5) version 1.0.10 2016-10-17 11:57:54 +03:00
vdemydiuk 7fec3da7bc Update readme 2016-10-12 17:01:22 +03:00
vdemydiuk 1d407b5e16 Changed sign key in library MtApiService: using MtApiKey.snk. Added logging into MtApiService and used ILMerge.Task to merge assemblies into one dll. 2016-10-12 16:37:54 +03:00
vdemydiuk e373f7976c Refactoring MtApiService 2016-10-11 12:23:47 +03:00
vdemydiuk 3785ee4ace Small refactoring MtApi (MT5) and MtService. Started version 1.0.22 of MtService 2016-10-10 15:49:53 +03:00
vdemydiuk b4b8e7eaf0 MtApi (MT5): Disabled backtesting in mql expert 2016-10-10 13:37:47 +03:00
vdemydiuk 22f7915a4a Merge branch 'mtapi5_backtesting' 2016-10-10 13:27:17 +03:00
vdemydiuk 84dfd21f9f Fixed issue #17: fix error in test client 2016-10-07 17:42:36 +03:00
vdemydiuk d4ee2cfada Issue #16: implemented backtesting functionality into MtApi5 2016-10-07 17:08:16 +03:00
vdemydiuk 0b3d686f05 Fixed issue #17 2016-10-07 17:05:06 +03:00
vdemydiuk cacc0ea787 Implemented function PositionOpen. Made small refactoring 2016-10-06 14:04:17 +03:00
vdemydiuk d96dc18ea3 Issue #19: added comment about WIX Tools 2016-10-06 13:32:56 +03:00
Konstantin Ivanov 6b4adfaa97 Add method SymbolInfoSession() 2016-10-05 17:02:00 +03:00
vdemydiuk 7aa2a1b691 Used WM_TIMER message to perform commands in MQL expert 2016-10-05 11:18:46 +03:00
vdemydiuk 5739423d6c Starting to work on MtApi (MT5) version 1.0.10 2016-10-05 10:29:03 +03:00
Konstantin Ivanov db4bb44fb3 Add SymbolSelect() and use existing local variables 2016-09-29 17:13:41 +03:00
Konstantin Ivanov 68d5fa98af Add SymbolName() 2016-09-29 16:30:11 +03:00
Konstantin Ivanov dc28823ca9 add SymbolsTotal() 2016-09-29 16:14:53 +03:00
152 changed files with 9384 additions and 7196 deletions
Executable
BIN
View File
Binary file not shown.
+341 -341
View File
@@ -21,57 +21,57 @@ using namespace System::Security;
#pragma pack(push, 1)
public struct CMqlRates
{
__int64 time; // Period start time
double open; // Open price
double high; // The highest price of the period
double low; // The lowest price of the period
double close; // Close price
__int64 tick_volume; // Tick volume
int spread; // Spread
__int64 real_volume; // Trade volume
__int64 time; // Period start time
double open; // Open price
double high; // The highest price of the period
double low; // The lowest price of the period
double close; // Close price
__int64 tick_volume; // Tick volume
int spread; // Spread
__int64 real_volume; // Trade volume
};
public struct CMqlTick
{
__int64 time; // Time of the last prices update
double bid; // Current Bid price
double ask; // Current Ask price
double last; // Price of the last deal (Last)
unsigned __int64 volume; // Volume for the current Last price
__int64 time; // Time of the last prices update
double bid; // Current Bid price
double ask; // Current Ask price
double last; // Price of the last deal (Last)
unsigned __int64 volume; // Volume for the current Last price
};
public struct CMqlBookInfo
{
int type; // Order type from ENUM_BOOK_TYPE enumeration
double price; // Price
__int64 volume; // Volume
int type; // Order type from ENUM_BOOK_TYPE enumeration
double price; // Price
__int64 volume; // Volume
};
#pragma pack(pop)
void convertSystemString(wchar_t* dest, String^ src)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
}
bool VerifySignature(System::String^ inputData, System::String^ signature, System::String^ publicKey)
{
bool verifyResult = false;
bool verifyResult = false;
try
{
DSACryptoServiceProvider^ dsa = gcnew DSACryptoServiceProvider();
dsa->FromXmlString(publicKey);
array<System::Byte>^ data = UTF8Encoding::ASCII->GetBytes(inputData);
array<System::Byte>^ signatureData = Convert::FromBase64String(signature);
verifyResult = dsa->VerifyData(data, signatureData);
}
catch(Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:VerifySignature(): failed. " + e->Message);
verifyResult = false;
}
try
{
DSACryptoServiceProvider^ dsa = gcnew DSACryptoServiceProvider();
dsa->FromXmlString(publicKey);
array<System::Byte>^ data = UTF8Encoding::ASCII->GetBytes(inputData);
array<System::Byte>^ signatureData = Convert::FromBase64String(signature);
verifyResult = dsa->VerifyData(data, signatureData);
}
catch(Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:VerifySignature(): failed. " + e->Message);
verifyResult = false;
}
return verifyResult;
}
@@ -80,431 +80,431 @@ bool g_IsVerified = true;
void _stdcall verify(int isDemo, wchar_t* accountName, long accountNumber)
{
if (isDemo != 0)
{
g_IsVerified = true;
return;
}
if (isDemo != 0)
{
g_IsVerified = true;
return;
}
System::String^ signature = MtRegistryManager::ReadSignatureKey(gcnew String(accountName), accountNumber.ToString());
Resources::ResourceManager^ rm = gcnew Resources::ResourceManager(L"MT5Connector.cl", Assembly::GetExecutingAssembly());
System::String^ inputData = gcnew System::String(accountName);
inputData += accountNumber.ToString();
System::String^ publicKey = rm->GetString(L"cl");
g_IsVerified = VerifySignature(inputData, gcnew System::String(signature), publicKey);
System::String^ signature = MtRegistryManager::ReadSignatureKey(gcnew String(accountName), accountNumber.ToString());
Resources::ResourceManager^ rm = gcnew Resources::ResourceManager(L"MT5Connector.cl", Assembly::GetExecutingAssembly());
System::String^ inputData = gcnew System::String(accountName);
inputData += accountNumber.ToString();
System::String^ publicKey = rm->GetString(L"cl");
g_IsVerified = VerifySignature(inputData, gcnew System::String(signature), publicKey);
}
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
if (g_IsVerified == false)
{
System::String^ errorVerified = "Verification is failed!\nPlease contact with support.";
convertSystemString(err, errorVerified);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): not verified");
return 0;
}
if (g_IsVerified == false)
{
System::String^ errorVerified = "Verification is failed!\nPlease contact with support.";
convertSystemString(err, errorVerified);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): not verified");
return 0;
}
try
{
MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): " + e->Message);
try
{
MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:deinitExpert(): " + e->Message);
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:updateQuote(): " + e->Message);
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:updateQuote(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall sendIntResponse(int expertHandle, int response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendLongResponse(int expertHandle, __int64 response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendULongResponse(int expertHandle, unsigned __int64 response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendBooleanResponse(int expertHandle, int response)
{
try
{
bool value = (response != 0) ? true : false;
try
{
bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendDoubleResponse(int expertHandle, double response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendVoidResponse(int expertHandle)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
{
try
{
array<double>^ list = gcnew array<double>(size);
try
{
array<double>^ list = gcnew array<double>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
{
try
{
array<int>^ list = gcnew array<int>(size);
try
{
array<int>^ list = gcnew array<int>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendLongArrayResponse(int expertHandle, __int64* values, int size)
{
try
{
array<System::Int64>^ list = gcnew array<System::Int64>(size);
try
{
array<System::Int64>^ list = gcnew array<System::Int64>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int size)
{
try
{
array<MtMqlRates^>^ list = gcnew array<MtMqlRates^>(size);
try
{
array<MtMqlRates^>^ list = gcnew array<MtMqlRates^>(size);
for(int i = 0; i < size; i++)
{
MtMqlRates^ rates = gcnew MtMqlRates();
rates->time = values[i].time;
rates->open = values[i].open;
rates->high = values[i].high;
rates->low = values[i].low;
rates->close = values[i].close;
rates->tick_volume = values[i].tick_volume;
rates->spread = values[i].spread;
rates->real_volume = values[i].real_volume;
for(int i = 0; i < size; i++)
{
MtMqlRates^ rates = gcnew MtMqlRates();
rates->time = values[i].time;
rates->open = values[i].open;
rates->high = values[i].high;
rates->low = values[i].low;
rates->close = values[i].close;
rates->tick_volume = values[i].tick_volume;
rates->spread = values[i].spread;
rates->real_volume = values[i].real_volume;
list[i] = rates;
}
list[i] = rates;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlTickResponse(int expertHandle, CMqlTick* response, int size)
{
try
{
MtMqlTick^ mtResponse = gcnew MtMqlTick();
try
{
MtMqlTick^ mtResponse = gcnew MtMqlTick();
mtResponse->time = response->time;
mtResponse->bid = response->bid;
mtResponse->ask = response->ask;
mtResponse->last = response->last;
mtResponse->volume = response->volume;
mtResponse->time = response->time;
mtResponse->bid = response->bid;
mtResponse->ask = response->ask;
mtResponse->last = response->last;
mtResponse->volume = response->volume;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlTickResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlTickResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlBookInfoArrayResponse(int expertHandle, CMqlBookInfo values[], int size)
{
try
{
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
try
{
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
for(int i = 0; i < size; i++)
{
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
for(int i = 0; i < size; i++)
{
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
info->type = values[i].type;
info->price = values[i].price;
info->volume = values[i].volume;
info->type = values[i].type;
info->price = values[i].price;
info->volume = values[i].volume;
list[i] = info;
}
list[i] = info;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
//----------- get values -------------------------------
int _stdcall getCommandType(int expertHandle, int* res)
{
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getCommandType(): " + e->Message);
return 0;
}
return 1;
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getCommandType(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
{
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getIntValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getIntValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
{
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
{
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getStringValue(): " + e->Message);
return 0;
}
return 1;
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getStringValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getULongValue(int expertHandle, int paramIndex, unsigned __int64* res)
{
try
{
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getULongValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getULongValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res)
{
try
{
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getLongValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getLongValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
{
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getUIntValue(int expertHandle, int paramIndex, unsigned int* res)
{
try
{
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getUIntValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getUIntValue(): " + e->Message);
return 0;
}
return 1;
}
+9 -9
View File
@@ -9,16 +9,16 @@ using namespace MTApiService;
ref class MT5Handler: IMetaTraderHandler
{
public:
MT5Handler()
{
msgId = WM_USER + 4096;
}
MT5Handler()
{
msgId = WM_TIMER;
}
virtual void SendTickToMetaTrader(int handle)
{
PostMessage((HWND)handle, msgId, 0x00000011, 0);
}
virtual void SendTickToMetaTrader(int handle)
{
PostMessage((HWND)handle, msgId, 0, 0);
}
private:
unsigned int msgId;
unsigned int msgId;
};
+2 -3
View File
@@ -1,8 +1,7 @@
namespace MTApiService
{
public interface ICommandManager
internal interface ICommandManager
{
void EnqueueCommandTask(MtCommandTask task);
MtCommandTask DequeueCommandTask();
MtCommandTask SendCommand(MtCommand task);
}
}
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- -->
<!-- ILMerge project-specific settings. Almost never need to be set explicitly. -->
<!-- for details, see http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx -->
<!-- -->
<!-- *** set this file to Type=None, CopyToOutput=Never *** -->
<!-- If True, all copy local dependencies will also be merged from referenced projects whether they are referenced in the current project explicitly or not -->
<ILMergeTransitive>true</ILMergeTransitive>
<!-- Extra ILMerge library paths (semicolon-separated). Dont put your package dependencies here, they will be added automagically -->
<ILMergeLibraryPath></ILMergeLibraryPath>
<!-- The solution NuGet package directory if not standard 'SOLUTION\packages' -->
<ILMergePackagesPath></ILMergePackagesPath>
<!-- The merge order file name if differs from standard 'ILMergeOrder.txt' -->
<ILMergeOrderFile></ILMergeOrderFile>
<!-- The strong key file name if not specified in the project -->
<ILMergeKeyFile>MtApiKey.snk</ILMergeKeyFile>
<!-- The assembly version if differs for the version of the main assembly -->
<ILMergeAssemblyVersion></ILMergeAssemblyVersion>
<!-- added in Version 1.0.4 -->
<ILMergeFileAlignment></ILMergeFileAlignment>
<!-- added in Version 1.0.4, default=none -->
<ILMergeAllowDuplicateType></ILMergeAllowDuplicateType>
<!-- If the <see cref="CopyAttributes"/> is also set, any assembly-level attributes names that have the same type are copied over into the target assembly -->
<ILMergeAllowMultipleAssemblyLevelAttributes></ILMergeAllowMultipleAssemblyLevelAttributes>
<!-- See ILMerge documentation -->
<ILMergeAllowZeroPeKind></ILMergeAllowZeroPeKind>
<!-- The assembly level attributes of each input assembly are copied over into the target assembly -->
<ILMergeCopyAttributes></ILMergeCopyAttributes>
<!-- Creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies, default=true -->
<ILMergeDebugInfo></ILMergeDebugInfo>
<!-- Target assembly will be delay signed -->
<ILMergeDelaySign></ILMergeDelaySign>
<!-- Types in assemblies other than the primary assembly have their visibility modified -->
<ILMergeInternalize></ILMergeInternalize>
<!-- The path name of the file that will be used to identify types that are not to have their visibility modified -->
<ILMergeInternalizeExcludeFile></ILMergeInternalizeExcludeFile>
<!-- XML documentation files are merged to produce an XML documentation file for the target assembly -->
<ILMergeXmlDocumentation></ILMergeXmlDocumentation>
<!-- External assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true, default value) -->
<ILMergePublicKeyTokens></ILMergePublicKeyTokens>
<!-- Types with the same name are all merged into a single type in the target assembly -->
<ILMergeUnionMerge></ILMergeUnionMerge>
<!-- The version of the target framework, default 40 (works for 45 too) -->
<ILTargetPlatform></ILTargetPlatform>
</PropertyGroup>
</Project>
+4
View File
@@ -0,0 +1,4 @@
# this file contains the partial list of the merged assemblies in the merge order
# you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build
# and finetune merge order to your satisfaction
+2 -5
View File
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace MTApiService
{
public interface IMtApiServer
{
MtResponse SendCommand(MtCommand command);
IEnumerable<MtQuote> GetQuotes();
List<MtQuote> GetQuotes();
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MTApiService
{
internal interface ITaskExecutor
{
void Execute(MtCommandTask task);
int Handle { get; }
}
}
+52
View File
@@ -0,0 +1,52 @@
using System;
using System.Diagnostics;
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
namespace MTApiService
{
public class LogConfigurator
{
private const string LogFileNameExtension = "txt";
public static void Setup(string profileName)
{
if (string.IsNullOrEmpty(profileName))
throw new ArgumentNullException();
var hierarchy = (Hierarchy) LogManager.GetRepository();
var patternLayout = new PatternLayout
{
ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
};
patternLayout.ActivateOptions();
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
var roller = new RollingFileAppender
{
AppendToFile = false,
File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}",
Layout = patternLayout,
PreserveLogFileNameExtension = true,
MaxSizeRollBackups = 5,
MaximumFileSize = "1GB",
RollingStyle = RollingFileAppender.RollingMode.Size,
StaticLogFileName = false
};
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
#if (DEBUG)
hierarchy.Root.Level = Level.Debug;
#else
hierarchy.Root.Level = Level.Info;
#endif
hierarchy.Configured = true;
}
}
}
+30 -5
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,6 +15,8 @@
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -35,12 +38,17 @@
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>MtApiKey.pfx</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.5\lib\net40-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
@@ -54,6 +62,8 @@
<ItemGroup>
<Compile Include="ICommandManager.cs" />
<Compile Include="IMetaTraderHandler.cs" />
<Compile Include="ITaskExecutor.cs" />
<Compile Include="LogConfigurator.cs" />
<Compile Include="MtCommandEventArgs.cs" />
<Compile Include="IDisposableChannel.cs" />
<Compile Include="IMtApiServer.cs" />
@@ -69,22 +79,37 @@
<Compile Include="MtConnectionProfile.cs" />
<Compile Include="MtExecutorManager.cs" />
<Compile Include="MtExpert.cs" />
<Compile Include="MtInstrument.cs" />
<Compile Include="MtQuote.cs" />
<Compile Include="MtResponse.cs" />
<Compile Include="MtServer.cs" />
<Compile Include="MtCommand.cs" />
<Compile Include="MtServerInstance.cs" />
<Compile Include="MtAdapter.cs" />
<Compile Include="MtService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="MtApiKey.pfx" />
<None Include="ILMerge.props">
<SubType>Designer</SubType>
</None>
<None Include="MtApiKey.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="ILMergeOrder.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props'))" />
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets'))" />
</Target>
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
+277
View File
@@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using log4net;
namespace MTApiService
{
public class MtAdapter
{
#region Fields
private const string LogProfileName = "MtApiService";
private static readonly ILog Log = LogManager.GetLogger(typeof(MtAdapter));
private static readonly MtAdapter Instance = new MtAdapter();
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
#endregion
#region Init Instance
private MtAdapter()
{
LogConfigurator.Setup(LogProfileName);
}
static MtAdapter()
{
}
public static MtAdapter GetInstance()
{
return Instance;
}
#endregion
#region Public Methods
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
MtServer server;
lock (_servers)
{
if (_servers.ContainsKey(port))
{
server = _servers[port];
}
else
{
server = new MtServer(port);
server.Stopped += server_Stopped;
_servers[port] = server;
server.Start();
}
}
var expert = new MtExpert(expertHandle, new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle }, mtHandler);
lock (_experts)
{
_experts[expert.Handle] = expert;
}
server.AddExpert(expert);
Log.Info("InitExpert: end");
}
public void DeinitExpert(int expertHandle)
{
Log.InfoFormat("DeinitExpert: begin. expertHandle = {0}", expertHandle);
MtExpert expert = null;
lock (_experts)
{
if (_experts.ContainsKey(expertHandle))
{
expert = _experts[expertHandle];
_experts.Remove(expertHandle);
}
}
if (expert != null)
{
expert.Deinit();
}
else
{
Log.WarnFormat("DeinitExpert: expert with id {0} has not been found.", expertHandle);
}
Log.Info("DeinitExpert: end");
}
public void SendQuote(int expertHandle, string symbol, double bid, double ask)
{
Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert != null)
{
expert.Quote = new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle };
}
else
{
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendQuote: end");
}
public void SendEvent(int expertHandle, int eventType, string payload)
{
Log.DebugFormat("SendEvent: begin. eventType = {0}, payload = {1}", eventType, payload);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert != null)
{
expert.SendEvent(new MtEvent { EventType = eventType, Payload = payload, ExpertHandle = expertHandle });
}
else
{
Log.WarnFormat("SendEvent: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendEvent: end");
}
public void SendResponse(int expertHandle, MtResponse response)
{
Log.DebugFormat("SendResponse: begin. id = {0}, response = {1}", expertHandle, response);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert != null)
{
expert.SendResponse(response);
}
else
{
Log.WarnFormat("SendResponse: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendResponse: end");
}
public int GetCommandType(int expertHandle)
{
Log.DebugFormat("GetCommandType: begin. expertHandle = {0}", expertHandle);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetCommandType: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandType() ?? 0;
Log.DebugFormat("GetCommandType: end. retval = {0}", retval);
return retval;
}
public object GetCommandParameter(int expertHandle, int index)
{
Log.DebugFormat("GetCommandParameter: begin. expertHandle = {0}, index = {1}", expertHandle, index);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetCommandParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandParameter(index);
Log.DebugFormat("GetCommandParameter: end. retval = {0}", retval);
return retval;
}
public object GetNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("GetNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetNamedParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetNamedParameter(name);
Log.DebugFormat("GetNamedParameter: end. retval = {0}", retval);
return retval;
}
public bool ContainsNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("ContainsNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("ContainsNamedParameter: expert with id {0} has not been found.", expertHandle);
}
bool retval = expert != null ? expert.ContainsNamedParameter(name) : false;
Log.DebugFormat("ContainsNamedParameter: end. retval = {0}", retval);
return retval;
}
#endregion
#region Private Methods
private void server_Stopped(object sender, EventArgs e)
{
var server = (MtServer)sender;
server.Stopped -= server_Stopped;
var port = server.Port;
Log.InfoFormat("server_Stopped: port = {0}", port);
lock (_servers)
{
if (_servers.ContainsKey(port))
{
_servers.Remove(port);
}
}
}
#endregion
}
}
Binary file not shown.
BIN
View File
Binary file not shown.
+11 -14
View File
@@ -1,26 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace MTApiService
{
class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
internal class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
{
public MtApiProxy(InstanceContext callbackContext, Binding binding,
EndpointAddress remoteAddress)
public MtApiProxy(InstanceContext callbackContext, Binding binding, EndpointAddress remoteAddress)
: base(callbackContext, binding, remoteAddress)
{
base.InnerDuplexChannel.Faulted += new EventHandler(InnerDuplexChannel_Faulted);
base.InnerDuplexChannel.Open();
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
}
#region IMtApi Members
public bool Connect()
{
InnerDuplexChannel.Open();
return Channel.Connect();
}
@@ -34,7 +31,7 @@ namespace MTApiService
return Channel.SendCommand(command);
}
public IEnumerable<MtQuote> GetQuotes()
public List<MtQuote> GetQuotes()
{
return Channel.GetQuotes();
}
@@ -47,19 +44,19 @@ namespace MTApiService
{
try
{
this.Close();
Close();
}
catch (CommunicationException)
{
this.Abort();
Abort();
}
catch (TimeoutException)
{
this.Abort();
Abort();
}
catch (Exception)
{
this.Abort();
Abort();
}
}
@@ -68,9 +65,9 @@ namespace MTApiService
#region Private Methods
private void InnerDuplexChannel_Faulted(object sender, EventArgs e)
{
if (Faulted != null)
Faulted(this, e);
Faulted?.Invoke(this, e);
}
#endregion
#region Events
+173 -183
View File
@@ -1,206 +1,203 @@
using System;
using System.Diagnostics;
using System.Collections;
using System.ServiceModel;
using System.Collections.Generic;
using log4net;
namespace MTApiService
{
[CallbackBehavior(UseSynchronizationContext = false)]
public class MtClient: IMtApiCallback, IDisposable
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class MtClient : IMtApiCallback, IDisposable
{
private static string SERVICE_NAME = "MtApiService";
private const string ServiceName = "MtApiService";
public delegate void MtQuoteHandler(MtQuote quote);
public delegate void MtEventHandler(MtEvent e);
#region Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient));
private readonly MtApiProxy _proxy;
#endregion
#region ctor
public MtClient(string host, int port)
{
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException(nameof(host), "host is null or empty");
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
Host = host;
Port = port;
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
var bind = new NetTcpBinding(SecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = new TimeSpan(12, 0, 0),
ReceiveTimeout = new TimeSpan(12, 0, 0),
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
}
public MtClient(int port)
{
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
Port = port;
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = new TimeSpan(12, 0, 0),
ReceiveTimeout = new TimeSpan(12, 0, 0),
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
}
#endregion
#region Public Methods
public void Open(string host, int port)
{
Debug.WriteLine("[INFO] MtClient::Open");
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException("host", "host is null or empty");
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException("port", "port value is invalid");
var urlService = string.Format("net.tcp://{0}:{1}/{2}", host, port, SERVICE_NAME);
lock (mClientLocker)
{
if (mProxy != null)
return;
var bind = new NetTcpBinding(SecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
mProxy.Faulted += mProxy_Faulted;
}
}
public void Open(int port)
{
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException("port", "port value is invalid");
var urlService = string.Format("net.pipe://localhost/{0}_{1}", SERVICE_NAME, port);
lock (mClientLocker)
{
if (mProxy != null)
return;
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
mProxy.Faulted += mProxy_Faulted;
}
}
public void Close()
{
Debug.WriteLine("[INFO] MtClient::Close");
lock (mClientLocker)
{
if (mProxy != null)
{
mProxy.Faulted -= mProxy_Faulted;
mProxy.Dispose();
mProxy = null;
}
mIsConnected = false;
}
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public void Connect()
{
Debug.WriteLine("[INFO] MtClient::Connect");
Log.Debug("Connect: begin.");
if (_proxy.State != CommunicationState.Created)
{
Log.ErrorFormat("Connected: end. Client has invalid state {0}", _proxy.State);
return;
}
bool coonected;
try
{
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
return;
mIsConnected = mProxy.Connect();
if (mIsConnected == false)
throw new Exception("Connected failed");
}
coonected = _proxy.Connect();
}
catch (Exception ex)
{
Debug.WriteLine("[ERROR] MtClient::Connect: {0}", ex.Message);
Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
Close();
throw new CommunicationException(string.Format("Connection failed to service"));
throw new CommunicationException($"Connection failed to service. {ex.Message}");
}
if (coonected == false)
{
Log.Error("Connect: end. Connection failed.");
throw new CommunicationException("Connection failed");
}
Log.Debug("Connect: end.");
}
public void Disconnect()
{
Debug.WriteLine("[INFO] MtClient::Disconnect");
Log.Debug("Disconnect: begin.");
try
{
lock (mClientLocker)
{
mIsConnected = false;
if (mProxy != null)
mProxy.Disconnect();
}
_proxy.Disconnect();
}
catch (Exception ex)
{
Debug.WriteLine("[ERROR] MtClient::Disconnect: {0}", ex.Message);
Close();
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
}
Log.Debug("Disconnect: end.");
}
public MtResponse SendCommand(int commandType, ArrayList commandParameters)
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> namedParams, int expertHandle)
{
Debug.WriteLine("[INFO] MtClient::SendCommand: commandType = {0}", commandType);
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
MtResponse result = null;
if (IsConnected == false)
{
Log.Error("SendCommand: Client is not connected.");
throw new CommunicationException("Client is not connected.");
}
MtResponse result;
try
{
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
result = mProxy.SendCommand(new MtCommand(commandType, commandParameters));
}
result = _proxy.SendCommand(new MtCommand {
CommandType = commandType,
Parameters = parameters,
NamedParams = namedParams,
ExpertHandle = expertHandle});
}
catch (Exception ex)
{
Debug.WriteLine("[ERROR] MtClient::SendCommand: {0}", ex.Message);
Close();
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
throw new CommunicationException("Service connection failed! " + ex.Message);
}
Log.DebugFormat("SendCommand: end. result = {0}", result);
return result;
}
public IEnumerable<MtQuote> GetQuotes()
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public List<MtQuote> GetQuotes()
{
Debug.WriteLine("[INFO] MtClient::GetQuotes");
Log.Debug("GetQuotes: begin.");
IEnumerable<MtQuote> result = null;
if (IsConnected == false)
{
Log.Warn("GetQuotes: end. Client is not connected.");
return null;
}
List<MtQuote> result;
try
{
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
result = mProxy.GetQuotes();
}
result = _proxy.GetQuotes();
}
catch (Exception ex)
{
Debug.WriteLine("[ERROR] MtClient::GetQuotes: {0}", ex.Message);
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
Close();
throw new CommunicationException("Service connection failed");
throw new CommunicationException($"Service connection failed! {ex.Message}");
}
return result;;
Log.DebugFormat("GetQuotes: end. quotes count = {0}", result?.Count);
return result;
}
#endregion
@@ -209,74 +206,71 @@ namespace MTApiService
public void OnQuoteUpdate(MtQuote quote)
{
if (quote != null)
{
if (QuoteUpdated != null)
{
QuoteUpdated(quote);
}
Log.DebugFormat("OnQuoteUpdate: begin. quote = {0}", quote);
Debug.WriteLine("[INFO] MtClient::OnQuoteUpdate: " + quote);
}
if (quote == null) return;
QuoteUpdated?.Invoke(quote);
Log.Debug("OnQuoteUpdate: end.");
}
public void OnQuoteAdded(MtQuote quote)
{
Debug.WriteLine("[INFO] MtClient::OnQuoteAdded");
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
QuoteAdded?.Invoke(quote);
Log.Debug("OnQuoteAdded: end.");
}
public void OnQuoteRemoved(MtQuote quote)
{
Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved");
Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
QuoteRemoved?.Invoke(quote);
Log.Debug("OnQuoteRemoved: end.");
}
public void OnServerStopped()
{
Debug.WriteLine("[INFO] MtClient::OnServerStopped");
Close();
Log.Debug("OnServerStopped: begin.");
ServerDisconnected?.Invoke(this, EventArgs.Empty);
Log.Debug("OnServerStopped: end.");
}
public void OnMtEvent(MtEvent mtEvent)
public void OnMtEvent(MtEvent e)
{
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
Log.DebugFormat("OnMtEvent: begin. event = {0}", e);
MtEventReceived?.Invoke(e);
Log.Debug("OnMtEvent: end.");
}
#endregion
#region Properties
public bool IsConnected
{
get
{
lock (mClientLocker)
{
return mProxy.State == CommunicationState.Opened && mIsConnected == true;
}
}
}
public string Host { get; private set; }
public int Port { get; private set; }
private bool IsConnected => _proxy.State == CommunicationState.Opened;
#endregion
#region Private Methods
void mProxy_Faulted(object sender, EventArgs e)
private void ProxyFaulted(object sender, EventArgs e)
{
Debug.WriteLine("[INFO] MtClient::mProxy_Faulted");
Log.Debug("ProxyFaulted: begin.");
Close();
ServerFailed?.Invoke(this, EventArgs.Empty);
if (ServerFailed != null)
{
ServerFailed(this, EventArgs.Empty);
}
Log.Debug("ProxyFaulted: end.");
}
#endregion
@@ -285,9 +279,11 @@ namespace MTApiService
public void Dispose()
{
Debug.WriteLine("[INFO] MtClient::Dispose");
Log.Debug("Dispose: begin.");
Close();
_proxy.Dispose();
Log.Debug("Dispose: end.");
}
#endregion
@@ -298,13 +294,7 @@ namespace MTApiService
public event MtQuoteHandler QuoteUpdated;
public event EventHandler ServerDisconnected;
public event EventHandler ServerFailed;
public event EventHandler<MtEventArgs> MtEventReceived;
#endregion
#region Fields
private readonly object mClientLocker = new object();
private MtApiProxy mProxy = null;
private bool mIsConnected = false;
public event MtEventHandler MtEventReceived;
#endregion
}
}
+16 -15
View File
@@ -1,26 +1,27 @@
using System;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
using System.Collections;
using System.Collections.Generic;
namespace MTApiService
{
[DataContract]
public class MtCommand
{
public MtCommand(int commandType, ArrayList parameters)
[DataMember]
public int CommandType { get; set; }
[DataMember]
public ArrayList Parameters { get; set; }
[DataMember]
public Dictionary<string, object> NamedParams { get; set; }
[DataMember]
public int ExpertHandle { get; set; }
public override string ToString()
{
CommandType = commandType;
Parameters = parameters;
return $"CommandType = {CommandType}; ExpertHandle = {ExpertHandle}";
}
[DataMember]
public int CommandType { get; private set; }
[DataMember]
public ArrayList Parameters { get; private set; }
}
}
Regular → Executable
+11 -3
View File
@@ -1,4 +1,5 @@
using System.Threading;
using System;
using System.Threading;
namespace MTApiService
{
@@ -10,6 +11,9 @@ namespace MTApiService
public MtCommandTask(MtCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
Command = command;
}
@@ -20,7 +24,7 @@ namespace MTApiService
_responseWaiter.WaitOne(time);
lock (_locker)
{
return _result;
return _result;
}
}
@@ -32,6 +36,10 @@ namespace MTApiService
}
_responseWaiter.Set();
}
public override string ToString()
{
return $"Command = {Command}";
}
}
}
+1 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService
{
public class MtConnectionProfile
+5 -18
View File
@@ -7,30 +7,17 @@ namespace MTApiService
public class MtEvent
{
[DataMember]
public int EventType { get; private set; }
public int EventType { get; internal set; }
[DataMember]
public string Payload { get; private set; }
public string Payload { get; internal set; }
public MtEvent(int eventType, string payload)
{
EventType = eventType;
Payload = payload;
}
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return "MtEvent = " + EventType + ", Payload = " + Payload;
return $"EventType = {EventType}; Payload = {Payload}; ExpertHandle = {ExpertHandle}";
}
}
public class MtEventArgs: EventArgs
{
public MtEventArgs(MtEvent e)
{
Event = e;
}
public MtEvent Event { get; private set; }
}
}
+73 -95
View File
@@ -1,137 +1,115 @@
using System;
using System.Collections.Generic;
using log4net;
namespace MTApiService
{
internal class MtCommandExecutorManager : ICommandManager
internal class MtExecutorManager : ICommandManager
{
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExecutorManager));
private readonly List<ITaskExecutor> _executorList = new List<ITaskExecutor>();
private readonly Dictionary<int, ITaskExecutor> _executorMap = new Dictionary<int, ITaskExecutor>();
private readonly object _locker = new object();
#endregion
#region Public Methods
public void Stop()
{
Log.Debug("Stop: begin.");
lock (_locker)
{
_commandExecutors.Clear();
_commandTasks.Clear();
_executorList.Clear();
_executorMap.Clear();
}
Log.Debug("Stop: end.");
}
public void AddCommandExecutor(MtExpert commandExecutor)
public void AddExecutor(ITaskExecutor executor)
{
if (commandExecutor == null)
return;
if (executor == null)
throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("AddExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker)
{
if (_commandExecutors.Contains(commandExecutor))
if (_executorList.Contains(executor))
{
Log.Warn("AddExecutor: end. Executor already exist.");
return;
_commandExecutors.Add(commandExecutor);
if (_commandTasks.Count > 0)
{
notify = true;
}
_executorList.Add(executor);
_executorMap[executor.Handle] = executor;
}
commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted;
commandExecutor.CommandManager = this;
if (notify)
{
NotifyCommandReady();
}
Log.Debug("AddCommandExecutor: end.");
}
public void RemoveCommandExecutor(MtExpert commandExecutor)
public void RemoveExecutor(ITaskExecutor executor)
{
if (commandExecutor == null)
return;
if (executor == null)
throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("RemoveExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker)
{
if (_commandExecutors.Contains(commandExecutor) == false)
if (_executorList.Contains(executor) == false)
{
Log.Warn("RemoveExecutor: end. Executor is not exist in collection.");
return;
}
_commandExecutors.Remove(commandExecutor);
if (_commandTasks.Count > 0)
_executorList.Remove(executor);
_executorMap.Remove(executor.Handle);
}
Log.Debug("RemoveExecutor: end.");
}
public MtCommandTask SendCommand(MtCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
var task = new MtCommandTask(command);
Log.DebugFormat("SendTask: begin. command = {0}", command);
ITaskExecutor executor;
lock (_locker)
{
if (_executorMap.ContainsKey(command.ExpertHandle))
{
notify = true;
executor = _executorMap[command.ExpertHandle];
}
else
{
executor = _executorList.Count > 0 ? _executorList[0] : null;
}
}
commandExecutor.CommandExecuted -= CommandExecutor_CommandExecuted;
commandExecutor.CommandManager = null;
if (notify)
if (executor == null)
{
NotifyCommandReady();
Log.Error("SendTask: Executor is null!");
}
else
{
executor.Execute(task);
}
Log.Debug("SendTask: end.");
return task;
}
public void EnqueueCommandTask(MtCommandTask task)
{
if (task == null)
return;
lock (_locker)
{
_commandTasks.Enqueue(task);
}
NotifyCommandReady();
}
public MtCommandTask DequeueCommandTask()
{
lock (_locker)
{
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
}
}
#endregion
#region Private Methods
private void NotifyCommandReady()
{
var commandExecutors = new List<MtExpert>();
lock (_locker)
{
commandExecutors.AddRange(_commandExecutors);
}
foreach (var executor in commandExecutors)
{
executor.NotifyCommandReady();
}
}
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
{
var notify = false;
lock (_locker)
{
if (_commandTasks.Count > 0)
{
notify = true;
}
}
if (notify)
{
NotifyCommandReady();
}
}
#endregion
#region Private Fields
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
private readonly object _locker = new object();
#endregion
}
}
+165 -101
View File
@@ -1,25 +1,161 @@
using System;
using log4net;
using System.Collections.Generic;
namespace MTApiService
{
public class MtExpert
internal class MtExpert: ITaskExecutor
{
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
public delegate void MtEventHandler(MtExpert expert, MtEvent e);
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _currentTask;
private readonly Queue<MtCommandTask> _taskQueue = new Queue<MtCommandTask>();
private readonly object _locker = new object();
#endregion
#region Public Methods
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
Quote = quote;
Handle = handle;
_mtHadler = mtHandler;
}
public void Deinit()
{
Log.Debug("Deinit: begin.");
IsEnable = false;
FireOnDeinited();
Log.Debug("Deinit: end.");
}
public void SendResponse(MtResponse response)
{
Log.DebugFormat("SendResponse: begin. response = {0}", response);
_currentTask.SetResult(response);
_currentTask = null;
Log.Debug("SendResponse: end.");
}
public int GetCommandType()
{
Log.Debug("GetCommandType: called.");
_currentTask = DequeueTask();
return _currentTask?.Command?.CommandType ?? 0;
}
public object GetCommandParameter(int index)
{
Log.DebugFormat("GetCommandParameter: called. index = {0}", index);
var command = _currentTask?.Command;
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
{
return command.Parameters[index];
}
return null;
}
public object GetNamedParameter(string name)
{
Log.DebugFormat("GetNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("GetNamedParameter: command is not defined in task.");
return null;
}
if (command.NamedParams == null)
{
Log.Warn("GetNamedParameter: NamedParams is not defined in command.");
return null;
}
return command.NamedParams[name];
}
public bool ContainsNamedParameter(string name)
{
Log.DebugFormat("ContainsNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("ContainsNamedParameter: command is not defined in task.");
return false;
}
if (command.NamedParams == null)
{
Log.Warn("ContainsNamedParameter: NamedParams is not defined in command.");
return false;
}
return command.NamedParams.ContainsKey(name);
}
public void SendEvent(MtEvent mtEvent)
{
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
FireOnMtEvent(mtEvent);
Log.Debug("SendEvent: end.");
}
public override string ToString()
{
return $"ExpertHandle = {Handle}";
}
#endregion
#region ITaskExecutor
public void Execute(MtCommandTask task)
{
lock (_taskQueue)
{
_taskQueue.Enqueue(task);
}
NotifyCommandReady();
}
#endregion
#region Properties
private MtQuote _quote;
public MtQuote Quote
public MtQuote Quote
{
get
{
lock (_locker)
{
return _quote;
return _quote;
}
}
set
{
lock(_locker)
lock (_locker)
{
_quote = value;
}
@@ -28,7 +164,7 @@ namespace MTApiService
}
}
public int Handle { get; private set; }
public int Handle { get; }
private bool _isEnable = true;
public bool IsEnable
@@ -49,93 +185,34 @@ namespace MTApiService
}
}
public ICommandManager CommandManager
{
private get
{
lock (_locker)
{
return _commandManager;
}
}
set
{
lock (_locker)
{
_commandManager = value;
}
}
}
#endregion
#region Public Methods
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
{
Quote = quote;
Handle = handle;
_mtHadler = mtHandler;
}
public void Deinit()
{
IsEnable = false;
FireOnDeinited();
}
public void SendResponse(MtResponse response)
{
_commandTask.SetResult(response);
_commandTask = null;
FireOnCommandExecuted();
}
public int GetCommandType()
{
var commandManager = CommandManager;
if (commandManager != null)
{
_commandTask = commandManager.DequeueCommandTask();
}
return _commandTask != null && _commandTask.Command != null ? _commandTask.Command.CommandType : 0;
}
public object GetCommandParameter(int index)
{
if (_commandTask != null)
{
var command = _commandTask.Command;
if (command != null && command.Parameters != null
&& index >= 0 && index < command.Parameters.Count)
{
return command.Parameters[index];
}
}
return null;
}
public void SendEvent(MtEvent mtEvent)
{
FireOnMtEvent(mtEvent);
}
#endregion
#region IMtCommandExecutor
public void NotifyCommandReady()
{
SendTickToMetaTrader();
}
#endregion
#region Private Methods
private void SendTickToMetaTrader()
private MtCommandTask DequeueTask()
{
if (_mtHadler != null)
Log.Debug("DequeueTask: called.");
MtCommandTask task;
int count;
lock (_locker)
{
_mtHadler.SendTickToMetaTrader(Handle);
count = _taskQueue.Count;
task = _taskQueue.Count > 0 ? _taskQueue.Dequeue() : null;
}
Log.DebugFormat("DequeueTask: end. left task count = {0}.", count);
return task;
}
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
_mtHadler.SendTickToMetaTrader(Handle);
Log.Debug("NotifyCommandReady: end.");
}
private void FireOnQuoteChanged(MtQuote quote)
@@ -148,29 +225,16 @@ namespace MTApiService
Deinited?.Invoke(this, EventArgs.Empty);
}
private void FireOnCommandExecuted()
{
CommandExecuted?.Invoke(this, EventArgs.Empty);
}
private void FireOnMtEvent(MtEvent mtEvent)
{
OnMtEvent?.Invoke(this, new MtEventArgs(mtEvent));
OnMtEvent?.Invoke(this, mtEvent);
}
#endregion
#region Events
public event EventHandler Deinited;
public event MtQuoteHandler QuoteChanged;
public event EventHandler CommandExecuted;
public event EventHandler<MtEventArgs> OnMtEvent;
#endregion
#region Private Fields
private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _commandTask;
private ICommandManager _commandManager;
private readonly object _locker = new object();
public event MtEventHandler OnMtEvent;
#endregion
}
}
-33
View File
@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; private set; }
[DataMember]
public double Bid { get; private set; }
[DataMember]
public double Ask { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
Instrument = instrument;
Bid = bid;
Ask = ask;
}
public override string ToString()
{
return "Instrument = " + Instrument + ", Bid = " + Bid + ", Ask = " + Ask;
}
}
}
+1 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
namespace MTApiService
{
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
namespace MTApiService
{
+1 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
namespace MTApiService
{
+15 -18
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
@@ -10,34 +7,34 @@ namespace MTApiService
public class MtMqlTradeRequest
{
[DataMember]
public int Action { get; set; }
public int Action { get; set; }
[DataMember]
public uint Magic { get; set; }
public uint Magic { get; set; }
[DataMember]
public uint Order { get; set; }
public uint Order { get; set; }
[DataMember]
public string Symbol { get; set; }
public string Symbol { get; set; }
[DataMember]
public double Volume { get; set; }
public double Volume { get; set; }
[DataMember]
public double Price { get; set; }
public double Price { get; set; }
[DataMember]
public double Stoplimit { get; set; }
public double Stoplimit { get; set; }
[DataMember]
public double Sl { get; set; }
public double Sl { get; set; }
[DataMember]
public double Tp { get; set; }
public double Tp { get; set; }
[DataMember]
public uint Deviation { get; set; }
public uint Deviation { get; set; }
[DataMember]
public int Type { get; set; }
public int Type { get; set; }
[DataMember]
public int Type_filling { get; set; }
public int Type_filling { get; set; }
[DataMember]
public int Type_time { get; set; }
public int Type_time { get; set; }
[DataMember]
public DateTime Expiration { get; set; }
public DateTime Expiration { get; set; }
[DataMember]
public string Comment { get; set; }
public string Comment { get; set; }
}
}
+25
View File
@@ -0,0 +1,25 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; internal set; }
[DataMember]
public double Bid { get; internal set; }
[DataMember]
public double Ask { get; internal set; }
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return $"Instrument = {Instrument}; Bid = {Bid}; Ask = {Ask}; ExpertHandle = {ExpertHandle}";
}
}
}
+89 -83
View File
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Diagnostics;
@@ -9,12 +7,12 @@ namespace MTApiService
{
public class MtRegistryManager
{
private const string SOFTWARE = "Software";
private const string APP_NAME = "MtApi";
private const string PROFILES_REGKEY = "ConnectionProfiles";
private const string HOST_REGVALUE_NAME = "Host";
private const string PORT_REGVALUE_NAME = "Port";
private const string SIGNATURE_REGVALUE_NAME = "MtSignature";
private const string Software = "Software";
private const string AppName = "MtApi";
private const string ProfilesRegkey = "ConnectionProfiles";
private const string HostRegvalueName = "Host";
private const string PortRegvalueName = "Port";
private const string SignatureRegvalueName = "MtSignature";
#region Public Methods
public static IEnumerable<MtConnectionProfile> LoadConnectionProfiles()
@@ -53,12 +51,12 @@ namespace MTApiService
string signature = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null)
{
using (softwareRegKey)
{
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null)
{
using (appRegKey)
@@ -73,7 +71,7 @@ namespace MTApiService
{
using (numberKey)
{
signature = numberKey.GetValue(SIGNATURE_REGVALUE_NAME).ToString();
signature = numberKey.GetValue(SignatureRegvalueName).ToString();
}
}
}
@@ -94,7 +92,7 @@ namespace MTApiService
return null;
}
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRgKey == null)
return null;
@@ -105,35 +103,33 @@ namespace MTApiService
{
//app name
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
if (appRegKey == null)
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey != null)
{
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
}
using (appRegKey)
{
//account name
var accountKey = appRegKey.OpenSubKey(accountName, true);
if (accountKey == null)
using (appRegKey)
{
accountKey = appRegKey.CreateSubKey(accountName);
}
//account name
var accountKey = appRegKey.OpenSubKey(accountName, true) ?? appRegKey.CreateSubKey(accountName);
using (accountKey)
{
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true);
if (numberKey == null)
if (accountKey != null)
{
numberKey = accountKey.CreateSubKey(accountNumber);
}
using (accountKey)
{
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true) ??
accountKey.CreateSubKey(accountNumber);
using (numberKey)
{
numberKey.SetValue(SIGNATURE_REGVALUE_NAME, signature);
if (numberKey != null)
{
using (numberKey)
{
numberKey.SetValue(SignatureRegvalueName, signature);
retVal = numberKey.ToString();
retVal = numberKey.ToString();
}
}
}
}
}
}
@@ -142,20 +138,19 @@ namespace MTApiService
return retVal;
}
public static bool ExportKey(string RegKey, string SavePath)
public static bool ExportKey(string regKey, string savePath)
{
string path = "\"" + SavePath + "\"";
string key = "\"" + RegKey + "\"";
var path = $"\"{savePath}\"";
var key = $"\"{regKey}\"";
Process proc = new Process();
var proc = new Process();
try
{
proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false;
proc = Process.Start("regedit.exe", "/e " + path + " " + key + "");
if (proc != null)
proc.WaitForExit();
proc?.WaitForExit();
}
catch(Exception)
{
@@ -163,8 +158,7 @@ namespace MTApiService
}
finally
{
if (proc != null)
proc.Dispose();
proc?.Dispose();
}
return true;
@@ -177,33 +171,38 @@ namespace MTApiService
{
List<MtConnectionProfile> profiles = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null)
{
using (softwareRegKey)
{
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null)
{
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey != null)
{
using (profilesRegKey)
{
profiles = new List<MtConnectionProfile>();
foreach (string profileNameKey in profilesRegKey.GetSubKeyNames())
foreach (var profileNameKey in profilesRegKey.GetSubKeyNames())
{
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileNameKey))
var tempKey = profilesRegKey.OpenSubKey(profileNameKey);
if (tempKey != null)
{
var profile = new MtConnectionProfile(profileNameKey);
using (tempKey)
{
var profile = new MtConnectionProfile(profileNameKey)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
profiles.Add(profile);
profiles.Add(profile);
}
}
}
}
@@ -220,27 +219,33 @@ namespace MTApiService
{
MtConnectionProfile profile = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null)
{
using (softwareRegKey)
{
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null)
{
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey != null)
{
using (profilesRegKey)
{
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileName))
var tempKey = profilesRegKey.OpenSubKey(profileName);
if (tempKey != null)
{
profile = new MtConnectionProfile(profileName);
using (tempKey)
{
profile = new MtConnectionProfile(profileName)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
}
}
}
}
@@ -254,7 +259,7 @@ namespace MTApiService
private static void SaveConnectionProfileToRegistry(MtConnectionProfile profile)
{
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRgKey == null)
return;
@@ -262,29 +267,30 @@ namespace MTApiService
using (softwareRgKey)
{
//app name
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
if (appRegKey == null)
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey != null)
{
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
}
using (appRegKey)
{
//ConnectionProfiles key
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey == null)
using (appRegKey)
{
profilesRegKey = appRegKey.CreateSubKey(PROFILES_REGKEY);
}
//ConnectionProfiles key
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true) ??
appRegKey.CreateSubKey(ProfilesRegkey);
using (profilesRegKey)
{
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
using (profileKey)
if (profilesRegKey != null)
{
profileKey.SetValue(HOST_REGVALUE_NAME, profile.Host);
profileKey.SetValue(PORT_REGVALUE_NAME, profile.Port);
using (profilesRegKey)
{
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
if (profileKey != null)
{
using (profileKey)
{
profileKey.SetValue(HostRegvalueName, profile.Host);
profileKey.SetValue(PortRegvalueName, profile.Port);
}
}
}
}
}
}
@@ -293,19 +299,19 @@ namespace MTApiService
private static void DeleteConnectionProfileFromRegistry(string profileName)
{
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey == null)
return;
using (softwareRegKey)
{
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey == null)
return;
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey == null)
return;
+118 -3
View File
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Collections;
using System.Globalization;
namespace MTApiService
{
@@ -13,7 +12,8 @@ namespace MTApiService
{
static IEnumerable<Type> GetKnownTypes()
{
return new Type[] { typeof(MtResponseInt), typeof(MtResponseDouble),
return new Type[] { typeof(MtResponseObject),
typeof(MtResponseInt), typeof(MtResponseDouble),
typeof(MtResponseString), typeof(MtResponseBool),
typeof(MtResponseLong), typeof(MtResponseULong),
typeof(MtResponseDoubleArray), typeof(MtResponseIntArray),
@@ -21,6 +21,30 @@ namespace MTApiService
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
typeof(MtResponseMqlBookInfoArray)};
}
public abstract object GetValue();
[DataMember]
public int ErrorCode { get; set; }
}
[DataContract]
public class MtResponseObject : MtResponse
{
public MtResponseObject(object value)
{
Value = value;
}
[DataMember]
public object Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value?.ToString() ?? string.Empty;
}
}
[DataContract]
@@ -33,6 +57,13 @@ namespace MTApiService
[DataMember]
public int Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -45,6 +76,13 @@ namespace MTApiService
[DataMember]
public long Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -57,6 +95,13 @@ namespace MTApiService
[DataMember]
public ulong Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -69,6 +114,13 @@ namespace MTApiService
[DataMember]
public double Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString(CultureInfo.CurrentCulture);
}
}
[DataContract]
@@ -81,6 +133,13 @@ namespace MTApiService
[DataMember]
public string Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value;
}
}
[DataContract]
@@ -93,6 +152,13 @@ namespace MTApiService
[DataMember]
public bool Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -105,6 +171,13 @@ namespace MTApiService
[DataMember]
public double[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -117,6 +190,13 @@ namespace MTApiService
[DataMember]
public int[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -129,6 +209,13 @@ namespace MTApiService
[DataMember]
public long[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -141,6 +228,13 @@ namespace MTApiService
[DataMember]
public ArrayList Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -153,6 +247,13 @@ namespace MTApiService
[DataMember]
public MtMqlRates[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -165,6 +266,13 @@ namespace MTApiService
[DataMember]
public MtMqlTick Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -177,6 +285,13 @@ namespace MTApiService
[DataMember]
public MtMqlBookInfo[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
}
+209 -110
View File
@@ -3,17 +3,26 @@ using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Net;
using System.Diagnostics;
using System.ServiceModel.Channels;
using System.Net.Sockets;
using log4net;
namespace MTApiService
{
internal class MtServer : IDisposable, IMtApiServer
{
#region Constants
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec
private const int STOP_EXPERT_INTERVAL = 1000; // 1 sec
private const int WaitResponseTime = 40000; // 40 sec
private const int StopExpertInterval = 1000; // 1 sec
#endregion
#region Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServer));
private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtExecutorManager _executorManager = new MtExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion
#region ctor
@@ -25,99 +34,126 @@ namespace MTApiService
#endregion
#region Properties
public int Port { get; private set; }
public int Port { get; }
#endregion
#region Public Methods
public void Start()
{
Log.Debug("Start: begin");
var hostsInitialized = InitHosts(Port);
if (hostsInitialized == false)
{
Debug.WriteLine("Start: InitHosts failed. ");
}
Log.DebugFormat("Start: end. hostsInitialized = {0}", hostsInitialized);
}
private bool InitHosts(int port)
{
Log.DebugFormat("InitHosts: begin. port = {0}", port);
int count;
lock (_hosts)
{
if (_hosts.Count > 0)
{
Log.Info("InitHosts: end. Host's has been initialized");
return false;
}
//init local pipe host
string localUrl = CreateConnectionAddress(null, port, true);
ServiceHost localServiceHost = CreateServiceHost(localUrl, true);
var localUrl = CreateConnectionAddress(null, port, true);
var localServiceHost = CreateServiceHost(localUrl, true);
if (localServiceHost != null)
{
_hosts.Add(localServiceHost);
}
//init network hosts
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
if (ips != null)
var dnsHostName = Dns.GetHostName();
var ips = Dns.GetHostEntry(dnsHostName);
if (ips == null)
{
foreach (IPAddress ipAddress in ips.AddressList)
Log.WarnFormat("InitHosts: end. Dns.GetHostEntry has returned null for DNS Host Name {0}", dnsHostName);
return false;
}
foreach (var ipAddress in ips.AddressList)
{
if (ipAddress?.AddressFamily == AddressFamily.InterNetwork)
{
if (ipAddress != null)
var ip = ipAddress.ToString();
var networkUrl = CreateConnectionAddress(ip, port, false);
var serviceHost = CreateServiceHost(networkUrl, false);
if (serviceHost != null)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
string ip = ipAddress.ToString();
string networkUrl = CreateConnectionAddress(ip, port, false);
ServiceHost serviceHost = CreateServiceHost(networkUrl, false);
if (serviceHost != null)
{
_hosts.Add(serviceHost);
}
}
_hosts.Add(serviceHost);
}
}
}
count = _hosts.Count;
}
Log.DebugFormat("InitHosts: end. Host's count = {0}", count);
return true;
}
private ServiceHost CreateServiceHost(string serverUrlAdress, bool local)
{
ServiceHost serviceHost = null;
if (serverUrlAdress != null)
{
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
Log.DebugFormat("CreateServiceHost: begin. serverUrlAdress = {0}; local = {1}", serverUrlAdress, local);
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
serviceHost.Open();
}
catch(Exception e)
{
Debug.WriteLine("CreateServiceHost: Create ServiceHost failed. " + e.Message);
}
if (serverUrlAdress == null)
{
Log.Warn("CreateServiceHost: end. serverUrlAdress is not defined");
return null;
}
ServiceHost serviceHost;
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
serviceHost.Open();
}
catch(Exception e)
{
Log.ErrorFormat("CreateServiceHost: Error! {0}", e.Message);
serviceHost = null;
}
Log.Debug("CreateServiceHost: end.");
return serviceHost;
}
public void AddExpert(MtExpert expert)
{
if (expert != null)
Log.DebugFormat("AddExpert: begin. expert {0}", expert);
if (expert == null)
{
expert.Deinited += expert_Deinited;
expert.QuoteChanged += expert_QuoteChanged;
expert.OnMtEvent += Expert_OnMtEvent;
lock (_experts)
{
_experts.Add(expert);
}
_executorManager.AddCommandExecutor(expert);
_service.OnQuoteAdded(expert.Quote);
Log.Warn("AddExpert: end. expert is not defined");
return;
}
expert.Deinited += expert_Deinited;
expert.QuoteChanged += expert_QuoteChanged;
expert.OnMtEvent += Expert_OnMtEvent;
lock (_experts)
{
_experts.Add(expert);
}
_executorManager.AddExecutor(expert);
_service.OnQuoteAdded(expert.Quote);
Log.Debug("AddExpert: end.");
}
#endregion
@@ -126,25 +162,39 @@ namespace MTApiService
public MtResponse SendCommand(MtCommand command)
{
MtResponse response = null;
Log.DebugFormat("SendCommand: begin. command {0}", command);
if (command != null)
if (command == null)
{
var task = new MtCommandTask(command);
_executorManager.EnqueueCommandTask(task);
//wait for execute command in MetaTrader
response = task.WaitResult(WAIT_RESPONSE_TIME);
Log.Warn("SendCommand: end. command is not defined");
return null;
}
var task = _executorManager.SendCommand(command);
//wait for execute command in MetaTrader
MtResponse response = null;
try
{
response = task.WaitResult(WaitResponseTime);
}
catch (Exception ex)
{
Log.WarnFormat("SendCommand: Exception - {0}", ex.Message);
}
Log.DebugFormat("SendCommand: end. response = {0}", response);
return response;
}
public IEnumerable<MtQuote> GetQuotes()
public List<MtQuote> GetQuotes()
{
Log.Debug("GetQuotes: called");
lock (_experts)
{
return (from s in _experts select s.Quote);
return _experts.Select(s => s.Quote).ToList();
}
}
@@ -153,99 +203,131 @@ namespace MTApiService
#region Private Methods
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var expertsCount = 0;
Log.DebugFormat("stopTimer_Elapsed: begin");
int expertsCount;
lock (_experts)
{
expertsCount = _experts.Count();
expertsCount = _experts.Count;
}
if (expertsCount == 0)
{
_service.OnStopServer();
Log.DebugFormat("stopTimer_Elapsed: experts count is 0. Call Stop().");
Stop();
}
var stopTimer = sender as System.Timers.Timer;
if (stopTimer != null)
{
stopTimer.Stop();
stopTimer.Elapsed -= stopTimer_Elapsed;
}
if (stopTimer == null) return;
stopTimer.Stop();
stopTimer.Elapsed -= stopTimer_Elapsed;
Log.DebugFormat("stopTimer_Elapsed: end");
}
private string CreateConnectionAddress(string host, int port, bool local)
private static string CreateConnectionAddress(string host, int port, bool local)
{
Log.DebugFormat("CreateConnectionAddress: begin. host = {0}, port = {1}, local = {2}", host, port, local);
string connectionAddress = null;
if (local == true)
if (local)
{
//by Pipe
connectionAddress = "net.pipe://localhost/MtApiService_" + port.ToString();
connectionAddress = "net.pipe://localhost/MtApiService_" + port;
}
else
{
//by Socket
if (host != null)
{
connectionAddress = "net.tcp://" + host.ToString() + ":" + port.ToString() + "/MtApiService";
}
connectionAddress = "net.tcp://" + host + ":" + port + "/MtApiService";
}
}
Log.DebugFormat("CreateConnectionAddress: end. connectionAddress = {0}", connectionAddress);
return connectionAddress;
}
private static Binding CreateConnectionBinding(bool local)
{
Binding connectionBinding = null;
Log.DebugFormat("CreateConnectionBinding: begin. local = {0}", local);
if (local == true)
Binding connectionBinding;
if (local)
{
//by Pipe
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
bind.MaxReceivedMessageSize = 2147483647;
bind.MaxBufferSize = 2147483647;
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = new TimeSpan(12, 0, 0),
ReceiveTimeout = new TimeSpan(12, 0, 0),
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
bind.MaxBufferPoolSize = 2147483647;
bind.ReaderQuotas.MaxArrayLength = 2147483647;
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
bind.ReaderQuotas.MaxDepth = 2147483647;
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
connectionBinding = bind;
}
else
{
//by Socket
var bind = new NetTcpBinding(SecurityMode.None);
bind.MaxReceivedMessageSize = 2147483647;
bind.MaxBufferSize = 2147483647;
var bind = new NetTcpBinding(SecurityMode.None)
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = new TimeSpan(12, 0, 0),
ReceiveTimeout = new TimeSpan(12, 0, 0),
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
bind.MaxBufferPoolSize = 2147483647;
bind.ReaderQuotas.MaxArrayLength = 2147483647;
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
bind.ReaderQuotas.MaxDepth = 2147483647;
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
connectionBinding = bind;
}
Log.Debug("CreateConnectionBinding: end.");
return connectionBinding;
}
private void Stop()
{
Log.Debug("Stop: begin.");
_executorManager.Stop();
lock (_hosts)
{
if (_hosts.Count == 0)
{
Log.Debug("Stop: end. Host count is 0.");
return;
}
try
{
@@ -254,15 +336,18 @@ namespace MTApiService
host.Close();
}
}
catch (TimeoutException)
catch (TimeoutException ex)
{
Log.ErrorFormat("Stop: TimeoutException - {0}", ex.Message);
foreach (var host in _hosts)
{
host.Abort();
}
}
catch (Exception)
catch (Exception ex)
{
Log.ErrorFormat("Stop: Exception - {0}", ex.Message);
// ignored
}
finally
@@ -272,23 +357,30 @@ namespace MTApiService
}
FireOnStopped();
Log.Debug("Stop: end.");
}
private void expert_Deinited(object sender, EventArgs e)
{
if (sender == null)
return;
Log.Debug("expert_Deinited: begin.");
var expert = (MtExpert)sender;
var expertsCount = 0;
var expert = sender as MtExpert;
if (expert == null)
{
Log.Warn("expert_Deinited: end. Expert is not defined.");
return;
}
int expertsCount;
lock (_experts)
{
_experts.Remove(expert);
expertsCount = _experts.Count();
expertsCount = _experts.Count;
}
_executorManager.RemoveCommandExecutor(expert);
_executorManager.RemoveExecutor(expert);
expert.Deinited -= expert_Deinited;
expert.QuoteChanged -= expert_QuoteChanged;
@@ -299,19 +391,29 @@ namespace MTApiService
{
var stopTimer = new System.Timers.Timer();
stopTimer.Elapsed += stopTimer_Elapsed;
stopTimer.Interval = STOP_EXPERT_INTERVAL;
stopTimer.Interval = StopExpertInterval;
stopTimer.Start();
}
Log.Debug("expert_Deinited: end.");
}
private void expert_QuoteChanged(MtExpert expert, MtQuote quote)
{
Log.DebugFormat("expert_QuoteChanged: begin. expert = {0}, quote = {1}", expert, quote);
_service.QuoteUpdate(quote);
Log.Debug("expert_QuoteChanged: end.");
}
private void Expert_OnMtEvent(object sender, MtEventArgs e)
private void Expert_OnMtEvent(MtExpert expert, MtEvent e)
{
_service.OnMtEvent(e.Event);
Log.DebugFormat("Expert_OnMtEvent: begin. expert = {0}, event = {1}", expert, e);
_service.OnMtEvent(e);
Log.Debug("Expert_OnMtEvent: end.");
}
private void FireOnStopped()
@@ -328,16 +430,13 @@ namespace MTApiService
#region IDispose
public void Dispose()
{
Log.Debug("Dispose: begin");
Stop();
Log.Debug("Dispose: end.");
}
#endregion
#region Fields
private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion
}
}
-190
View File
@@ -1,190 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Net;
using System.Diagnostics;
namespace MTApiService
{
public class MtServerInstance
{
#region Init_Instance
static readonly MtServerInstance mInstance = new MtServerInstance();
private MtServerInstance()
{
}
static MtServerInstance()
{
}
public static MtServerInstance GetInstance()
{
return mInstance;
}
#endregion
#region Public Methods
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
{
Debug.WriteLine("MtApiServerInstance::InitExpert: symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
MtServer server = null;
lock (mServersDictionary)
{
if (mServersDictionary.ContainsKey(port))
{
server = mServersDictionary[port];
}
else
{
server = new MtServer(port);
server.Stopped += new EventHandler(server_Stopped);
mServersDictionary[port] = server;
server.Start();
}
}
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
lock (mExpertsDictionary)
{
mExpertsDictionary[expert.Handle] = expert;
}
server.AddExpert(expert);
}
public void DeinitExpert(int expertHandle)
{
Debug.WriteLine("MtApiServerInstance::DeinitExpert: expertHandle = {0}", expertHandle);
MtExpert expert = null;
lock (mExpertsDictionary)
{
if (mExpertsDictionary.ContainsKey(expertHandle) == true)
{
expert = mExpertsDictionary[expertHandle];
mExpertsDictionary.Remove(expertHandle);
}
}
if (expert != null)
{
expert.Deinit();
}
}
public void SendQuote(int expertHandle, string symbol, double bid, double ask)
{
Debug.WriteLine("MtApiServerInstance::SendQuote: enter. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.Quote = new MtQuote(symbol, bid, ask);
}
Debug.WriteLine("MtApiServerInstance::SendQuote: finish.");
}
public void SendEvent(int expertHandle, int eventType, string payload)
{
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.SendEvent(new MtEvent(eventType, payload));
}
Debug.WriteLine("MtApiServerInstance::SendEvent: finished");
}
public void SendResponse(int expertHandle, MtResponse response)
{
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.SendResponse(response);
}
Debug.WriteLine("MtApiServerInstance::SendResponse: finish");
}
public int GetCommandType(int expertHandle)
{
Debug.WriteLine("MtApiServerInstance::GetCommandType: expertHandle = {0}", expertHandle);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
return (expert != null) ? expert.GetCommandType() : 0;
}
public object GetCommandParameter(int expertHandle, int index)
{
Debug.WriteLine("MtApiServerInstance::GetCommandParameter: expertHandle = {0}, index = {1}", expertHandle, index);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
return (expert != null) ? expert.GetCommandParameter(index) : null;
}
#endregion
#region Private Methods
private void server_Stopped(object sender, EventArgs e)
{
MtServer server = (MtServer)sender;
server.Stopped -= server_Stopped;
var port = server.Port;
lock (mServersDictionary)
{
if (mServersDictionary.ContainsKey(port))
{
mServersDictionary.Remove(port);
}
}
}
#endregion
#region Fields
private readonly MtRegistryManager mConnectionManager = new MtRegistryManager();
private readonly Dictionary<int, MtServer> mServersDictionary = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> mExpertsDictionary = new Dictionary<int, MtExpert>();
#endregion
}
}
+98 -47
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;
using log4net;
namespace MTApiService
{
@@ -18,7 +19,7 @@ namespace MTApiService
MtResponse SendCommand(MtCommand command);
[OperationContract]
IEnumerable<MtQuote> GetQuotes();
List<MtQuote> GetQuotes();
}
[ServiceContract]
@@ -46,107 +47,149 @@ namespace MTApiService
InstanceContextMode = InstanceContextMode.Single)]
public sealed class MtService : IMtApi
{
private static readonly ILog Log = LogManager.GetLogger(typeof(MtService));
public MtService(IMtApiServer serverCallback)
{
if (serverCallback == null)
throw new ArgumentNullException("serverCallback");
throw new ArgumentNullException(nameof(serverCallback));
mServer = serverCallback;
_server = serverCallback;
}
#region IMtApi
public bool Connect()
{
bool connected = false;
Log.Debug("Connect: begin");
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
if (callback != null)
if (callback == null)
{
Log.Warn("Connect: end. Callback is not defined.");
return false;
}
var connected = false;
try
{
_clientsLocker.AcquireWriterLock(10000);
try
{
mClientsLocker.AcquireWriterLock(10000);
if (_clientCallbacks.Contains(callback) == false)
_clientCallbacks.Add(callback);
try
{
if (mClientCallbacks.Contains(callback) == false)
mClientCallbacks.Add(callback);
connected = true;
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
connected = true;
}
catch (ApplicationException)
finally
{
_clientsLocker.ReleaseWriterLock();
}
}
catch (ApplicationException ex)
{
Log.ErrorFormat("Connect: ApplicationException - {0}", ex.Message);
}
Log.DebugFormat("Connect: end. connected = {0}", connected);
return connected;
}
public void Disconnect()
{
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
Log.Debug("Disconnect: begin");
if (callback != null)
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
if (callback == null)
{
Log.Warn("Disconnect: end. Callback is not definded.");
return;
}
try
{
_clientsLocker.AcquireWriterLock(10000);
try
{
mClientsLocker.AcquireWriterLock(10000);
try
{
mClientCallbacks.Remove(callback);
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
_clientCallbacks.Remove(callback);
}
catch (ApplicationException)
finally
{
_clientsLocker.ReleaseWriterLock();
}
}
catch (ApplicationException ex)
{
Log.ErrorFormat("Disconnect: ApplicationException - {0}", ex.Message);
}
Log.Debug("Disconnect: end.");
}
public MtResponse SendCommand(MtCommand command)
{
return mServer.SendCommand(command);
Log.DebugFormat("SendCommand: called. command = {0}", command);
return _server.SendCommand(command);
}
public IEnumerable<MtQuote> GetQuotes()
public List<MtQuote> GetQuotes()
{
return mServer.GetQuotes();
Log.Debug("GetQuotes: called.");
return _server.GetQuotes();
}
#endregion
#region Public Methods
public void OnStopServer()
{
Log.Debug("OnStopServer: begin.");
ExecuteCallbackAction(a => a.OnServerStopped());
Log.Debug("OnStopServer: end.");
}
public void QuoteUpdate(MtQuote quote)
{
Log.DebugFormat("QuoteUpdate: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
Log.Debug("QuoteUpdate: end.");
}
public void OnQuoteAdded(MtQuote quote)
{
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
Log.Debug("OnQuoteAdded: end.");
}
public void OnQuoteRemoved(MtQuote quote)
{
Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
Log.Debug("OnQuoteRemoved: end.");
}
public void OnMtEvent(MtEvent mtEvent)
public void OnMtEvent(MtEvent e)
{
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
Log.DebugFormat("OnMtEvent: begin.quote = {0}", e);
ExecuteCallbackAction(a => a.OnMtEvent(e));
Log.Debug("OnMtEvent: end.");
}
#endregion
@@ -154,22 +197,26 @@ namespace MTApiService
private void ExecuteCallbackAction(Action<IMtApiCallback> action)
{
Log.Debug("ExecuteCallbackAction: begin.");
try
{
mClientsLocker.AcquireReaderLock(2000);
_clientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientCallbacks = null;
try
{
foreach (var callback in mClientCallbacks)
foreach (var callback in _clientCallbacks)
{
try
{
action(callback);
}
catch (Exception)
catch (Exception ex)
{
Log.ErrorFormat("ExecuteCallbackAction: Exception - {0}", ex.Message);
if (crashedClientCallbacks == null)
crashedClientCallbacks = new List<IMtApiCallback>();
@@ -179,29 +226,33 @@ namespace MTApiService
if (crashedClientCallbacks != null)
{
Log.WarnFormat("ExecuteCallbackAction: crashed callback count = {0}", crashedClientCallbacks.Count);
foreach (var crashedCallback in crashedClientCallbacks)
{
mClientCallbacks.Remove(crashedCallback);
_clientCallbacks.Remove(crashedCallback);
}
}
}
finally
{
mClientsLocker.ReleaseReaderLock();
_clientsLocker.ReleaseReaderLock();
}
}
catch (ApplicationException)
catch (ApplicationException ex)
{
//TODO: add logging
Log.ErrorFormat("ExecuteCallbackAction: ApplicationException - {0}", ex.Message);
}
Log.Debug("ExecuteCallbackAction: end.");
}
#endregion
#region Fields
private readonly IMtApiServer mServer;
private readonly List<IMtApiCallback> mClientCallbacks = new List<IMtApiCallback>();
private readonly ReaderWriterLock mClientsLocker = new ReaderWriterLock();
private readonly IMtApiServer _server;
private readonly List<IMtApiCallback> _clientCallbacks = new List<IMtApiCallback>();
private readonly ReaderWriterLock _clientsLocker = new ReaderWriterLock();
#endregion
}
}
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.21.0")]
[assembly: AssemblyFileVersion("1.0.21.0")]
[assembly: AssemblyVersion("1.0.25.0")]
[assembly: AssemblyFileVersion("1.0.25.0")]
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="2.13.0307" targetFramework="net40" />
<package id="log4net" version="2.0.5" targetFramework="net40" />
<package id="MSBuild.ILMerge.Task" version="1.0.5" targetFramework="net40" />
</packages>
-2
View File
@@ -11,13 +11,11 @@ ref class MT4Handler: IMetaTraderHandler
public:
MT4Handler()
{
//msgId = RegisterWindowMessage("MetaTrader4_Internal_Message");
msgId = WM_TIMER;
}
virtual void SendTickToMetaTrader(int handle)
{
//PostMessage((HWND)handle, msgId, 2, 1);
PostMessage((HWND)handle, msgId, 0, 0);
}
+203 -194
View File
@@ -4,7 +4,8 @@
#include "MT4Handler.h"
#include "Windows.h"
#include < vcclr.h >
#include <vcclr.h>
#include <functional>
using namespace System;
using namespace MTApiService;
@@ -17,242 +18,250 @@ using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Diagnostics;
#define _DLLAPI extern "C" __declspec(dllexport)
void convertSystemString(wchar_t* dest, String^ src)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
}
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MT4Handler^ mtHandler = gcnew MT4Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:initExpert(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateQuote(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
template <typename T> T Execute(std::function<T()> func, wchar_t* err, T default_value)
{
T result = default_value;
try
{
MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
result = func();
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateTimeBar(): " + e->Message);
return 0;
}
return 1;
return result;
}
int _stdcall sendIntResponse(int expertHandle, int response)
_DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &port, symbol, &bid, &ask]() {
MT4Handler^ mtHandler = gcnew MT4Handler();
MtAdapter::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
return true;
}, err, false);
}
int _stdcall sendBooleanResponse(int expertHandle, int response)
_DLLAPI bool _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle]() {
MtAdapter::GetInstance()->DeinitExpert(expertHandle);
return true;
}, err, false);
}
int _stdcall sendDoubleResponse(int expertHandle, double response)
_DLLAPI bool _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, symbol, &bid, &ask]() {
MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
return true;
}, err, false);
}
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &eventType, payload]() {
MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
return true;
}, err, false);
}
int _stdcall sendVoidResponse(int expertHandle)
_DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
return true;
}, err, false);
}
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
_DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, wchar_t* err)
{
try
{
array<double>^ list = gcnew array<double>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
return true;
}, err, false);
}
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
_DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, wchar_t* err)
{
try
{
array<int>^ list = gcnew array<int>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
return true;
}, err, false);
}
int _stdcall getCommandType(int expertHandle, int* res)
_DLLAPI bool _stdcall sendStringResponse(int expertHandle, wchar_t* response, wchar_t* err)
{
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
return true;
}, err, false);
}
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
_DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, wchar_t* err)
{
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getIntValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &code, message]() {
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
res->ErrorCode = code;
MtAdapter::GetInstance()->SendResponse(expertHandle, res);
return true;
}, err, false);
}
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
_DLLAPI bool _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
{
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
return true;
}, err, false);
}
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
_DLLAPI bool _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size, wchar_t* err)
{
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, values, &size]() {
array<double>^ list = gcnew array<double>(size);
for (int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
return true;
}, err, false);
}
_DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int size, wchar_t* err)
{
return Execute<bool>([&expertHandle, values, &size]() {
array<int>^ list = gcnew array<int>(size);
for (int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
return true;
}, err, false);
}
_DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
{
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
return true;
}, err, false);
}
_DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, res]() {
*res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getIntValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
// --- index parameters
_DLLAPI bool _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
return true;
}, err, false);
}
_DLLAPI bool _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (__int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
// --- named parameters
_DLLAPI bool _stdcall containsNamedValue(int expertHandle, wchar_t* paramName)
{
wchar_t err[1000];
return Execute<bool>([&expertHandle, paramName]() {
return MtAdapter::GetInstance()->ContainsNamedParameter(expertHandle, gcnew String(paramName));
}, err, false);
}
_DLLAPI bool _stdcall getNamedIntValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (int)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedDoubleValue(int expertHandle, wchar_t* paramName, double* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (double)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedStringValue(int expertHandle, wchar_t* paramName, wchar_t* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
convertSystemString(res, (String^)obj);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedBooleanValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (bool)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedLongValue(int expertHandle, wchar_t* paramName, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
if (obj != nullptr)
*res = (__int64)obj;
return true;
}, err, false);
}
-17
View File
@@ -1,17 +0,0 @@
LIBRARY MTConnector
EXPORTS initExpert
deinitExpert
updateQuote
sendEvent
sendIntResponse
sendBooleanResponse
sendDoubleResponse
sendStringResponse
sendVoidResponse
sendDoubleArrayResponse
sendIntArrayResponse
getCommandType
getIntValue
getDoubleValue
getStringValue
-5
View File
@@ -96,7 +96,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -109,7 +108,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -121,7 +119,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -133,7 +130,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -154,7 +150,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="MTConnector.def" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
-3
View File
@@ -44,9 +44,6 @@
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="MTConnector.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
+37 -1
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApiClientUI", "TestClients\TestApiClientUI\TestApiClientUI.csproj", "{663CC515-EAAE-47D4-8933-5008C2DA1160}"
EndProject
@@ -37,6 +37,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MtApiSetupActions", "MtApiS
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestClients", "TestClients", "{B91FF338-E05D-4EF1-948B-A2376DB37ECA}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApi5Bootstrapper", "MtApi5Bootstrapper\MtApi5Bootstrapper.wixproj", "{1497E285-C228-490B-9638-565E118548FB}"
ProjectSection(ProjectDependencies) = postProject
{A9ED070F-AB4D-4380-9DDE-5D931AC71333} = {A9ED070F-AB4D-4380-9DDE-5D931AC71333}
EndProjectSection
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApiBootstrapper", "MtApiBootstrapper\MtApiBootstrapper.wixproj", "{8E63046B-56E5-4623-8808-558AD72A8F2B}"
ProjectSection(ProjectDependencies) = postProject
{78B94552-DB17-40EC-B7C6-23D32DB85DC1} = {78B94552-DB17-40EC-B7C6-23D32DB85DC1}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -196,6 +206,32 @@ Global
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x64.ActiveCfg = Release|x86
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.ActiveCfg = Release|x86
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.Build.0 = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Any CPU.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.Build.0 = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.ActiveCfg = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Build.0 = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Deploy.0 = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.Build.0 = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Any CPU.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.Build.0 = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|x64.ActiveCfg = Release|x64
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.Build.0 = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Any CPU.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.Build.0 = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x64.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.Build.0 = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Any CPU.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.Build.0 = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x64.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi
{
enum EnumColorFormat
{
COLOR_FORMAT_XRGB_NOALPHA = 0, //The component of the alpha channel is ignored
COLOR_FORMAT_ARGB_RAW = 1, //Color components are not handled by the terminal (must be correctly set by the user)
COLOR_FORMAT_ARGB_NORMALIZE = 2 //Color components are handled by the terminal
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
public enum EnumObject
{
OBJ_VLINE = 0, //Vertical Line
OBJ_HLINE = 1, //Horizontal Line
OBJ_TREND = 2, //Trend Line
BJ_TRENDBYANGLE = 3, //Trend Line By Angle
OBJ_CYCLES = 20, //Cycle Lines
OBJ_CHANNEL = 5, //Equidistant Channel
OBJ_STDDEVCHANNEL = 6, //Standard Deviation Channel
OBJ_REGRESSION = 4, //Linear Regression Channel
OBJ_PITCHFORK = 19, //Andrews’ Pitchfork
OBJ_GANNLINE = 7, //Gann Line
OBJ_GANNFAN = 8, //Gann Fan
OBJ_GANNGRID = 9, //Gann Grid
OBJ_FIBO = 10, //Fibonacci Retracement
OBJ_FIBOTIMES = 11, //Fibonacci Time Zones
OBJ_FIBOFAN = 12, //Fibonacci Fan
OBJ_FIBOARC = 13, //Fibonacci Arcs
OBJ_FIBOCHANNEL = 15, //Fibonacci Channel
OBJ_EXPANSION = 14, //Fibonacci Expansion
OBJ_RECTANGLE = 16, //Rectangle
OBJ_TRIANGLE = 17, //Triangle
OBJ_ELLIPSE = 18, //Ellipse
OBJ_ARROW_THUMB_UP = 29, //Thumbs Up
OBJ_ARROW_THUMB_DOWN = 30, //Thumbs Down
OBJ_ARROW_UP = 31, //Arrow Up
OBJ_ARROW_DOWN = 32, //Arrow Down
OBJ_ARROW_STOP = 33, //Stop Sign
OBJ_ARROW_CHECK = 34, //Check Sign
OBJ_ARROW_LEFT_PRICE = 35, //Left Price Label
OBJ_ARROW_RIGHT_PRICE = 36, //Right Price Label
OBJ_ARROW_BUY = 37, //Buy Sign
OBJ_ARROW_SELL = 38, //Sell Sign
OBJ_ARROW = 22, //Arrow
OBJ_TEXT = 21, //Text
OBJ_LABEL = 23, //Label
OBJ_BUTTON = 25, //Button
OBJ_BITMAP = 26, //Bitmap
OBJ_BITMAP_LABEL = 24, //Bitmap Label
OBJ_EDIT = 27, //Edit
OBJ_EVENT = 42, //The "Event" object corresponding to an event in the economic calendar
OBJ_RECTANGLE_LABEL = 28 //The "Rectangle label" object for creating and designing the custom graphical interface.
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi
{
public enum EnumObjectPropertyDouble
{
OBJPROP_PRICE = 20, // Price coordinate
OBJPROP_LEVELVALUE = 204, // Level value
OBJPROP_SCALE = 12, // Scale (properties of Gann objects, Fibonacci Arcs and Ellipse)
OBJPROP_ANGLE = 13, // Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE
OBJPROP_DEVIATION = 16, // Deviation for the Standard Deviation Channel
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace MtApi
{
public enum EnumObjectPropertyInteger
{
OBJPROP_COLOR = 6,
OBJPROP_STYLE = 7,
OBJPROP_WIDTH = 8,
OBJPROP_BACK = 9,
OBJPROP_ZORDER = 207,
OBJPROP_HIDDEN = 208,
OBJPROP_SELECTED = 17,
OBJPROP_READONLY = 1028,
OBJPROP_TYPE = 18,
OBJPROP_TIME = 19,
OBJPROP_SELECTABLE = 1000,
OBJPROP_CREATETIME = 998,
OBJPROP_LEVELS = 200,
OBJPROP_LEVELCOLOR = 201,
OBJPROP_LEVELSTYLE = 202,
OBJPROP_LEVELWIDTH = 203,
OBJPROP_ALIGN = 1036,
OBJPROP_FONTSIZE = 100,
OBJPROP_RAY_RIGHT = 1004,
OBJPROP_ELLIPSE = 11,
OBJPROP_ARROWCODE = 14,
OBJPROP_TIMEFRAMES = 15,
OBJPROP_ANCHOR = 1011,
OBJPROP_XDISTANCE = 102,
OBJPROP_YDISTANCE = 103,
OBJPROP_STATE = 1018,
OBJPROP_XSIZE = 1019,
OBJPROP_YSIZE = 1020,
OBJPROP_XOFFSET = 1033,
OBJPROP_YOFFSET = 1034,
OBJPROP_BGCOLOR = 1025,
OBJPROP_CORNER = 101,
OBJPROP_BORDER_TYPE = 1029,
OBJPROP_BORDER_COLOR = 1035
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace MtApi
{
public enum EnumObjectPropertyString
{
OBJPROP_NAME = 1037,
OBJPROP_TEXT = 999,
OBJPROP_TOOLTIP = 206,
OBJPROP_LEVELTEXT = 205,
OBJPROP_FONT = 1001,
OBJPROP_BMPFILE = 1017,
OBJPROP_SYMBOL = 1021
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace MtApi
{
public enum EnumSeriesInfoInteger
{
SERIES_BARS_COUNT = 0,
SERIES_FIRSTDATE = 1,
SERIES_LASTBAR_DATE = 5,
SERIES_SERVER_FIRSTDATE = 2
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/marketinfoconstants#enum_symbol_info_double
public enum EnumSymbolInfoDouble
{
SYMBOL_BID = 1, // Bid - best sell offer
SYMBOL_BIDHIGH = 2, // Not supported
SYMBOL_BIDLOW = 3, // Not supported
SYMBOL_ASK = 4, // Ask - best buy offer
SYMBOL_ASKHIGH = 5, // Not supported
SYMBOL_ASKLOW = 6, // Not supported
SYMBOL_LAST = 7, // Not supported
SYMBOL_LASTHIGH = 8, // Not supported
SYMBOL_LASTLOW = 9, // Not supported
SYMBOL_POINT = 16, // Symbol point value
SYMBOL_TRADE_TICK_VALUE = 26, // Value of SYMBOL_TRADE_TICK_VALUE_PROFIT
SYMBOL_TRADE_TICK_VALUE_PROFIT = 53, // Not supported
SYMBOL_TRADE_TICK_VALUE_LOSS = 54, // Not supported
SYMBOL_TRADE_TICK_SIZE = 27, // Minimal price change
SYMBOL_TRADE_CONTRACT_SIZE = 28, // Trade contract size
SYMBOL_VOLUME_MIN = 34, // Minimal volume for a deal
SYMBOL_VOLUME_MAX = 35, // Maximal volume for a deal
SYMBOL_VOLUME_STEP = 36, // Minimal volume change step for deal execution
SYMBOL_VOLUME_LIMIT = 55, // Not supported
SYMBOL_SWAP_LONG = 38, // Buy order swap value
SYMBOL_SWAP_SHORT = 39, // Sell order swap value
SYMBOL_MARGIN_INITIAL = 42, // Initial margin means the amount in the margin currency required for opening an order with the volume of one lot. It is used for checking a client's assets when he or she enters the market.
SYMBOL_MARGIN_MAINTENANCE = 43, // The maintenance margin. If it is set, it sets the margin amount in the margin currency of the symbol, charged from one lot. It is used for checking a client's assets when his/her account state changes. If the maintenance margin is equal to 0, the initial margin is used.
SYMBOL_MARGIN_LONG = 44, // Not supported
SYMBOL_MARGIN_SHORT = 45, // Not supported
SYMBOL_MARGIN_LIMIT = 46, // Not supported
SYMBOL_MARGIN_STOP = 47, // Not supported
SYMBOL_MARGIN_STOPLIMIT = 48, // Not supported
SYMBOL_SESSION_VOLUME = 57, // Not supported
SYMBOL_SESSION_TURNOVER = 58, // Not supported
SYMBOL_SESSION_INTEREST = 59, // Not supported
SYMBOL_SESSION_BUY_ORDERS_VOLUME = 61, // Not supported
SYMBOL_SESSION_SELL_ORDERS_VOLUME = 63, // Not supported
SYMBOL_SESSION_OPEN = 64, // Not supported
SYMBOL_SESSION_CLOSE = 65, // Not supported
SYMBOL_SESSION_AW = 66, // Not supported
SYMBOL_SESSION_PRICE_SETTLEMENT = 67, // Not supported
SYMBOL_SESSION_PRICE_LIMIT_MIN = 68, // Not supported
SYMBOL_SESSION_PRICE_LIMIT_MAX = 69, // Not supported
}
}
+31
View File
@@ -0,0 +1,31 @@
namespace MtApi
{
//MQL4: ENUM_SYMBOL_INFO_INTEGER
public enum EnumSymbolInfoInteger
{
SYMBOL_SELECT = 0,
SYMBOL_VISIBLE = 76,
SYMBOL_SESSION_DEALS = 56,
SYMBOL_SESSION_BUY_ORDERS = 60,
SYMBOL_SESSION_SELL_ORDERS = 62,
SYMBOL_VOLUME = 10,
SYMBOL_VOLUMEHIGH = 11,
SYMBOL_VOLUMELOW = 12,
SYMBOL_TIME = 15,
SYMBOL_DIGITS = 17,
SYMBOL_SPREAD = 18,
SYMBOL_SPREAD_FLOAT = 41,
SYMBOL_TRADE_CALC_MODE = 29,
SYMBOL_TRADE_MODE = 30,
SYMBOL_START_TIME = 51,
SYMBOL_EXPIRATION_TIME = 52,
SYMBOL_TRADE_STOPS_LEVEL = 31,
SYMBOL_TRADE_FREEZE_LEVEL = 32,
SYMBOL_TRADE_EXEMODE = 33,
SYMBOL_SWAP_MODE = 37,
SYMBOL_SWAP_ROLLOVER3DAYS = 40,
SYMBOL_EXPIRATION_MODE = 49,
SYMBOL_FILLING_MODE = 50,
SYMBOL_ORDER_MODE = 71
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_double
public enum EnumTerminalInfoDouble
{
TERMINAL_COMMUNITY_BALANCE = 25 // Balance in MQL5.community
}
}
+27
View File
@@ -0,0 +1,27 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_integer
public enum EnumTerminalInfoInteger
{
TERMINAL_BUILD = 5, // The client terminal build number
TERMINAL_COMMUNITY_ACCOUNT = 23, // The flag indicates the presence of MQL5.community authorization data in the terminal
TERMINAL_COMMUNITY_CONNECTION = 24, // Connection to MQL5.community
TERMINAL_CONNECTED = 6, // Connection to a trade server
TERMINAL_DLLS_ALLOWED = 7, // Permission to use DLL
TERMINAL_TRADE_ALLOWED = 8, // Permission to trade
TERMINAL_EMAIL_ENABLED = 9, // Permission to send e-mails using SMTP-server and login, specified in the terminal settings
TERMINAL_FTP_ENABLED = 10, // Permission to send reports using FTP-server and login, specified in the terminal settings
TERMINAL_NOTIFICATIONS_ENABLED = 26, // Permission to send notifications to smartphone
TERMINAL_MAXBARS = 11, // The maximal bars count on the chart
TERMINAL_MQID = 22, // The flag indicates the presence of MetaQuotes ID data to send Push notifications
TERMINAL_CODEPAGE = 12, // Number of the code page of the language installed in the client terminal
TERMINAL_CPU_CORES = 21, // The number of CPU cores in the system
TERMINAL_DISK_SPACE = 20, // Free disk space for the MQL4\Files folder of the terminal, Mb
TERMINAL_MEMORY_PHYSICAL = 14, // Physical memory in the system, Mb
TERMINAL_MEMORY_TOTAL = 15, // Memory available to the process of the terminal , Mb
TERMINAL_MEMORY_AVAILABLE = 16, // Free memory of the terminal process, Mb
TERMINAL_MEMORY_USED = 17, // Memory used by the terminal , Mb
TERMINAL_SCREEN_DPI = 27, // The resolution of information display on the screen is measured as number of Dots in a line per Inch (DPI). Knowing the parameter value, you can set the size of graphical objects so that they look the same on monitors with different resolution characteristics.
TERMINAL_PING_LAST = 28 // The last known value of a ping to a trade server in microseconds. One second comprises of one million microseconds
}
}
-42
View File
@@ -1,42 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MtApi
{
static class ExtensionMethods
{
#region Event Methods
public static Task FireEventAsync(this MtApiQuoteHandler evenHandler, object sender, string symbol, double bid, double ask)
{
return Task.Factory.StartNew(() =>
{
evenHandler?.Invoke(sender, symbol, bid, ask);
});
}
public static Task FireEventAsync(this EventHandler eventHandler, object sender)
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, EventArgs.Empty);
});
}
public static Task FireEventAsync<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, e);
});
}
#endregion
public static MtQuote Convert(this MTApiService.MtQuote quote)
{
return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null;
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace MtApi
{
[Flags]
public enum FlagFontStyle
{
//Flags for specifying font style
FONT_ITALIC = -2147483648,
FONT_UNDERLINE = 1073741824,
FONT_STRIKEOUT = 536870912,
//Flags for specifying font width
FW_DONTCARE = 0,
FW_THIN = 1,
FW_EXTRALIGHT = 2,
FW_ULTRALIGHT = 3,
FW_LIGHT = 4,
FW_NORMAL = 5,
FW_REGULAR = 6,
FW_MEDIUM = 7,
FW_SEMIBOLD = 8,
FW_DEMIBOLD = 9,
FW_BOLD = 10,
FW_EXTRABOLD = 11,
FW_ULTRABOLD = 12,
FW_HEAVY = 13,
FW_BLACK = 14
}
}
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public enum MarketInfoModeType
{
+3 -8
View File
@@ -4,7 +4,7 @@ namespace MtApi.Monitors
public class TimeframeTradeMonitor : TradeMonitor
{
#region Fields
private volatile bool _isStarted = false;
private volatile bool _isStarted;
#endregion
#region ctor
@@ -23,13 +23,8 @@ namespace MtApi.Monitors
// Returns:
// true if PositionMonitor should check orders
// otherwise, false.
public override bool IsStarted
{
get
{
return _isStarted;
}
}
public override bool IsStarted => _isStarted;
#endregion
#region Protected Methods
+6 -15
View File
@@ -13,7 +13,7 @@ namespace MtApi.Monitors
#endregion
#region ctor
public TradeMonitor(MtApiClient apiClient)
protected TradeMonitor(MtApiClient apiClient)
{
if (apiClient == null)
throw new ArgumentNullException(nameof(apiClient));
@@ -73,13 +73,7 @@ namespace MtApi.Monitors
protected abstract void OnMtConnected();
protected abstract void OnMtDisconnected();
public bool IsMtConnected
{
get
{
return _apiClient.ConnectionState == MtConnectionState.Connected;
}
}
public bool IsMtConnected => _apiClient.ConnectionState == MtConnectionState.Connected;
protected void Check()
{
@@ -113,12 +107,12 @@ namespace MtApi.Monitors
prevOrders = _prevOrders;
}
if (_prevOrders != null) //skip checking on first load orders
if (prevOrders != null) //skip checking on first load orders
{
//check open orders
foreach (var order in tradesOrders)
{
if (_prevOrders.Find(a => a.Ticket == order.Ticket) == null)
if (prevOrders.Find(a => a.Ticket == order.Ticket) == null)
{
openedOrders.Add(order);
}
@@ -126,7 +120,7 @@ namespace MtApi.Monitors
//check closed orders
var closeOrdersTemp = new List<MtOrder>();
foreach (var order in _prevOrders)
foreach (var order in prevOrders)
{
if (tradesOrders.Find(a => a.Ticket == order.Ticket) == null)
{
@@ -180,10 +174,7 @@ namespace MtApi.Monitors
_prevOrders = null;
}
Task.Factory.StartNew(() =>
{
Check();
});
Task.Factory.StartNew(Check);
}
#endregion
}
+1 -6
View File
@@ -5,12 +5,7 @@ namespace MtApi
public class MqlRates
{
public int MtTime { get; set; }
public DateTime Time
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtTime); }
}
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
public double Open { get; set; }
public double High { get; set; }
public double Low { get; set; }
+14
View File
@@ -0,0 +1,14 @@
using System;
namespace MtApi
{
public class MqlTick
{
public int MtTime { get; set; }
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
public double Bid { get; set; }
public double Ask { get; set; }
public double Last { get; set; }
public ulong Volume { get; set; }
}
}
+21 -1
View File
@@ -59,9 +59,20 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ChartPeriod.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="EnumColorFormat.cs" />
<Compile Include="EnumObject.cs" />
<Compile Include="EnumObjectPropertyDouble.cs" />
<Compile Include="EnumObjectPropertyInteger.cs" />
<Compile Include="EnumObjectPropertyString.cs" />
<Compile Include="EnumSeriesInfoInteger.cs" />
<Compile Include="EnumSymbolInfoDouble.cs" />
<Compile Include="EnumSymbolInfoInteger.cs" />
<Compile Include="EnumTerminalInfoDouble.cs" />
<Compile Include="EnumTerminalInfoInteger.cs" />
<Compile Include="FlagFontStyle.cs" />
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
<Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" />
<Compile Include="MtConnectionEventArgs.cs" />
<Compile Include="MtConnectionException.cs" />
<Compile Include="MtConnectionState.cs" />
@@ -72,6 +83,7 @@
<Compile Include="MtOrder.cs" />
<Compile Include="MtQuote.cs" />
<Compile Include="MtQuoteEventArgs.cs" />
<Compile Include="MtSession.cs" />
<Compile Include="MtTimeBar.cs" />
<Compile Include="MtTypes.cs" />
<Compile Include="Monitors\TradeMonitor.cs" />
@@ -90,14 +102,22 @@
<Compile Include="Requests\OrderDeleteRequest.cs" />
<Compile Include="Requests\OrderModifyRequest.cs" />
<Compile Include="Requests\OrderSendRequest.cs" />
<Compile Include="Requests\SeriesInfoIntegerRequest.cs" />
<Compile Include="Requests\SessionRequest.cs" />
<Compile Include="Requests\RequestBase.cs" />
<Compile Include="Requests\RequestType.cs" />
<Compile Include="Requests\SymbolInfoDoubleRequest.cs" />
<Compile Include="Requests\SymbolInfoTickRequest.cs" />
<Compile Include="Responses\CopyRatesResponse.cs" />
<Compile Include="Responses\GetOrderResponse.cs" />
<Compile Include="Responses\GetOrdersResponse.cs" />
<Compile Include="Responses\ICustomResponse.cs" />
<Compile Include="Responses\OrderSendResponse.cs" />
<Compile Include="Responses\SeriesInfoIntegerResponse.cs" />
<Compile Include="Responses\SessionResponse.cs" />
<Compile Include="Responses\ResponseBase.cs" />
<Compile Include="Responses\SymbolInfoDoubleResponse.cs" />
<Compile Include="Responses\SymbolInfoTickResponse.cs" />
<Compile Include="SeriesIdentifier.cs" />
<Compile Include="TimeBarArgs.cs" />
<Compile Include="Monitors\TimeframeTradeMonitor.cs" />
+1071 -270
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -13,9 +13,9 @@ namespace MtApi
return Color.FromArgb((byte)(color), (byte)(color >> 8), (byte)(color >> 16));
}
public static int ConvertToMtColor(Color color)
public static int ConvertToMtColor(Color? color)
{
return color == Color.Empty ? 0xffffff : (Color.FromArgb(color.B, color.G, color.R).ToArgb() & 0xffffff);
return color == null || color == Color.Empty ? 0xffffff : (Color.FromArgb(color.Value.B, color.Value.G, color.Value.R).ToArgb() & 0xffffff);
}
}
}
+3 -3
View File
@@ -13,13 +13,13 @@ namespace MtApi
return new DateTime(tmpTime.Ticks + (time * 0x989680L));
}
public static int ConvertToMtTime(DateTime time)
public static int ConvertToMtTime(DateTime? time)
{
int result = 0;
if (time != DateTime.MinValue)
if (time != null && time != DateTime.MinValue)
{
DateTime tmpTime = new DateTime(1970, 1, 1);
result = (int)((time.Ticks - tmpTime.Ticks) / 0x989680L);
result = (int)((time.Value.Ticks - tmpTime.Ticks) / 0x989680L);
}
return result;
}
+49 -17
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
enum MtCommandType
{
@@ -58,9 +53,15 @@ namespace MtApi
IsVisualMode = 37,
UninitializeReason = 38,
ErrorDescription = 39,
TerminalCompany = 68,
TerminalName = 69,
TerminalPath = 70,
TerminalInfoString = 153,
TerminalInfoInteger = 204,
TerminalInfoDouble = 205,
//Account Information
AccountBalance = 40,
AccountBalance = 40,
AccountCredit = 41,
AccountCompany = 42,
AccountCurrency = 43,
@@ -91,11 +92,6 @@ namespace MtApi
SendMail = 66,
Sleep = 67,
//Client Terminal
TerminalCompany = 68,
TerminalName = 69,
TerminalPath = 70,
//Date and Time
Day = 71,
DayOfWeek = 72,
@@ -139,8 +135,8 @@ namespace MtApi
iBullsPower = 106,
iCCI = 107,
iCCIOnArray = 108,
iCustom = 109,
iCustom_d = 10109,
//iCustom = 109,
//iCustom_d = 10109,
iDeMarker = 110,
iEnvelopes = 111,
iEnvelopesOnArray = 112,
@@ -188,13 +184,49 @@ namespace MtApi
//
RefreshRates = 150,
//
TerminalInfoString = 153,
SymbolInfoString = 154,
//Requests
MtRequest = 155,
//Backtesting
BacktestingReady = 156
BacktestingReady = 156,
//Market Info
SymbolInfoString = 154,
SymbolsTotal = 200,
SymbolName = 201,
SymbolSelect = 202,
SymbolInfoInteger = 203,
ChartId = 206,
ChartRedraw = 207,
//Object Functions
ObjectCreate = 208,
ObjectName = 209,
ObjectDelete = 210,
ObjectsDeleteAll = 211,
ObjectFind = 212,
ObjectGetTimeByValue = 213,
ObjectGetValueByTime = 214,
ObjectMove = 215,
ObjectsTotal = 216,
ObjectGetDouble = 217,
ObjectGetInteger = 218,
ObjectGetString = 219,
ObjectSetDouble = 220,
ObjectSetInteger = 221,
ObjectSetString = 222,
TextSetFont = 223,
TextOut = 224,
TextGetSize = 225,
ObjectDescription = 226,
ObjectGet = 227,
ObjectGetFiboDescription = 228,
ObjectGetShiftByValue = 229,
ObjectGetValueByShift = 230,
ObjectSet = 231,
ObjectSetFiboDescription = 232,
ObjectSetText = 233,
ObjectType = 234
}
}
+1 -4
View File
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
public class MtConnectionEventArgs: EventArgs
{
public MtConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; }
public string ConnectionMessage { get; private set; }
public MtConnectionEventArgs(MtConnectionState status, string message)
{
Regular → Executable
+85 -84
View File
@@ -1,5 +1,6 @@
namespace MtApi
{
// https://docs.mql4.com/constants/errorswarnings/errorcodes
public enum MtErrorCode
{
MtApiCustomError = -1, // Error occurred in MtApi.
@@ -10,91 +11,91 @@
ServerBusy = 4, // Trade server is busy.
OldVersion = 5, // Old version of the client terminal.
NoConnection = 6, // No connection with trade server.
NotEnoughRights = 7, // Not enough rights.
TooFrequentRequests = 8, // Too frequent requests.
MalfunctionalTrade = 9, // Malfunctional trade operation.
NotEnoughRights = 7, // Not enough rights.
TooFrequentRequests = 8, // Too frequent requests.
MalfunctionalTrade = 9, // Malfunctional trade operation.
AccountDisabled = 64, // Account disabled.
InvalidAccount = 65, // Invalid account.
TradeTimeout = 128, // Trade timeout.
InvalidPrice = 129, // Invalid price.
InvalidStops = 130, // Invalid stops.
InvalidTradeVolume = 131, // Invalid trade volume.
MarketClosed = 132, // Market is closed.
TradeDisabled = 133, // Trade is disabled.
NotEnoughMoney = 134, // Not enough money.
PriceChanged = 135, // Price changed.
OffQuotes = 136, // Off quotes.
BrokerBusy = 137, // Broker is busy.
Requote = 138, // Requote.
OrderLocked = 139, // Order is locked.
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
TooManyRequests = 141, // Too many requests.
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
TradeContextBusy = 146, // Trade context is busy.
TradeExpirationDenied = 147, // Expirations are denied by broker.
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
InvalidAccount = 65, // Invalid account.
TradeTimeout = 128, // Trade timeout.
InvalidPrice = 129, // Invalid price.
InvalidStops = 130, // Invalid stops.
InvalidTradeVolume = 131, // Invalid trade volume.
MarketClosed = 132, // Market is closed.
TradeDisabled = 133, // Trade is disabled.
NotEnoughMoney = 134, // Not enough money.
PriceChanged = 135, // Price changed.
OffQuotes = 136, // Off quotes.
BrokerBusy = 137, // Broker is busy.
Requote = 138, // Requote.
OrderLocked = 139, // Order is locked.
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
TooManyRequests = 141, // Too many requests.
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
TradeContextBusy = 146, // Trade context is busy.
TradeExpirationDenied = 147, // Expirations are denied by broker.
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
NoMqlerror = 4000, // No error.
WrongFunctionPointer = 4001, // Wrong function pointer.
ArrayIndexOutOfRange = 4002, // Array index is out of range.
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
RecursiveStackOverflow = 4004, // Recursive stack overflow.
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
NoMemoryForParameterString = 4006, // No memory for parameter string.
NoMemoryForTempString = 4007, // No memory for temp string.
NotInitializedString = 4008, // Not initialized string.
NotInitializedArraystring = 4009, // Not initialized string in an array.
NoMemoryForArraystring = 4010, // No memory for an array string.
TooLongString = 4011, // Too long string.
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
ZeroDivide = 4013, // Zero divide.
UnknownCommand = 4014, // Unknown command.
WrongJump = 4015, // Wrong jump.
NotInitializedArray = 4016, // Not initialized array.
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
CannotLoadLibrary = 4018, // Cannot load library.
CannotCallFunction = 4019, // Cannot call function.
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
SystemBusy = 4022, // System is busy.
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
StringFunctionInternalError = 4052, // String function internal error.
SomeArrayError = 4053, // Some array error.
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
CustomIndicatorError = 4055, // Custom indicator error.
IncompatibleArrays = 4056, // Arrays are incompatible.
GlobalVariablesProcessingError = 4057, // Global variables processing error.
GlobalVariableNotFound = 4058, // Global variable not found.
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
FunctionNotConfirmed = 4060, // Function is not confirmed.
SendMailError = 4061, // Mail sending error.
StringParameterExpected = 4062, // String parameter expected.
IntegerParameterExpected = 4063, // Integer parameter expected.
DoubleParameterExpected = 4064, // Double parameter expected.
ArrayAsParameterExpected = 4065, // Array as parameter expected.
HistoryWillUpdated = 4066, // Requested history data in updating state.
TradeError = 4067, // Some error in trade operation execution.
EndOfFile = 4099, // End of a file.
SomeFileError = 4100, // Some file error.
WrongFileName = 4101, // Wrong file name.
TooManyOpenedFiles = 4102, // Too many opened files.
CannotOpenFile = 4103, // Cannot open file.
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
NoOrderSelected = 4105, // No order selected.
UnknownSymbol = 4106, // Unknown symbol.
InvalidPriceParam = 4107, // Invalid price.
InvalidTicket = 4108, // Invalid ticket.
TradeNotAllowed = 4109, // Trade is not allowed.
LongsNotAllowed = 4110, // Longs are not allowed.
ShortsNotAllowed = 4111, // Shorts are not allowed.
ObjectAlreadyExists = 4200, // Object already exists.
UnknownObjectProperty = 4201, // Unknown object property.
ObjectDoesNotExist = 4202, // Object does not exist.
UnknownObjectType = 4203, // Unknown object type.
NoObjectName = 4204, // No object name.
ObjectCoordinatesError = 4205, // Object coordinates error.
NoSpecifiedSubwindow = 4206, // No specified subwindow.
SomeObjectError = 4207 // Some error in object operation.
NoMqlerror = 4000, // No error.
WrongFunctionPointer = 4001, // Wrong function pointer.
ArrayIndexOutOfRange = 4002, // Array index is out of range.
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
RecursiveStackOverflow = 4004, // Recursive stack overflow.
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
NoMemoryForParameterString = 4006, // No memory for parameter string.
NoMemoryForTempString = 4007, // No memory for temp string.
NotInitializedString = 4008, // Not initialized string.
NotInitializedArraystring = 4009, // Not initialized string in an array.
NoMemoryForArraystring = 4010, // No memory for an array string.
TooLongString = 4011, // Too long string.
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
ZeroDivide = 4013, // Zero divide.
UnknownCommand = 4014, // Unknown command.
WrongJump = 4015, // Wrong jump.
NotInitializedArray = 4016, // Not initialized array.
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
CannotLoadLibrary = 4018, // Cannot load library.
CannotCallFunction = 4019, // Cannot call function.
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
SystemBusy = 4022, // System is busy.
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
StringFunctionInternalError = 4052, // String function internal error.
SomeArrayError = 4053, // Some array error.
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
CustomIndicatorError = 4055, // Custom indicator error.
IncompatibleArrays = 4056, // Arrays are incompatible.
GlobalVariablesProcessingError = 4057, // Global variables processing error.
GlobalVariableNotFound = 4058, // Global variable not found.
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
FunctionNotConfirmed = 4060, // Function is not confirmed.
SendMailError = 4061, // Mail sending error.
StringParameterExpected = 4062, // String parameter expected.
IntegerParameterExpected = 4063, // Integer parameter expected.
DoubleParameterExpected = 4064, // Double parameter expected.
ArrayAsParameterExpected = 4065, // Array as parameter expected.
HistoryWillUpdated = 4066, // Requested history data in updating state.
TradeError = 4067, // Some error in trade operation execution.
EndOfFile = 4099, // End of a file.
SomeFileError = 4100, // Some file error.
WrongFileName = 4101, // Wrong file name.
TooManyOpenedFiles = 4102, // Too many opened files.
CannotOpenFile = 4103, // Cannot open file.
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
NoOrderSelected = 4105, // No order selected.
UnknownSymbol = 4106, // Unknown symbol.
InvalidPriceParam = 4107, // Invalid price.
InvalidTicket = 4108, // Invalid ticket.
TradeNotAllowed = 4109, // Trade is not allowed.
LongsNotAllowed = 4110, // Longs are not allowed.
ShortsNotAllowed = 4111, // Shorts are not allowed.
ObjectAlreadyExists = 4200, // Object already exists.
UnknownObjectProperty = 4201, // Unknown object property.
ObjectDoesNotExist = 4202, // Object does not exist.
UnknownObjectType = 4203, // Unknown object type.
NoObjectName = 4204, // No object name.
ObjectCoordinatesError = 4205, // Object coordinates error.
NoSpecifiedSubwindow = 4206, // No specified subwindow.
SomeObjectError = 4207 // Some error in object operation.
}
}
+10 -6
View File
@@ -1,15 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public class MtQuote
{
public string Instrument { get; private set; }
public double Bid { get; private set; }
public double Ask { get; private set; }
public int ExpertHandle { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
@@ -17,5 +13,13 @@ namespace MtApi
Bid = bid;
Ask = ask;
}
internal MtQuote(MTApiService.MtQuote quote)
{
Instrument = quote.Instrument;
Bid = quote.Bid;
Ask = quote.Ask;
ExpertHandle = quote.ExpertHandle;
}
}
}
-3
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
+23
View File
@@ -0,0 +1,23 @@
using System;
namespace MtApi
{
public class MtSession
{
public string Symbol { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public uint Index { get; set; }
public int MtFromTime { get; set; }
public DateTime From => MtApiTimeConverter.ConvertFromMtTime(MtFromTime);
public int MtToTime { get; set; }
public DateTime To => MtApiTimeConverter.ConvertFromMtTime(MtToTime);
public bool HasData { get; set; }
public SessionType Type { get; set; }
}
public enum SessionType
{
Quote,
Trade
}
}
Executable → Regular
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.30.0")]
[assembly: AssemblyFileVersion("1.0.30.0")]
[assembly: AssemblyVersion("1.0.33.0")]
[assembly: AssemblyFileVersion("1.0.33.0")]
+9 -27
View File
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Requests
namespace MtApi.Requests
{
public abstract class CopyRatesRequestBase : RequestBase
internal abstract class CopyRatesRequestBase : RequestBase
{
public enum CopyRatesTypeEnum
{
@@ -15,10 +9,7 @@ namespace MtApi.Requests
CopyRates_3 = 3,
}
public override RequestType RequestType
{
get { return RequestType.CopyRates; }
}
public override RequestType RequestType => RequestType.CopyRates;
public abstract CopyRatesTypeEnum CopyRatesType { get; }
@@ -26,34 +17,25 @@ namespace MtApi.Requests
public ENUM_TIMEFRAMES Timeframe { get; set; }
}
public class CopyRates1Request : CopyRatesRequestBase
internal class CopyRates1Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_1; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_1;
public int StartPos { get; set; }
public int Count { get; set; }
}
public class CopyRates2Request : CopyRatesRequestBase
internal class CopyRates2Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_2; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_2;
public int StartTime { get; set; }
public int Count { get; set; }
}
public class CopyRates3Request : CopyRatesRequestBase
internal class CopyRates3Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_3; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_3;
public int StartTime { get; set; }
public int StopTime { get; set; }
+2 -5
View File
@@ -1,14 +1,11 @@
namespace MtApi.Requests
{
public class GetOrderRequest: RequestBase
internal class GetOrderRequest: RequestBase
{
public int Index { get; set; }
public int Select { get; set; }
public int Pool { get; set; }
public override RequestType RequestType
{
get { return RequestType.GetOrder; }
}
public override RequestType RequestType => RequestType.GetOrder;
}
}
+2 -5
View File
@@ -1,12 +1,9 @@
namespace MtApi.Requests
{
public class GetOrdersRequest: RequestBase
internal class GetOrdersRequest: RequestBase
{
public int Pool { get; set; }
public override RequestType RequestType
{
get { return RequestType.GetOrders; }
}
public override RequestType RequestType => RequestType.GetOrders;
}
}
Regular → Executable
+3 -8
View File
@@ -1,10 +1,8 @@

using System;
using System.Collections;
using System.Collections;
namespace MtApi.Requests
{
public class ICustomRequest : RequestBase
internal class ICustomRequest : RequestBase
{
public enum ParametersType
{
@@ -22,9 +20,6 @@ namespace MtApi.Requests
public ArrayList Params { get; set; }
public ParametersType ParamsType { get; set; }
public override RequestType RequestType
{
get { return RequestType.iCustom; }
}
public override RequestType RequestType => RequestType.iCustom;
}
}
+2 -5
View File
@@ -1,15 +1,12 @@
namespace MtApi.Requests
{
public class OrderCloseByRequest: RequestBase
internal class OrderCloseByRequest: RequestBase
{
public int Ticket { get; set; }
public int Opposite { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderCloseBy; }
}
public override RequestType RequestType => RequestType.OrderCloseBy;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderCloseRequest: RequestBase
internal class OrderCloseRequest: RequestBase
{
public int Ticket { get; set; }
@@ -9,9 +9,6 @@
public int? Slippage { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderClose; }
}
public override RequestType RequestType => RequestType.OrderClose;
}
}
+2 -5
View File
@@ -1,14 +1,11 @@
namespace MtApi.Requests
{
public class OrderDeleteRequest: RequestBase
internal class OrderDeleteRequest: RequestBase
{
public int Ticket { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderDelete; }
}
public override RequestType RequestType => RequestType.OrderDelete;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderModifyRequest: RequestBase
internal class OrderModifyRequest: RequestBase
{
public int Ticket { get; set; }
public double Price { get; set; }
@@ -10,9 +10,6 @@
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderModify; }
}
public override RequestType RequestType => RequestType.OrderModify;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderSendRequest: RequestBase
internal class OrderSendRequest: RequestBase
{
public string Symbol { get; set; }
public int Cmd { get; set; }
@@ -15,9 +15,6 @@
public int? Expiration { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderSend; }
}
public override RequestType RequestType => RequestType.OrderSend;
}
}
+6 -8
View File
@@ -1,9 +1,7 @@
using Newtonsoft.Json;
namespace MtApi.Requests
{
public abstract class RequestBase
namespace MtApi.Requests
{
internal abstract class RequestBase
{
public abstract RequestType RequestType { get; }
}
}
public abstract RequestType RequestType { get; }
}
}
+15 -11
View File
@@ -1,16 +1,20 @@
namespace MtApi.Requests
{
public enum RequestType
internal enum RequestType
{
Unknown = 0,
GetOrder = 1,
GetOrders = 2,
OrderSend = 3,
OrderClose = 4,
OrderCloseBy = 5,
OrderDelete = 6,
OrderModify = 7,
iCustom = 8,
CopyRates = 9
Unknown = 0,
GetOrder = 1,
GetOrders = 2,
OrderSend = 3,
OrderClose = 4,
OrderCloseBy = 5,
OrderDelete = 6,
OrderModify = 7,
iCustom = 8,
CopyRates = 9,
Session = 10,
SeriesInfoInteger = 11,
SymbolInfoDouble = 12,
SymbolInfoTick = 13
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi.Requests
{
internal class SeriesInfoIntegerRequest: RequestBase
{
public override RequestType RequestType => RequestType.SeriesInfoInteger;
public string SymbolName { get; set; }
public int Timeframe { get; set; }
public int PropId { get; set; }
}
}
+14
View File
@@ -0,0 +1,14 @@
using System;
namespace MtApi.Requests
{
internal class SessionRequest : RequestBase
{
public string Symbol { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public int SessionIndex { get; set; }
public SessionType SessionType { get; set; }
public override RequestType RequestType => RequestType.Session;
}
}
+12
View File
@@ -0,0 +1,12 @@
using System;
namespace MtApi.Requests
{
internal class SymbolInfoDoubleRequest : RequestBase
{
public override RequestType RequestType => RequestType.SymbolInfoDouble;
public string SymbolName { get; set; }
public int PropId { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi.Requests
{
internal class SymbolInfoTickRequest: RequestBase
{
public override RequestType RequestType => RequestType.SymbolInfoTick;
public string Symbol { get; set; }
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MtApi.Responses
{
public class CopyRatesResponse: ResponseBase
internal class CopyRatesResponse: ResponseBase
{
public List<MqlRates> Rates { get; set; }
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class GetOrderResponse: ResponseBase
internal class GetOrderResponse: ResponseBase
{
public MtOrder Order { get; set; }
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MtApi.Responses
{
public class GetOrdersResponse: ResponseBase
internal class GetOrdersResponse: ResponseBase
{
public List<MtOrder> Orders { get; set; }
}
+2 -8
View File
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Responses
namespace MtApi.Responses
{
public class ICustomResponse: ResponseBase
internal class ICustomResponse: ResponseBase
{
public double Value { get; set; }
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class OrderSendResponse: ResponseBase
internal class OrderSendResponse: ResponseBase
{
public int Ticket { get; set; }
}
Regular → Executable
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class ResponseBase
internal class ResponseBase
{
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SeriesInfoIntegerResponse: ResponseBase
{
public long Value { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SessionResponse : ResponseBase
{
public MtSession Session { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SymbolInfoDoubleResponse: ResponseBase
{
public double Value { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SymbolInfoTickResponse: ResponseBase
{
public MqlTick Tick { get; set; }
}
}
-4
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public enum TradeOperation
{
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi5
{
public enum CopyTicksFlag
{
Info = 1, // ticks with Bid and/or Ask changes
Trade = 2, // ticks with changes in Last and Volume
All = -1 // all ticks
}
}
+188
View File
@@ -0,0 +1,188 @@
namespace MtApi5
{
//Error codes from https://www.mql5.com/en/docs/constants/errorswarnings/errorcodes
public enum ErrorCode
{
ErrCustom = -1, // Error occurred in MtApi5.
ErrSuccess = 0, // The operation completed successfully
ErrInternalError = 4001, // Unexpected internal error
ErrWrongInternalParameter = 4002, // Wrong parameter in the inner call of the client terminal function
ErrInvalidParameter = 4003, // Wrong parameter when calling the system function
ErrNotEnoughMemory = 4004, // Not enough memory to perform the system function
ErrStructWithobjectsOrclass = 4005, // The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes
ErrInvalidArray = 4006, // Array of a wrong type, wrong size, or a damaged object of a dynamic array
ErrArrayResizeError = 4007, // Not enough memory for the relocation of an array, or an attempt to change the size of a static array
ErrStringResizeError = 4008, // Not enough memory for the relocation of string
ErrNotinitializedString = 4009, // Not initialized string
ErrInvalidDatetime = 4010, // Invalid date and/or time
ErrArrayBadSize = 4011, // Requested array size exceeds 2 GB
ErrInvalidPointer = 4012, // Wrong pointer
ErrInvalidPointerType = 4013, // Wrong type of pointer
ErrFunctionNotAllowed = 4014, // Function is not allowed for call
ErrResourceNameDuplicated = 4015, // The names of the dynamic and the static resource match
ErrResourceNotFound = 4016, // Resource with this name has not been found in EX5
ErrResourceUnsuppotedType = 4017, // Unsupported resource type or its size exceeds 16 Mb
ErrResourceNameIsTooLong = 4018, // The resource name exceeds 63 characters
ErrChartWrongId = 4101, // Wrong chart ID
ErrChartNoReply = 4102, // Chart does not respond
ErrChartNotFound = 4103, // Chart not found
ErrChartNoExpert = 4104, // No Expert Advisor in the chart that could handle the event
ErrChartCannotOpen = 4105, // Chart opening error
ErrChartCannotChange = 4106, // Failed to change chart symbol and period
ErrChartWrongParameter = 4107, // Error value of the parameter for the function of working with charts
ErrChartCannotCreateTimer = 4108, // Failed to create timer
ErrChartWrongProperty = 4109, // Wrong chart property ID
ErrChartScreenshotFailed = 4110, // Error creating screenshots
ErrChartNavigateFailed = 4111, // Error navigating through chart
ErrChartTemplateFailed = 4112, // Error applying template
ErrChartWindowNotFound = 4113, // Subwindow containing the indicator was not found
ErrChartIndicatorCannotAdd = 4114, // Error adding an indicator to chart
ErrChartIndicatorCannotDel = 4115, // Error deleting an indicator from the chart
ErrChartIndicatorNotFound = 4116, // Indicator not found on the specified chart
ErrObjectError = 4201, // Error working with a graphical object
ErrObjectNotFound = 4202, // Graphical object was not found
ErrObjectWrongProperty = 4203, // Wrong ID of a graphical object property
ErrObjectGetdateFailed = 4204, // Unable to get date corresponding to the value
ErrObjectGetvalueFailed = 4205, // Unable to get value corresponding to the date
ErrMarketUnknownSymbol = 4301, // Unknown symbol
ErrMarketNotSelected = 4302, // Symbol is not selected in MarketWatch
ErrMarketWrongProperty = 4303, // Wrong identifier of a symbol property
ErrMarketLasttimeUnknown = 4304, // Time of the last tick is not known (no ticks)
ErrMarketSelectError = 4305, // Error adding or deleting a symbol in MarketWatch
ErrHistoryNotFound = 4401, // Requested history not found
ErrHistoryWrongProperty = 4402, // Wrong ID of the history property
ErrGlobalvariableNotFound = 4501, // Global variable of the client terminal is not found
ErrGlobalvariableExists = 4502, // Global variable of the client terminal with the same name already exists
ErrMailSendFailed = 4510, // Email sending failed
ErrPlaySoundFailed = 4511, // Sound playing failed
ErrMql5WrongProperty = 4512, // Wrong identifier of the program property
ErrTerminalWrongProperty = 4513, // Wrong identifier of the terminal property
ErrFtpSendFailed = 4514, // File sending via ftp failed
ErrNotificationSendFailed = 4515, // Failed to send a notification
ErrNotificationWrongParameter = 4516, // Invalid parameter for sending a notification — an empty string or NULL has been passed to the SendNotification() function
ErrNotificationWrongSettings = 4517, // Wrong settings of notifications in the terminal (ID is not specified or permission is not set)
ErrNotificationTooFrequent = 4518, // Too frequent sending of notifications
ErrFtpNoserver = 4519, // FTP server is not specified
ErrFtpNologin = 4520, // FTP login is not specified
ErrFtpFileError = 4521, // File not found in the MQL5\Files directory to send on FTP server
ErrFtpConnectFailed = 4522, // FTP connection failed
ErrFtpChangedir = 4523, // FTP path not found on server
ErrFtpClosed = 4524, // FTP connection closed
ErrBuffersNoMemory = 4601, // Not enough memory for the distribution of indicator buffers
ErrBuffersWrongIndex = 4602, // Wrong indicator buffer index
ErrCustomWrongProperty = 4603, // Wrong ID of the custom indicator property
ErrAccountWrongProperty = 4701, // Wrong account property ID
ErrTradeWrongProperty = 4751, // Wrong trade property ID
ErrTradeDisabled = 4752, // Trading by Expert Advisors prohibited
ErrTradePositionNotFound = 4753, // Position not found
ErrTradeOrderNotFound = 4754, // Order not found
ErrTradeDealNotFound = 4755, // Deal not found
ErrTradeSendFailed = 4756, // Trade request sending failed
ErrIndicatorUnknownSymbol = 4801, // Unknown symbol
ErrIndicatorCannotCreate = 4802, // Indicator cannot be created
ErrIndicatorNoMemory = 4803, // Not enough memory to add the indicator
ErrIndicatorCannotApply = 4804, // The indicator cannot be applied to another indicator
ErrIndicatorCannotAdd = 4805, // Error applying an indicator to chart
ErrIndicatorDataNotFound = 4806, // Requested data not found
ErrIndicatorWrongHandle = 4807, // Wrong indicator handle
ErrIndicatorWrongParameters = 4808, // Wrong number of parameters when creating an indicator
ErrIndicatorParametersMissing = 4809, // No parameters when creating an indicator
ErrIndicatorCustomName = 4810, // The first parameter in the array must be the name of the custom indicator
ErrIndicatorParameterType = 4811, // Invalid parameter type in the array when creating an indicator
ErrIndicatorWrongIndex = 4812, // Wrong index of the requested indicator buffer
ErrBooksCannotAdd = 4901, // Depth Of Market can not be added
ErrBooksCannotDelete = 4902, // Depth Of Market can not be removed
ErrBooksCannotGet = 4903, // The data from Depth Of Market can not be obtained
ErrBooksCannotSubscribe = 4904, // Error in subscribing to receive new data from Depth Of Market
ErrTooManyFiles = 5001, // More than 64 files cannot be opened at the same time
ErrWrongFilename = 5002, // Invalid file name
ErrTooLongFilename = 5003, // Too long file name
ErrCannotOpenFile = 5004, // File opening error
ErrFileCachebufferError = 5005, // Not enough memory for cache to read
ErrCannotDeleteFile = 5006, // File deleting error
ErrInvalidFilehandle = 5007, // A file with this handle was closed, or was not opening at all
ErrWrongFilehandle = 5008, // Wrong file handle
ErrFileNottowrite = 5009, // The file must be opened for writing
ErrFileNottoread = 5010, // The file must be opened for reading
ErrFileNotbin = 5011, // The file must be opened as a binary one
ErrFileNottxt = 5012, // The file must be opened as a text
ErrFileNottxtorcsv = 5013, // The file must be opened as a text or CSV
ErrFileNotcsv = 5014, // The file must be opened as CSV
ErrFileReaderror = 5015, // File reading error
ErrFileBinstringsize = 5016, // String size must be specified, because the file is opened as binary
ErrIncompatibleFile = 5017, // A text file must be for string arrays, for other arrays - binary
ErrFileIsDirectory = 5018, // This is not a file, this is a directory
ErrFileNotExist = 5019, // File does not exist
ErrFileCannotRewrite = 5020, // File can not be rewritten
ErrWrongDirectoryname = 5021, // Wrong directory name
ErrDirectoryNotExist = 5022, // Directory does not exist
ErrFileIsnotDirectory = 5023, // This is a file, not a directory
ErrCannotDeleteDirectory = 5024, // The directory cannot be removed
ErrCannotCleanDirectory = 5025, // Failed to clear the directory (probably one or more files are blocked and removal operation failed)
ErrFileWriteerror = 5026, // Failed to write a resource to a file
ErrFileEndoffile = 5027, // Unable to read the next piece of data from a CSV file (FileReadString, FileReadNumber, FileReadDatetime, FileReadBool), since the end of file is reached
ErrNoStringDate = 5030, // No date in the string
ErrWrongStringDate = 5031, // Wrong date in the string
ErrWrongStringTime = 5032, // Wrong time in the string
ErrStringTimeError = 5033, // Error converting string to date
ErrStringOutOfMemory = 5034, // Not enough memory for the string
ErrStringSmallLen = 5035, // The string length is less than expected
ErrStringTooBignumber = 5036, // Too large number, more than ULONG_MAX
ErrWrongFormatstring = 5037, // Invalid format string
ErrTooManyFormatters = 5038, // Amount of format specifiers more than the parameters
ErrTooManyParameters = 5039, // Amount of parameters more than the format specifiers
ErrWrongStringParameter = 5040, // Damaged parameter of string type
ErrStringposOutofrange = 5041, // Position outside the string
ErrStringZeroadded = 5042, // 0 added to the string end, a useless operation
ErrStringUnknowntype = 5043, // Unknown data type when converting to a string
ErrWrongStringObject = 5044, // Damaged string object
ErrIncompatibleArrays = 5050, // Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only
ErrSmallAsseriesArray = 5051, // The receiving array is declared as AS_SERIES, and it is of insufficient size
ErrSmallArray = 5052, // Too small array, the starting position is outside the array
ErrZerosizeArray = 5053, // An array of zero length
ErrNumberArraysOnly = 5054, // Must be a numeric array
ErrOnedimArraysOnly = 5055, // Must be a one-dimensional array
ErrSeriesArray = 5056, // Timeseries cannot be used
ErrDoubleArrayOnly = 5057, // Must be an array of type double
ErrFloatArrayOnly = 5058, // Must be an array of type float
ErrLongArrayOnly = 5059, // Must be an array of type long
ErrIntArrayOnly = 5060, // Must be an array of type int
ErrShortArrayOnly = 5061, // Must be an array of type short
ErrCharArrayOnly = 5062, // Must be an array of type char
ErrOpenclNotSupported = 5100, // OpenCL functions are not supported on this computer
ErrOpenclInternal = 5101, // Internal error occurred when running OpenCL
ErrOpenclInvalidHandle = 5102, // Invalid OpenCL handle
ErrOpenclContextCreate = 5103, // Error creating the OpenCL context
ErrOpenclQueueCreate = 5104, // Failed to create a run queue in OpenCL
ErrOpenclProgramCreate = 5105, // Error occurred when compiling an OpenCL program
ErrOpenclTooLongKernelName = 5106, // Too long kernel name (OpenCL kernel)
ErrOpenclKernelCreate = 5107, // Error creating an OpenCL kernel
ErrOpenclSetKernelParameter = 5108, // Error occurred when setting parameters for the OpenCL kernel
ErrOpenclExecute = 5109, // OpenCL program runtime error
ErrOpenclWrongBufferSize = 5110, // Invalid size of the OpenCL buffer
ErrOpenclWrongBufferOffset = 5111, // Invalid offset in the OpenCL buffer
ErrOpenclBufferCreate = 5112, // Failed to create an OpenCL buffer
ErrWebrequestInvalidAddress = 5200, // Invalid URL
ErrWebrequestConnectFailed = 5201, // Failed to connect to specified URL
ErrWebrequestTimeout = 5202, // Timeout exceeded
ErrWebrequestRequestFailed = 5203, // HTTP request failed
ErrUserErrorFirst = 65536 // User defined errors start with this code
}
}
+15
View File
@@ -0,0 +1,15 @@
using System;
namespace MtApi5
{
public class ExecutionException: Exception
{
public ExecutionException(ErrorCode errorCode, string message)
:base(message)
{
ErrorCode = errorCode;
}
public ErrorCode ErrorCode { get; private set; }
}
}
-30
View File
@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
static class ExtensionMethods
{
#region Event Methods
public static void FireEvent(this EventHandler eventHandler, object sender)
{
if (eventHandler != null)
{
eventHandler(sender, EventArgs.Empty);
}
}
public static void FireEvent<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
if (eventHandler != null)
{
eventHandler(sender, e);
}
}
#endregion
}
}
+12 -11
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
@@ -19,13 +16,17 @@ namespace MtApi5
this.real_volume = real_volume;
}
public DateTime time { get; private set; } // Period start time
public double open { get; private set; } // Open price
public double high { get; private set; } // The highest price of the period
public double low { get; private set; } // The lowest price of the period
public double close { get; private set; } // Close price
public long tick_volume { get; private set; } // Tick volume
public int spread { get; private set; } // Spread
public long real_volume { get; private set; } // Trade volume
public MqlRates()
{
}
public DateTime time { get; set; } // Period start time
public double open { get; set; } // Open price
public double high { get; set; } // The highest price of the period
public double low { get; set; } // The lowest price of the period
public double close { get; set; } // Close price
public long tick_volume { get; set; } // Tick volume
public int spread { get; set; } // Spread
public long real_volume { get; set; } // Trade volume
}
}

Some files were not shown because too many files have changed in this diff Show More