mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 11:07:48 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a7bb6f2cb | |||
| d63a53b8a9 | |||
| 7e821fcade | |||
| 8e3f206c76 | |||
| 8e5dcbd2ee | |||
| 563a5a895b | |||
| 32f6018858 | |||
| c64417474a | |||
| 6d4b5f4c00 | |||
| 601c95369e | |||
| 0542dd3e71 | |||
| 15068ca99c | |||
| c3617549f8 | |||
| aa91196e31 | |||
| ba7b50e241 | |||
| ddcd6fa2d5 | |||
| ad55740bc7 | |||
| 26a3db9ae1 | |||
| 7d3af82e1f | |||
| 09b72fc64d | |||
| 834b0af430 | |||
| 5dd1e4831d | |||
| 39f11bfc34 | |||
| c6faaf0602 | |||
| c14726bdba | |||
| 05452e3b90 | |||
| 094cdcc448 | |||
| a63e628124 | |||
| 7fec3da7bc | |||
| 1d407b5e16 | |||
| e373f7976c | |||
| 3785ee4ace | |||
| b4b8e7eaf0 | |||
| 22f7915a4a | |||
| 84dfd21f9f | |||
| d4ee2cfada | |||
| 0b3d686f05 | |||
| cacc0ea787 | |||
| d96dc18ea3 | |||
| 6b4adfaa97 | |||
| 7aa2a1b691 | |||
| 5739423d6c |
Executable
BIN
Binary file not shown.
+341
-341
@@ -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,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;
|
||||
};
|
||||
Executable
+67
@@ -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>
|
||||
Executable
+4
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+52
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ICommandManager.cs" />
|
||||
<Compile Include="IMetaTraderHandler.cs" />
|
||||
<Compile Include="LogConfigurator.cs" />
|
||||
<Compile Include="MtCommandEventArgs.cs" />
|
||||
<Compile Include="IDisposableChannel.cs" />
|
||||
<Compile Include="IMtApiServer.cs" />
|
||||
@@ -78,13 +87,28 @@
|
||||
<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">
|
||||
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
+11
-14
@@ -1,20 +1,17 @@
|
||||
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;
|
||||
InnerDuplexChannel.Open();
|
||||
}
|
||||
|
||||
#region IMtApi Members
|
||||
@@ -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
|
||||
|
||||
+175
-137
@@ -1,173 +1,208 @@
|
||||
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
|
||||
{
|
||||
private static string SERVICE_NAME = "MtApiService";
|
||||
private const string ServiceName = "MtApiService";
|
||||
|
||||
public delegate void MtQuoteHandler(MtQuote quote);
|
||||
|
||||
#region Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient));
|
||||
|
||||
private MtApiProxy _proxy;
|
||||
private bool _isConnected;
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void Open(string host, int port)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Open");
|
||||
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, port);
|
||||
|
||||
if (string.IsNullOrEmpty(host))
|
||||
throw new ArgumentNullException("host", "host is null or empty");
|
||||
throw new ArgumentNullException(nameof(host), "host is null or empty");
|
||||
|
||||
if (port < 0 || port > 65536)
|
||||
throw new ArgumentOutOfRangeException("port", "port value is invalid");
|
||||
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
|
||||
|
||||
var urlService = string.Format("net.tcp://{0}:{1}/{2}", host, port, SERVICE_NAME);
|
||||
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
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;
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Open(int port)
|
||||
{
|
||||
Log.DebugFormat("Open: begin. port = {0}", port);
|
||||
|
||||
if (port < 0 || port > 65536)
|
||||
throw new ArgumentOutOfRangeException("port", "port value is invalid");
|
||||
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
|
||||
|
||||
var urlService = string.Format("net.pipe://localhost/{0}_{1}", SERVICE_NAME, port);
|
||||
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
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;
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Close");
|
||||
Log.Debug("Close: begin.");
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
if (mProxy != null)
|
||||
{
|
||||
mProxy.Faulted -= mProxy_Faulted;
|
||||
mProxy.Dispose();
|
||||
mProxy = null;
|
||||
}
|
||||
|
||||
mIsConnected = false;
|
||||
_proxy.Faulted -= ProxyFaulted;
|
||||
_proxy.Dispose();
|
||||
_proxy = null;
|
||||
}
|
||||
|
||||
_isConnected = false;
|
||||
|
||||
Log.Debug("Close: end.");
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public void Connect()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Connect");
|
||||
Log.Debug("Connect: begin.");
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Error("Connect: _proxy is not defined.");
|
||||
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
|
||||
}
|
||||
|
||||
if (_isConnected)
|
||||
{
|
||||
Log.Warn("Connected: end. Client is already connected.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
if (mProxy != null && mIsConnected == true)
|
||||
return;
|
||||
|
||||
mIsConnected = mProxy.Connect();
|
||||
|
||||
if (mIsConnected == false)
|
||||
throw new Exception("Connected failed");
|
||||
}
|
||||
_isConnected = _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 (_isConnected == 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;
|
||||
_isConnected = false;
|
||||
|
||||
if (mProxy != null)
|
||||
mProxy.Disconnect();
|
||||
}
|
||||
_proxy?.Disconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::Disconnect: {0}", ex.Message);
|
||||
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::SendCommand: commandType = {0}", commandType);
|
||||
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
|
||||
|
||||
MtResponse result = null;
|
||||
MtResponse result;
|
||||
|
||||
if (_isConnected == false)
|
||||
{
|
||||
Log.Error("SendCommand: Client is not connected.");
|
||||
throw new CommunicationException("Client is not connected.");
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Error("SendCommand: Proxy is not defined.");
|
||||
throw new CommunicationException("Proxy is not defined.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
if (mProxy != null && mIsConnected == true)
|
||||
result = mProxy.SendCommand(new MtCommand(commandType, commandParameters));
|
||||
}
|
||||
result = _proxy.SendCommand(new MtCommand(commandType, parameters));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::SendCommand: {0}", ex.Message);
|
||||
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
@@ -177,30 +212,41 @@ namespace MTApiService
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public IEnumerable<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;
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Warn("GetQuotes: end. _proxy is not defined.");
|
||||
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 +255,70 @@ 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");
|
||||
Log.Debug("OnServerStopped: begin.");
|
||||
|
||||
Close();
|
||||
|
||||
ServerDisconnected?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
Log.Debug("OnServerStopped: end.");
|
||||
}
|
||||
|
||||
|
||||
public void OnMtEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent);
|
||||
|
||||
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
|
||||
|
||||
Log.Debug("OnMtEvent: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
return mProxy.State == CommunicationState.Opened && mIsConnected == true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsConnected => _proxy.State == CommunicationState.Opened && _isConnected;
|
||||
|
||||
#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 +327,11 @@ namespace MTApiService
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Dispose");
|
||||
Log.Debug("Dispose: begin.");
|
||||
|
||||
Close();
|
||||
|
||||
Log.Debug("Dispose: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -300,11 +344,5 @@ namespace MTApiService
|
||||
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;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections;
|
||||
|
||||
namespace MTApiService
|
||||
@@ -22,5 +18,9 @@ namespace MTApiService
|
||||
[DataMember]
|
||||
public ArrayList Parameters { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CommandType = {CommandType}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+11
-3
@@ -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,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class MtConnectionProfile
|
||||
|
||||
@@ -1,31 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
internal class MtCommandExecutorManager : ICommandManager
|
||||
{
|
||||
#region Private Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager));
|
||||
|
||||
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
|
||||
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
|
||||
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Log.Debug("Stop: begin.");
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_commandExecutors.Clear();
|
||||
_commandTasks.Clear();
|
||||
}
|
||||
|
||||
Log.Debug("Stop: end.");
|
||||
}
|
||||
|
||||
public void AddCommandExecutor(MtExpert commandExecutor)
|
||||
{
|
||||
if (commandExecutor == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
|
||||
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor))
|
||||
{
|
||||
Log.Warn("AddCommandExecutor: end. Command executor already exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
_commandExecutors.Add(commandExecutor);
|
||||
if (_commandTasks.Count > 0)
|
||||
@@ -41,18 +60,25 @@ namespace MTApiService
|
||||
{
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("AddCommandExecutor: end.");
|
||||
}
|
||||
|
||||
public void RemoveCommandExecutor(MtExpert commandExecutor)
|
||||
{
|
||||
if (commandExecutor == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
|
||||
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor) == false)
|
||||
{
|
||||
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection.");
|
||||
return;
|
||||
}
|
||||
|
||||
_commandExecutors.Remove(commandExecutor);
|
||||
if (_commandTasks.Count > 0)
|
||||
@@ -68,23 +94,31 @@ namespace MTApiService
|
||||
{
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("RemoveCommandExecutor: end.");
|
||||
}
|
||||
|
||||
public void EnqueueCommandTask(MtCommandTask task)
|
||||
{
|
||||
if (task == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
|
||||
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_commandTasks.Enqueue(task);
|
||||
_commandTasks.Enqueue(task);
|
||||
}
|
||||
|
||||
NotifyCommandReady();
|
||||
|
||||
Log.Debug("EnqueueCommandTask: end.");
|
||||
}
|
||||
|
||||
public MtCommandTask DequeueCommandTask()
|
||||
{
|
||||
Log.Debug("DequeueCommandTask: called.");
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
|
||||
@@ -96,6 +130,8 @@ namespace MTApiService
|
||||
#region Private Methods
|
||||
private void NotifyCommandReady()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
var commandExecutors = new List<MtExpert>();
|
||||
lock (_locker)
|
||||
{
|
||||
@@ -106,10 +142,14 @@ namespace MTApiService
|
||||
{
|
||||
executor.NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
|
||||
}
|
||||
|
||||
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
|
||||
{
|
||||
Log.Debug("CommandExecutor_CommandExecuted: begin.");
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
@@ -124,14 +164,8 @@ namespace MTApiService
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("CommandExecutor_CommandExecuted: end.");
|
||||
}
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
+93
-68
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
@@ -6,20 +7,103 @@ namespace MTApiService
|
||||
{
|
||||
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
|
||||
|
||||
#region Private Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
|
||||
|
||||
private readonly IMetaTraderHandler _mtHadler;
|
||||
private MtCommandTask _commandTask;
|
||||
private ICommandManager _commandManager;
|
||||
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);
|
||||
|
||||
_commandTask.SetResult(response);
|
||||
_commandTask = null;
|
||||
FireOnCommandExecuted();
|
||||
|
||||
Log.Debug("SendResponse: end.");
|
||||
}
|
||||
|
||||
public int GetCommandType()
|
||||
{
|
||||
Log.Debug("GetCommandType: called.");
|
||||
|
||||
var commandManager = CommandManager;
|
||||
if (commandManager != null)
|
||||
{
|
||||
_commandTask = commandManager.DequeueCommandTask();
|
||||
}
|
||||
|
||||
return _commandTask?.Command?.CommandType ?? 0;
|
||||
}
|
||||
|
||||
public object GetCommandParameter(int index)
|
||||
{
|
||||
Log.DebugFormat("GetCommandType: called. index = {0}", index);
|
||||
|
||||
var command = _commandTask?.Command;
|
||||
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
|
||||
{
|
||||
return command.Parameters[index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
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 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 +112,7 @@ namespace MTApiService
|
||||
}
|
||||
}
|
||||
|
||||
public int Handle { get; private set; }
|
||||
public int Handle { get; }
|
||||
|
||||
private bool _isEnable = true;
|
||||
public bool IsEnable
|
||||
@@ -69,73 +153,21 @@ namespace MTApiService
|
||||
|
||||
#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()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
SendTickToMetaTrader();
|
||||
|
||||
Log.Debug("NotifyCommandReady: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void SendTickToMetaTrader()
|
||||
{
|
||||
if (_mtHadler != null)
|
||||
{
|
||||
_mtHadler.SendTickToMetaTrader(Handle);
|
||||
}
|
||||
_mtHadler.SendTickToMetaTrader(Handle);
|
||||
}
|
||||
|
||||
private void FireOnQuoteChanged(MtQuote quote)
|
||||
@@ -165,12 +197,5 @@ namespace MTApiService
|
||||
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();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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,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,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,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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -21,6 +20,8 @@ namespace MTApiService
|
||||
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
|
||||
typeof(MtResponseMqlBookInfoArray)};
|
||||
}
|
||||
|
||||
public abstract object GetValue();
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -33,6 +34,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 +53,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 +72,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 +91,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 +110,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 +129,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 +148,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 +167,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 +186,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 +205,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 +224,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 +243,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 +262,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public MtMqlBookInfo[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+197
-107
@@ -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 MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
|
||||
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.AddCommandExecutor(expert);
|
||||
|
||||
_service.OnQuoteAdded(expert.Quote);
|
||||
|
||||
Log.Debug("AddExpert: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -126,25 +162,30 @@ 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 = new MtCommandTask(command);
|
||||
_executorManager.EnqueueCommandTask(task);
|
||||
|
||||
//wait for execute command in MetaTrader
|
||||
var response = task.WaitResult(WaitResponseTime);
|
||||
|
||||
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 +194,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 +327,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,20 +348,27 @@ 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);
|
||||
@@ -299,19 +382,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)
|
||||
{
|
||||
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event);
|
||||
|
||||
_service.OnMtEvent(e.Event);
|
||||
|
||||
Log.Debug("Expert_OnMtEvent: end.");
|
||||
}
|
||||
|
||||
private void FireOnStopped()
|
||||
@@ -328,16 +421,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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class MtServerInstance
|
||||
{
|
||||
#region Init_Instance
|
||||
#region Fields
|
||||
private const string LogProfileName = "MtApiService";
|
||||
|
||||
static readonly MtServerInstance mInstance = new MtServerInstance();
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
|
||||
private static readonly MtServerInstance Instance = new MtServerInstance();
|
||||
|
||||
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 MtServerInstance()
|
||||
{
|
||||
{
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
}
|
||||
|
||||
static MtServerInstance()
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
public static MtServerInstance GetInstance()
|
||||
{
|
||||
return mInstance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -33,20 +38,23 @@ namespace MTApiService
|
||||
#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);
|
||||
if (mtHandler == null)
|
||||
throw new ArgumentNullException(nameof(mtHandler));
|
||||
|
||||
MtServer server = null;
|
||||
lock (mServersDictionary)
|
||||
Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
|
||||
|
||||
MtServer server;
|
||||
lock (_servers)
|
||||
{
|
||||
if (mServersDictionary.ContainsKey(port))
|
||||
if (_servers.ContainsKey(port))
|
||||
{
|
||||
server = mServersDictionary[port];
|
||||
server = _servers[port];
|
||||
}
|
||||
else
|
||||
{
|
||||
server = new MtServer(port);
|
||||
server.Stopped += new EventHandler(server_Stopped);
|
||||
mServersDictionary[port] = server;
|
||||
server.Stopped += server_Stopped;
|
||||
_servers[port] = server;
|
||||
|
||||
server.Start();
|
||||
}
|
||||
@@ -54,137 +62,172 @@ namespace MTApiService
|
||||
|
||||
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
|
||||
|
||||
lock (mExpertsDictionary)
|
||||
lock (_experts)
|
||||
{
|
||||
mExpertsDictionary[expert.Handle] = expert;
|
||||
_experts[expert.Handle] = expert;
|
||||
}
|
||||
|
||||
server.AddExpert(expert);
|
||||
|
||||
Log.Info("InitExpert: end");
|
||||
}
|
||||
|
||||
public void DeinitExpert(int expertHandle)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::DeinitExpert: expertHandle = {0}", expertHandle);
|
||||
Log.InfoFormat("DeinitExpert: begin. expertHandle = {0}", expertHandle);
|
||||
|
||||
MtExpert expert = null;
|
||||
|
||||
lock (mExpertsDictionary)
|
||||
lock (_experts)
|
||||
{
|
||||
if (mExpertsDictionary.ContainsKey(expertHandle) == true)
|
||||
if (_experts.ContainsKey(expertHandle))
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
mExpertsDictionary.Remove(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)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendQuote: enter. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
|
||||
Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.Quote = new MtQuote(symbol, bid, ask);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendQuote: finish.");
|
||||
Log.Debug("SendQuote: end");
|
||||
}
|
||||
|
||||
public void SendEvent(int expertHandle, int eventType, string payload)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload);
|
||||
Log.DebugFormat("SendEvent: begin. eventType = {0}, payload = {1}", eventType, payload);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.SendEvent(new MtEvent(eventType, payload));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendEvent: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendEvent: finished");
|
||||
Log.Debug("SendEvent: end");
|
||||
}
|
||||
|
||||
public void SendResponse(int expertHandle, MtResponse response)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response);
|
||||
Log.DebugFormat("SendResponse: begin. id = {0}, response = {1}", expertHandle, response);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.SendResponse(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendResponse: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendResponse: finish");
|
||||
Log.Debug("SendResponse: end");
|
||||
}
|
||||
|
||||
public int GetCommandType(int expertHandle)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::GetCommandType: expertHandle = {0}", expertHandle);
|
||||
Log.DebugFormat("GetCommandType: begin. expertHandle = {0}", expertHandle);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
return (expert != null) ? expert.GetCommandType() : 0;
|
||||
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)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::GetCommandParameter: expertHandle = {0}, index = {1}", expertHandle, index);
|
||||
Log.DebugFormat("GetCommandParameter: begin. expertHandle = {0}, index = {1}", expertHandle, index);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
return (expert != null) ? expert.GetCommandParameter(index) : null;
|
||||
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;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void server_Stopped(object sender, EventArgs e)
|
||||
{
|
||||
MtServer server = (MtServer)sender;
|
||||
var server = (MtServer)sender;
|
||||
server.Stopped -= server_Stopped;
|
||||
|
||||
var port = server.Port;
|
||||
lock (mServersDictionary)
|
||||
|
||||
Log.InfoFormat("server_Stopped: port = {0}", port);
|
||||
|
||||
lock (_servers)
|
||||
{
|
||||
if (mServersDictionary.ContainsKey(port))
|
||||
if (_servers.ContainsKey(port))
|
||||
{
|
||||
mServersDictionary.Remove(port);
|
||||
_servers.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
|
||||
}
|
||||
}
|
||||
|
||||
+96
-45
@@ -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 definded.");
|
||||
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.Debug("QuoteUpdate: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
|
||||
|
||||
Log.Debug("QuoteUpdate: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteAdded(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteAdded: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
|
||||
|
||||
Log.Debug("OnQuoteAdded: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteRemoved(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteRemoved: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
|
||||
|
||||
Log.Debug("OnQuoteRemoved: end.");
|
||||
}
|
||||
|
||||
public void OnMtEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.Debug("OnMtEvent: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.24.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.24.0")]
|
||||
|
||||
Executable
+6
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+183
-169
@@ -19,56 +19,56 @@ using namespace System::Diagnostics;
|
||||
|
||||
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();
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,185 +89,199 @@ int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_
|
||||
|
||||
int _stdcall sendIntResponse(int expertHandle, int response)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + 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] MTConnector:sendBooleanResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:sendDoubleResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:sendStringResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendVoidResponse(int expertHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:sendDoubleArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:sendIntArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + 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] MTConnector:sendLongResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getCommandType(int expertHandle, int* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:getIntValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:getDoubleValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector: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] MTConnector:getStringValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + 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;
|
||||
}
|
||||
+14
-13
@@ -3,16 +3,17 @@ LIBRARY MTConnector
|
||||
EXPORTS initExpert
|
||||
deinitExpert
|
||||
updateQuote
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
getBooleanValue
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
sendLongResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
getBooleanValue
|
||||
+37
-1
@@ -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
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
namespace MtApi
|
||||
{
|
||||
public enum EnumSeriesInfoInteger
|
||||
{
|
||||
SERIES_BARS_COUNT = 0,
|
||||
SERIES_FIRSTDATE = 1,
|
||||
SERIES_LASTBAR_DATE = 5,
|
||||
SERIES_SERVER_FIRSTDATE = 2
|
||||
}
|
||||
}
|
||||
Executable
+46
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -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
|
||||
}
|
||||
}
|
||||
Executable
+27
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public enum MarketInfoModeType
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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; }
|
||||
|
||||
Executable
+14
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -59,9 +59,15 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChartPeriod.cs" />
|
||||
<Compile Include="EnumSeriesInfoInteger.cs" />
|
||||
<Compile Include="EnumSymbolInfoDouble.cs" />
|
||||
<Compile Include="EnumSymbolInfoInteger.cs" />
|
||||
<Compile Include="EnumTerminalInfoDouble.cs" />
|
||||
<Compile Include="EnumTerminalInfoInteger.cs" />
|
||||
<Compile Include="ExtensionMethods.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 +78,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 +97,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" />
|
||||
|
||||
+484
-228
File diff suppressed because it is too large
Load Diff
+11
-10
@@ -58,9 +58,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 +97,6 @@ namespace MtApi
|
||||
SendMail = 66,
|
||||
Sleep = 67,
|
||||
|
||||
//Client Terminal
|
||||
TerminalCompany = 68,
|
||||
TerminalName = 69,
|
||||
TerminalPath = 70,
|
||||
|
||||
//Date and Time
|
||||
Day = 71,
|
||||
DayOfWeek = 72,
|
||||
@@ -188,8 +189,6 @@ namespace MtApi
|
||||
//
|
||||
RefreshRates = 150,
|
||||
//
|
||||
TerminalInfoString = 153,
|
||||
SymbolInfoString = 154,
|
||||
|
||||
//Requests
|
||||
MtRequest = 155,
|
||||
@@ -197,9 +196,11 @@ namespace MtApi
|
||||
//Backtesting
|
||||
BacktestingReady = 156,
|
||||
|
||||
//Symbols
|
||||
//Market Info
|
||||
SymbolInfoString = 154,
|
||||
SymbolsTotal = 200,
|
||||
SymbolName = 201,
|
||||
SymbolSelect = 202
|
||||
SymbolSelect = 202,
|
||||
SymbolInfoInteger = 203
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+85
-84
@@ -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.
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public class MtQuote
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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.32.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.32.1")]
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Executable
+11
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Executable
+12
@@ -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; }
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
internal class SymbolInfoTickRequest: RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.SymbolInfoTick;
|
||||
|
||||
public string Symbol { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class CopyRatesResponse: ResponseBase
|
||||
internal class CopyRatesResponse: ResponseBase
|
||||
{
|
||||
public List<MqlRates> Rates { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class GetOrderResponse: ResponseBase
|
||||
internal class GetOrderResponse: ResponseBase
|
||||
{
|
||||
public MtOrder Order { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class GetOrdersResponse: ResponseBase
|
||||
internal class GetOrdersResponse: ResponseBase
|
||||
{
|
||||
public List<MtOrder> Orders { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+2
-8
@@ -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; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class OrderSendResponse: ResponseBase
|
||||
internal class OrderSendResponse: ResponseBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class ResponseBase
|
||||
internal class ResponseBase
|
||||
{
|
||||
public int ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SeriesInfoIntegerResponse: ResponseBase
|
||||
{
|
||||
public long Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SessionResponse : ResponseBase
|
||||
{
|
||||
public MtSession Session { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SymbolInfoDoubleResponse: ResponseBase
|
||||
{
|
||||
public double Value { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SymbolInfoTickResponse: ResponseBase
|
||||
{
|
||||
public MqlTick Tick { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public enum TradeOperation
|
||||
{
|
||||
|
||||
Executable
+9
@@ -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
|
||||
}
|
||||
}
|
||||
Executable
+188
@@ -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
|
||||
}
|
||||
}
|
||||
Executable
+15
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
static class ExtensionMethods
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
#region Event Methods
|
||||
public static void FireEvent(this EventHandler eventHandler, object sender)
|
||||
{
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(sender, EventArgs.Empty);
|
||||
}
|
||||
eventHandler?.Invoke(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);
|
||||
}
|
||||
eventHandler?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
+12
-11
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -9,17 +6,24 @@ namespace MtApi5
|
||||
{
|
||||
public MqlTick(DateTime time, double bid, double ask, double last, ulong volume)
|
||||
{
|
||||
this.time = time;
|
||||
MtTime = Mt5TimeConverter.ConvertToMtTime(time);
|
||||
this.bid = bid;
|
||||
this.ask = ask;
|
||||
this.last = last;
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
public DateTime time { get; private set; } // Time of the last prices update
|
||||
public double bid { get; private set; } // Current Bid price
|
||||
public double ask { get; private set; } // Current Ask price
|
||||
public double last { get; private set; } // Price of the last deal (Last)
|
||||
public ulong volume { get; private set; } // Volume for the current Last price
|
||||
public MqlTick()
|
||||
{
|
||||
}
|
||||
|
||||
public long MtTime { get; set; } // Time of the last prices update
|
||||
|
||||
public double bid { get; set; } // Current Bid price
|
||||
public double ask { get; set; } // Current Ask price
|
||||
public double last { get; set; } // Price of the last deal (Last)
|
||||
public ulong volume { get; set; } // Volume for the current Last price
|
||||
|
||||
public DateTime time => Mt5TimeConverter.ConvertFromMtTime(MtTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -8,7 +6,7 @@ namespace MtApi5
|
||||
{
|
||||
public ENUM_TRADE_REQUEST_ACTIONS Action { get; set; } // Trade operation type
|
||||
public uint Magic { get; set; } // Expert Advisor ID (magic number)
|
||||
public uint Order { get; set; } // Order ticket
|
||||
public ulong Order { get; set; } // Order ticket
|
||||
public string Symbol { get; set; } // Trade symbol
|
||||
public double Volume { get; set; } // Requested volume for a deal in lots
|
||||
public double Price { get; set; } // Price
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
enum Mt5CommandType
|
||||
internal enum Mt5CommandType
|
||||
{
|
||||
//NoCommand = 0
|
||||
|
||||
@@ -101,6 +101,18 @@ namespace MtApi5
|
||||
MarketBookRelease = 61,
|
||||
MarketBookGet = 62,
|
||||
OrderCloseAll = 63,
|
||||
PositionClose = 64
|
||||
|
||||
//CTrade
|
||||
PositionClose = 64,
|
||||
PositionOpen = 65,
|
||||
|
||||
//Backtesting
|
||||
BacktestingReady = 66,
|
||||
IsTesting = 67,
|
||||
|
||||
Print = 68,
|
||||
|
||||
//Requests
|
||||
MtRequest = 155,
|
||||
}
|
||||
}
|
||||
+17
-1
@@ -32,9 +32,14 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@@ -42,6 +47,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CopyTicksFlag.cs" />
|
||||
<Compile Include="MqlBookInfo.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
<Compile Include="MqlTick.cs" />
|
||||
@@ -55,10 +61,17 @@
|
||||
<Compile Include="MqlTradeResult.cs" />
|
||||
<Compile Include="Mt5QuoteEventArgs.cs" />
|
||||
<Compile Include="MtApi5Client.cs" />
|
||||
<Compile Include="MtCommandType.cs" />
|
||||
<Compile Include="Mt5CommandType.cs" />
|
||||
<Compile Include="MtConverters.cs" />
|
||||
<Compile Include="ErrorCode.cs" />
|
||||
<Compile Include="ExecutionException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Mt5Quote.cs" />
|
||||
<Compile Include="Requests\CopyTicksRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\RequestType.cs" />
|
||||
<Compile Include="Responses\CopyTicksResponse.cs" />
|
||||
<Compile Include="Responses\ResponseBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
|
||||
@@ -66,6 +79,9 @@
|
||||
<Name>MTApiService</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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.
|
||||
|
||||
+590
-489
File diff suppressed because it is too large
Load Diff
+30
-33
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MTApiService;
|
||||
using System.Collections;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
static class MtConverters
|
||||
internal static class MtConverters
|
||||
{
|
||||
#region Values Converters
|
||||
public static Mt5Quote Parse(this MtQuote quote)
|
||||
@@ -17,29 +14,29 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out MqlTradeResult result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = null;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
uint retcode = uint.Parse(values[1]);
|
||||
ulong deal = ulong.Parse(values[2]);
|
||||
ulong order = ulong.Parse(values[3]);
|
||||
double volume = double.Parse(values[4]);
|
||||
double price = double.Parse(values[5]);
|
||||
double bid = double.Parse(values[6]);
|
||||
double ask = double.Parse(values[7]);
|
||||
string comment = values[8];
|
||||
uint request_id = uint.Parse(values[9]);
|
||||
var retcode = uint.Parse(values[1]);
|
||||
var deal = ulong.Parse(values[2]);
|
||||
var order = ulong.Parse(values[3]);
|
||||
var volume = double.Parse(values[4]);
|
||||
var price = double.Parse(values[5]);
|
||||
var bid = double.Parse(values[6]);
|
||||
var ask = double.Parse(values[7]);
|
||||
var comment = values[8];
|
||||
var requestId = uint.Parse(values[9]);
|
||||
|
||||
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, request_id);
|
||||
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, requestId);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -52,28 +49,28 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out MqlTradeCheckResult result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = null;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
uint retcode = uint.Parse(values[1]);
|
||||
double balance = double.Parse(values[2]);
|
||||
double equity = double.Parse(values[3]);
|
||||
double profit = double.Parse(values[4]);
|
||||
double margin = double.Parse(values[5]);
|
||||
double margin_free = double.Parse(values[6]);
|
||||
double margin_level = double.Parse(values[7]);
|
||||
string comment = values[8];
|
||||
var retcode = uint.Parse(values[1]);
|
||||
var balance = double.Parse(values[2]);
|
||||
var equity = double.Parse(values[3]);
|
||||
var profit = double.Parse(values[4]);
|
||||
var margin = double.Parse(values[5]);
|
||||
var marginFree = double.Parse(values[6]);
|
||||
var marginLevel = double.Parse(values[7]);
|
||||
var comment = values[8];
|
||||
|
||||
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, margin_free, margin_level, comment);
|
||||
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, marginFree, marginLevel, comment);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -87,7 +84,7 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out double result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = 0;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
@@ -113,24 +110,24 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out DateTime from, out DateTime to)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
|
||||
from = new DateTime();
|
||||
to = new DateTime();
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
int iFrom = int.Parse(values[1]);
|
||||
var iFrom = int.Parse(values[1]);
|
||||
from = Mt5TimeConverter.ConvertFromMtTime(iFrom);
|
||||
|
||||
int iTo= int.Parse(values[2]);
|
||||
var iTo= int.Parse(values[2]);
|
||||
to = Mt5TimeConverter.ConvertFromMtTime(iTo);
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -148,7 +145,7 @@ namespace MtApi5
|
||||
if (request == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
int exp = Mt5TimeConverter.ConvertToMtTime(request.Expiration);
|
||||
var exp = Mt5TimeConverter.ConvertToMtTime(request.Expiration);
|
||||
|
||||
return new ArrayList { (int)request.Action, request.Magic, request.Order, request.Symbol, request.Volume
|
||||
, request.Price, request.Stoplimit, request.Sl, request.Tp, request.Deviation, (int)request.Type
|
||||
|
||||
@@ -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.9.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.9.0")]
|
||||
[assembly: AssemblyVersion("1.0.11.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.11.1")]
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class CopyTicksRequest: RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.CopyTicks;
|
||||
|
||||
public string SymbolName { get; set; }
|
||||
public int Flags { get; set; }
|
||||
public ulong From { get; set; }
|
||||
public uint Count { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal abstract class RequestBase
|
||||
{
|
||||
public abstract RequestType RequestType { get; }
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal enum RequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
CopyTicks = 1
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MtApi5.Responses
|
||||
{
|
||||
internal class CopyTicksResponse: ResponseBase
|
||||
{
|
||||
public List<MqlTick> Ticks { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
namespace MtApi5.Responses
|
||||
{
|
||||
internal class ResponseBase
|
||||
{
|
||||
public int ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net40" />
|
||||
</packages>
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define MsiSourceFileName="MtApi5Installer_x64.msi"?>
|
||||
<?define VcRedistFileName="vc_redist.x64.exe"?>
|
||||
<?else ?>
|
||||
<?define MsiSourceFileName="MtApi5Installer_x86.msi"?>
|
||||
<?define VcRedistFileName="vc_redist.x86.exe"?>
|
||||
<?endif ?>
|
||||
|
||||
<?define ProductName="!(bind.packageName.MtApi5Msi)" ?>
|
||||
<?define ProductVersion="!(bind.packageVersion.MtApi5Msi)" ?>
|
||||
<?define Manufacturer="!(bind.packageManufacturer.MtApi5Msi)" ?>
|
||||
|
||||
<Bundle Name="$(var.ProductName) Bootstrapper"
|
||||
Version="$(var.ProductVersion)"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="1497e285-c228-490b-9638-565e118548fb">
|
||||
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication LicenseFile="..\LICENSE.rtf"/>
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<Chain>
|
||||
|
||||
<ExePackage SourceFile="..\vcredist\$(var.VcRedistFileName)"
|
||||
Name="Redist\$(var.VcRedistFileName)"
|
||||
Cache="no"
|
||||
Compressed="yes"
|
||||
InstallCommand="/install /quiet /norestart">
|
||||
<!-- Ignore "Newer version installed" error -->
|
||||
<ExitCode Value="1638" Behavior="success"/>
|
||||
</ExePackage>
|
||||
|
||||
<MsiPackage Id="MtApi5Msi"
|
||||
SourceFile="..\build\installers\$(var.Configuration)\$(var.MsiSourceFileName)"
|
||||
Visible="yes"
|
||||
DisplayInternalUI="yes" />
|
||||
|
||||
</Chain>
|
||||
</Bundle>
|
||||
</Wix>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>1497e285-c228-490b-9638-565e118548fb</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApi5_Setup_$(Platform)</OutputName>
|
||||
<OutputType>Bundle</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Bundle.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixBalExtension">
|
||||
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
|
||||
<Name>WixBalExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Wix.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -6,7 +6,7 @@
|
||||
<ProductVersion>3.6</ProductVersion>
|
||||
<ProjectGuid>{a9ed070f-ab4d-4380-9dde-5d931ac71333}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApi5Installer</OutputName>
|
||||
<OutputName>MtApi5Installer_$(Platform)</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
@@ -22,11 +22,11 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
|
||||
<OutputPath>..\build\installers\$(Configuration)</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?define ProductName="MtApi5" ?>
|
||||
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define ProductName="MtApi5_x64" ?>
|
||||
<?define ProductPathNative="..\build\products\$(var.Configuration)\x64\"?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||||
<?define PlatformSystemFolder = "System64Folder" ?>
|
||||
<?else ?>
|
||||
<?define ProductName="MtApi5" ?>
|
||||
<?define ProductPathNative="..\build\products\$(var.Configuration)\"?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||||
<?define PlatformSystemFolder = "SystemFolder" ?>
|
||||
<?endif ?>
|
||||
|
||||
<?define ProductVersion="1.0.9" ?>
|
||||
<?define ProductVersion=!(bind.FileVersion.MtApi5.dll) ?>
|
||||
<?define Manufacturer="DW"?>
|
||||
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
|
||||
|
||||
<Product Id="*"
|
||||
<Product Id="*"
|
||||
Name="$(var.ProductName) $(var.ProductVersion)"
|
||||
Language="1033"
|
||||
Version="$(var.ProductVersion)"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="d72d346e-e6f7-4c23-85c6-1c42b3175599">
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<WixVariable Id="WixUILicenseRtf" Value="..\LICENSE.rtf" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Feature Id="MtApi5" Title="$(var.ProductName)" Level="1">
|
||||
@@ -37,7 +39,7 @@
|
||||
|
||||
<Property Id="WIXUI_INSTALLDIR">INSTALLFOLDER</Property>
|
||||
<UIRef Id="WixUI_Mondo" />
|
||||
</Product>
|
||||
</Product>
|
||||
|
||||
<Fragment>
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
@@ -78,6 +80,11 @@
|
||||
</RegistryKey>
|
||||
|
||||
</Component>
|
||||
|
||||
<Component Id="NewtonsoftJsondll" Directory="INSTALLFOLDER">
|
||||
<File Id="Newtonsoft.Json.dll" Name="Newtonsoft.Json.dll" KeyPath="yes"
|
||||
src="$(var.ProductPath)Newtonsoft.Json.dll"/>
|
||||
</Component>
|
||||
|
||||
<Component Id="MTApiServiceDll" Directory="INSTALLFOLDER">
|
||||
<File Id="GAC_MTApiService.dll" Name="MTApiService.dll" KeyPath="yes"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user