mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 02:57:56 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| db4bb44fb3 | |||
| 68d5fa98af | |||
| dc28823ca9 |
+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
+55
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
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")}.{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);
|
||||
|
||||
var memory = new MemoryAppender();
|
||||
memory.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(memory);
|
||||
|
||||
#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.22.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.22.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);
|
||||
}
|
||||
|
||||
|
||||
+187
-158
@@ -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,170 +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;
|
||||
}
|
||||
+14
-12
@@ -3,15 +3,17 @@ LIBRARY MTConnector
|
||||
EXPORTS initExpert
|
||||
deinitExpert
|
||||
updateQuote
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
sendLongResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
getBooleanValue
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChartPeriod.cs" />
|
||||
<Compile Include="EnumSymbolInfoInteger.cs" />
|
||||
<Compile Include="ExtensionMethods.cs" />
|
||||
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
@@ -72,6 +73,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,6 +92,7 @@
|
||||
<Compile Include="Requests\OrderDeleteRequest.cs" />
|
||||
<Compile Include="Requests\OrderModifyRequest.cs" />
|
||||
<Compile Include="Requests\OrderSendRequest.cs" />
|
||||
<Compile Include="Requests\SessionRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\RequestType.cs" />
|
||||
<Compile Include="Responses\CopyRatesResponse.cs" />
|
||||
@@ -97,6 +100,7 @@
|
||||
<Compile Include="Responses\GetOrdersResponse.cs" />
|
||||
<Compile Include="Responses\ICustomResponse.cs" />
|
||||
<Compile Include="Responses\OrderSendResponse.cs" />
|
||||
<Compile Include="Responses\SessionResponse.cs" />
|
||||
<Compile Include="Responses\ResponseBase.cs" />
|
||||
<Compile Include="SeriesIdentifier.cs" />
|
||||
<Compile Include="TimeBarArgs.cs" />
|
||||
|
||||
+241
-181
@@ -15,25 +15,34 @@ namespace MtApi
|
||||
|
||||
public sealed class MtApiClient
|
||||
{
|
||||
private const int DoubleArrayLimit = 64800;
|
||||
private volatile bool IsBacktestingMode = false;
|
||||
private volatile bool _isBacktestingMode;
|
||||
|
||||
#region MetaTrader Constants
|
||||
|
||||
//Special constant
|
||||
public const int NULL = 0;
|
||||
public const int EMPTY = -1;
|
||||
|
||||
private const string LogProfileName = "MtApiClient";
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly MtClient _client = new MtClient();
|
||||
private readonly object _locker = new object();
|
||||
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
|
||||
public MtApiClient()
|
||||
{
|
||||
_client.QuoteAdded += mClient_QuoteAdded;
|
||||
_client.QuoteRemoved += mClient_QuoteRemoved;
|
||||
_client.QuoteUpdated += mClient_QuoteUpdated;
|
||||
_client.ServerDisconnected += mClient_ServerDisconnected;
|
||||
_client.ServerFailed += mClient_ServerFailed;
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
|
||||
_client.QuoteAdded += _client_QuoteAdded;
|
||||
_client.QuoteRemoved += _client_QuoteRemoved;
|
||||
_client.QuoteUpdated += _client_QuoteUpdated;
|
||||
_client.ServerDisconnected += _client_ServerDisconnected;
|
||||
_client.ServerFailed += _client_ServerFailed;
|
||||
_client.MtEventReceived += _client_MtEventReceived;
|
||||
}
|
||||
#endregion
|
||||
@@ -46,15 +55,8 @@ namespace MtApi
|
||||
///<param name="port">Port of host connection (default 8222) </param>
|
||||
public void BeginConnect(string host, int port)
|
||||
{
|
||||
//if (string.IsNullOrEmpty(host) == false && (host.Equals("localhost") || host.Equals("127.0.0.1")))
|
||||
//{
|
||||
// this.BeginConnect(port);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
Action<string, int> connectAction = Connect;
|
||||
connectAction.BeginInvoke(host, port, null, null);
|
||||
//}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
@@ -81,12 +83,16 @@ namespace MtApi
|
||||
///</summary>
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
{
|
||||
var quotes = _client.GetQuotes();
|
||||
return quotes != null ? (from q in quotes select q.Convert()) : null;
|
||||
IEnumerable<MTApiService.MtQuote> quotes;
|
||||
lock (_client)
|
||||
{
|
||||
quotes = _client.GetQuotes();
|
||||
}
|
||||
return quotes?.Select(q => q.Convert());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
#region Properties
|
||||
|
||||
///<summary>
|
||||
///Connection status of MetaTrader API.
|
||||
@@ -174,7 +180,7 @@ namespace MtApi
|
||||
public double OrderOpenPrice(int ticket)
|
||||
{
|
||||
var commandParameters = new ArrayList { ticket };
|
||||
double retVal = SendCommand<double>(MtCommandType.OrderOpenPriceByTicket, commandParameters);
|
||||
var retVal = SendCommand<double>(MtCommandType.OrderOpenPriceByTicket, commandParameters);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
@@ -219,7 +225,7 @@ namespace MtApi
|
||||
[Obsolete("OrderType is deprecated, please use GetOrder instead.")]
|
||||
public TradeOperation OrderType()
|
||||
{
|
||||
int retVal = SendCommand<int>(MtCommandType.OrderType, null);
|
||||
var retVal = SendCommand<int>(MtCommandType.OrderType, null);
|
||||
|
||||
return (TradeOperation)retVal;
|
||||
}
|
||||
@@ -250,7 +256,7 @@ namespace MtApi
|
||||
Expiration = MtApiTimeConverter.ConvertToMtTime(expiration),
|
||||
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrowColor)
|
||||
});
|
||||
return response != null ? response.Ticket : -1;
|
||||
return response?.Ticket ?? -1;
|
||||
}
|
||||
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
|
||||
@@ -278,7 +284,7 @@ namespace MtApi
|
||||
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, string price, int slippage, double stoploss, double takeprofit)
|
||||
{
|
||||
double dPrice = 0;
|
||||
double dPrice;
|
||||
return double.TryParse(price, out dPrice) ?
|
||||
OrderSend(symbol, cmd, volume, dPrice, slippage, stoploss, takeprofit, null, 0, DateTime.MinValue, Color.Empty) : 0;
|
||||
}
|
||||
@@ -316,7 +322,7 @@ namespace MtApi
|
||||
Comment = comment,
|
||||
Magic = magic,
|
||||
});
|
||||
return response != null ? response.Ticket : -1;
|
||||
return response?.Ticket ?? -1;
|
||||
}
|
||||
|
||||
public int OrderSendSell(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic)
|
||||
@@ -332,7 +338,7 @@ namespace MtApi
|
||||
Comment = comment,
|
||||
Magic = magic,
|
||||
});
|
||||
return response != null ? response.Ticket : -1;
|
||||
return response?.Ticket ?? -1;
|
||||
}
|
||||
|
||||
public bool OrderClose(int ticket, double lots, double price, int slippage, Color color)
|
||||
@@ -421,7 +427,7 @@ namespace MtApi
|
||||
return response != null;
|
||||
}
|
||||
|
||||
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration, Color arrow_color)
|
||||
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration, Color arrowColor)
|
||||
{
|
||||
var response = SendRequest<ResponseBase>(new OrderModifyRequest
|
||||
{
|
||||
@@ -430,7 +436,7 @@ namespace MtApi
|
||||
Stoploss = stoploss,
|
||||
Takeprofit = takeprofit,
|
||||
Expiration = MtApiTimeConverter.ConvertToMtTime(expiration),
|
||||
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrow_color)
|
||||
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrowColor)
|
||||
});
|
||||
return response != null;
|
||||
}
|
||||
@@ -482,7 +488,7 @@ namespace MtApi
|
||||
public MtOrder GetOrder(int index, OrderSelectMode select, OrderSelectSource pool)
|
||||
{
|
||||
var response = SendRequest<GetOrderResponse>(new GetOrderRequest { Index = index, Select = (int) select, Pool = (int) pool});
|
||||
return response != null ? response.Order : null;
|
||||
return response?.Order;
|
||||
}
|
||||
|
||||
public List<MtOrder> GetOrders(OrderSelectSource pool)
|
||||
@@ -652,6 +658,63 @@ namespace MtApi
|
||||
|
||||
#endregion
|
||||
|
||||
#region Symbols
|
||||
///<summary>
|
||||
///Returns the number of available (selected in Market Watch or all) symbols.
|
||||
///</summary>
|
||||
///<param name="selected">Request mode. Can be true or false.</param>
|
||||
///<returns>
|
||||
///If the 'selected' parameter is true, the function returns the number of symbols selected in MarketWatch. If the value is false, it returns the total number of all symbols.
|
||||
///</returns>
|
||||
public int SymbolsTotal(bool selected)
|
||||
{
|
||||
var commandParameters = new ArrayList { selected };
|
||||
return SendCommand<int>(MtCommandType.SymbolsTotal, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the name of a symbol.
|
||||
///</summary>
|
||||
///<param name="pos">Order number of a symbol.</param>
|
||||
///<param name="selected">Request mode. If the value is true, the symbol is taken from the list of symbols selected in MarketWatch. If the value is false, the symbol is taken from the general list.</param>
|
||||
///<returns>
|
||||
///Value of string type with the symbol name.
|
||||
///</returns>
|
||||
public string SymbolName(int pos, bool selected)
|
||||
{
|
||||
var commandParameters = new ArrayList { pos, selected };
|
||||
return SendCommand<string>(MtCommandType.SymbolName, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Selects a symbol in the Market Watch window or removes a symbol from the window.
|
||||
///</summary>
|
||||
///<param name="name">Symbol name</param>
|
||||
///<param name="select">Switch. If the value is false, a symbol should be removed from MarketWatch, otherwise a symbol should be selected in this window. A symbol can't be removed if the symbol chart is open, or there are open orders for this symbol.</param>
|
||||
///<returns>
|
||||
///In case of failure returns false.
|
||||
///</returns>
|
||||
public bool SymbolSelect(string name, bool select)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, select };
|
||||
return SendCommand<bool>(MtCommandType.SymbolSelect, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the corresponding property of a specified symbol.
|
||||
///</summary>
|
||||
///<param name="name">Symbol name</param>
|
||||
///<param name="propId">Identifier of a symbol property. The value can be one of the values of the EnumSymbolInfoInteger enumeration</param>
|
||||
///<returns>
|
||||
///The value of long type.
|
||||
///</returns>
|
||||
public long SymbolInfoInteger(string name, EnumSymbolInfoInteger propId)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, (int)propId };
|
||||
return SendCommand<long>(MtCommandType.SymbolInfoInteger, commandParameters);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Common Function
|
||||
|
||||
public void Alert(string msg)
|
||||
@@ -712,15 +775,15 @@ namespace MtApi
|
||||
return SendCommand<bool>(MtCommandType.SendFTP, commandParameters);
|
||||
}
|
||||
|
||||
public bool SendFTP(string filename, string ftp_path)
|
||||
public bool SendFTP(string filename, string ftpPath)
|
||||
{
|
||||
var commandParameters = new ArrayList { filename, ftp_path };
|
||||
var commandParameters = new ArrayList { filename, ftpPath };
|
||||
return SendCommand<bool>(MtCommandType.SendFTPA, commandParameters);
|
||||
}
|
||||
|
||||
public void SendMail(string subject, string some_text)
|
||||
public void SendMail(string subject, string someText)
|
||||
{
|
||||
var commandParameters = new ArrayList { subject, some_text };
|
||||
var commandParameters = new ArrayList { subject, someText };
|
||||
SendCommand<object>(MtCommandType.SendMail, commandParameters);
|
||||
}
|
||||
|
||||
@@ -888,15 +951,15 @@ namespace MtApi
|
||||
return MtApiTimeConverter.ConvertFromMtTime(commandResponse);
|
||||
}
|
||||
|
||||
public bool GlobalVariableSetOnCondition(string name, double value, double check_value)
|
||||
public bool GlobalVariableSetOnCondition(string name, double value, double checkValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, value, check_value };
|
||||
var commandParameters = new ArrayList { name, value, checkValue };
|
||||
return SendCommand<bool>(MtCommandType.GlobalVariableSetOnCondition, commandParameters);
|
||||
}
|
||||
|
||||
public int GlobalVariablesDeleteAll(string prefix_name)
|
||||
public int GlobalVariablesDeleteAll(string prefixName)
|
||||
{
|
||||
var commandParameters = new ArrayList { prefix_name };
|
||||
var commandParameters = new ArrayList { prefixName };
|
||||
return SendCommand<int>(MtCommandType.GlobalVariableSetOnCondition, commandParameters);
|
||||
}
|
||||
|
||||
@@ -920,15 +983,15 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iAD, commandParameters);
|
||||
}
|
||||
|
||||
public double iAlligator(string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift)
|
||||
public double iAlligator(string symbol, int timeframe, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, int maMethod, int appliedPrice, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, maMethod, appliedPrice, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iAlligator, commandParameters);
|
||||
}
|
||||
|
||||
public double iADX(string symbol, int timeframe, int period, int applied_price, int mode, int shift)
|
||||
public double iADX(string symbol, int timeframe, int period, int appliedPrice, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iADX, commandParameters);
|
||||
}
|
||||
|
||||
@@ -944,50 +1007,50 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iAO, commandParameters);
|
||||
}
|
||||
|
||||
public double iBearsPower(string symbol, int timeframe, int period, int applied_price, int shift)
|
||||
public double iBearsPower(string symbol, int timeframe, int period, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iBearsPower, commandParameters);
|
||||
}
|
||||
|
||||
public double iBands(string symbol, int timeframe, int period, int deviation, int bands_shift, int applied_price, int mode, int shift)
|
||||
public double iBands(string symbol, int timeframe, int period, int deviation, int bandsShift, int appliedPrice, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, deviation, bands_shift, applied_price, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, deviation, bandsShift, appliedPrice, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iBands, commandParameters);
|
||||
}
|
||||
|
||||
public double iBandsOnArray(double[] array, int total, int period, int deviation, int bands_shift, int mode, int shift)
|
||||
public double iBandsOnArray(double[] array, int total, int period, int deviation, int bandsShift, int mode, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(period);
|
||||
commandParameters.Add(deviation);
|
||||
commandParameters.Add(bands_shift);
|
||||
commandParameters.Add(bandsShift);
|
||||
commandParameters.Add(mode);
|
||||
commandParameters.Add(shift);
|
||||
|
||||
return SendCommand<double>(MtCommandType.iBandsOnArray, commandParameters);
|
||||
}
|
||||
|
||||
public double iBullsPower(string symbol, int timeframe, int period, int applied_price, int shift)
|
||||
public double iBullsPower(string symbol, int timeframe, int period, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iBullsPower, commandParameters);
|
||||
}
|
||||
|
||||
public double iCCI(string symbol, int timeframe, int period, int applied_price, int shift)
|
||||
public double iCCI(string symbol, int timeframe, int period, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iCCI, commandParameters);
|
||||
}
|
||||
|
||||
public double iCCIOnArray(double[] array, int total, int period, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] { });
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(period);
|
||||
commandParameters.Add(shift);
|
||||
@@ -1007,7 +1070,7 @@ namespace MtApi
|
||||
Params = new ArrayList(parameters),
|
||||
ParamsType = ICustomRequest.ParametersType.Int
|
||||
});
|
||||
return response != null ? response.Value : double.NaN;
|
||||
return response?.Value ?? double.NaN;
|
||||
}
|
||||
|
||||
public double iCustom(string symbol, int timeframe, string name, double[] parameters, int mode, int shift)
|
||||
@@ -1022,7 +1085,7 @@ namespace MtApi
|
||||
Params = new ArrayList(parameters),
|
||||
ParamsType = ICustomRequest.ParametersType.Double
|
||||
});
|
||||
return response != null ? response.Value : double.NaN;
|
||||
return response?.Value ?? double.NaN;
|
||||
}
|
||||
|
||||
public double iCustom(string symbol, int timeframe, string name, int mode, int shift)
|
||||
@@ -1035,7 +1098,7 @@ namespace MtApi
|
||||
Mode = mode,
|
||||
Shift = shift
|
||||
});
|
||||
return response != null ? response.Value : double.NaN;
|
||||
return response?.Value ?? double.NaN;
|
||||
}
|
||||
|
||||
public double iDeMarker(string symbol, int timeframe, int period, int shift)
|
||||
@@ -1044,21 +1107,21 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iDeMarker, commandParameters);
|
||||
}
|
||||
|
||||
public double iEnvelopes(string symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift)
|
||||
public double iEnvelopes(string symbol, int timeframe, int maPeriod, int maMethod, int maShift, int appliedPrice, double deviation, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, maPeriod, maMethod, maShift, appliedPrice, deviation, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iEnvelopes, commandParameters);
|
||||
}
|
||||
|
||||
public double iEnvelopesOnArray(double[] array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift)
|
||||
public double iEnvelopesOnArray(double[] array, int total, int maPeriod, int maMethod, int maShift, double deviation, int mode, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(ma_period);
|
||||
commandParameters.Add(ma_method);
|
||||
commandParameters.Add(ma_shift);
|
||||
commandParameters.Add(maPeriod);
|
||||
commandParameters.Add(maMethod);
|
||||
commandParameters.Add(maShift);
|
||||
commandParameters.Add(deviation);
|
||||
commandParameters.Add(mode);
|
||||
commandParameters.Add(shift);
|
||||
@@ -1066,9 +1129,9 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iEnvelopesOnArray, commandParameters);
|
||||
}
|
||||
|
||||
public double iForce(string symbol, int timeframe, int period, int ma_method, int applied_price, int shift)
|
||||
public double iForce(string symbol, int timeframe, int period, int maMethod, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, ma_method, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, maMethod, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iForce, commandParameters);
|
||||
}
|
||||
|
||||
@@ -1078,15 +1141,15 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iFractals, commandParameters);
|
||||
}
|
||||
|
||||
public double iGator(string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift)
|
||||
public double iGator(string symbol, int timeframe, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, int maMethod, int appliedPrice, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, maMethod, appliedPrice, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iGator, commandParameters);
|
||||
}
|
||||
|
||||
public double iIchimoku(string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift)
|
||||
public double iIchimoku(string symbol, int timeframe, int tenkanSen, int kijunSen, int senkouSpanB, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, tenkanSen, kijunSen, senkouSpanB, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iIchimoku, commandParameters);
|
||||
}
|
||||
|
||||
@@ -1096,17 +1159,17 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iBWMFI, commandParameters);
|
||||
}
|
||||
|
||||
public double iMomentum(string symbol, int timeframe, int period, int applied_price, int shift)
|
||||
public double iMomentum(string symbol, int timeframe, int period, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iMomentum, commandParameters);
|
||||
}
|
||||
|
||||
public double iMomentumOnArray(double[] array, int total, int period, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(period);
|
||||
commandParameters.Add(shift);
|
||||
@@ -1120,41 +1183,41 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iMFI, commandParameters);
|
||||
}
|
||||
|
||||
public double iMA(string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price, int shift)
|
||||
public double iMA(string symbol, int timeframe, int period, int maShift, int maMethod, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, ma_shift, ma_method, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, maShift, maMethod, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iMA, commandParameters);
|
||||
}
|
||||
|
||||
double iMAOnArray(double[] array, int total, int period, int ma_shift, int ma_method, int shift)
|
||||
public double iMAOnArray(double[] array, int total, int period, int maShift, int maMethod, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(period);
|
||||
commandParameters.Add(ma_shift);
|
||||
commandParameters.Add(ma_method);
|
||||
commandParameters.Add(maShift);
|
||||
commandParameters.Add(maMethod);
|
||||
commandParameters.Add(shift);
|
||||
|
||||
return SendCommand<double>(MtCommandType.iMAOnArray, commandParameters);
|
||||
}
|
||||
|
||||
public double iOsMA(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int shift)
|
||||
public double iOsMA(string symbol, int timeframe, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, fastEmaPeriod, slowEmaPeriod, signalPeriod, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iOsMA, commandParameters);
|
||||
}
|
||||
|
||||
public double iMACD(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift)
|
||||
public double iMACD(string symbol, int timeframe, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, int appliedPrice, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, fastEmaPeriod, slowEmaPeriod, signalPeriod, appliedPrice, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iMACD, commandParameters);
|
||||
}
|
||||
|
||||
public double iOBV(string symbol, int timeframe, int applied_price, int shift)
|
||||
public double iOBV(string symbol, int timeframe, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iOBV, commandParameters);
|
||||
}
|
||||
|
||||
@@ -1164,17 +1227,17 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iSAR, commandParameters);
|
||||
}
|
||||
|
||||
public double iRSI( string symbol, int timeframe, int period, int applied_price, int shift)
|
||||
public double iRSI( string symbol, int timeframe, int period, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iRSI, commandParameters);
|
||||
}
|
||||
|
||||
public double iRSIOnArray(double[] array, int total, int period, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(period);
|
||||
commandParameters.Add(shift);
|
||||
@@ -1188,29 +1251,29 @@ namespace MtApi
|
||||
return SendCommand<double>(MtCommandType.iRVI, commandParameters);
|
||||
}
|
||||
|
||||
public double iStdDev(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)
|
||||
public double iStdDev(string symbol, int timeframe, int maPeriod, int maShift, int maMethod, int appliedPrice, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, ma_period, ma_shift, ma_method, applied_price, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, maPeriod, maShift, maMethod, appliedPrice, shift };
|
||||
return SendCommand<double>(MtCommandType.iStdDev, commandParameters);
|
||||
}
|
||||
|
||||
public double iStdDevOnArray(double[] array, int total, int ma_period, int ma_shift, int ma_method, int shift)
|
||||
public double iStdDevOnArray(double[] array, int total, int maPeriod, int maShift, int maMethod, int shift)
|
||||
{
|
||||
int arraySize = array != null ? array.Length : 0;
|
||||
var arraySize = array?.Length ?? 0;
|
||||
var commandParameters = new ArrayList { arraySize };
|
||||
commandParameters.AddRange(array);
|
||||
commandParameters.AddRange(array ?? new double[] {});
|
||||
commandParameters.Add(total);
|
||||
commandParameters.Add(ma_period);
|
||||
commandParameters.Add(ma_shift);
|
||||
commandParameters.Add(ma_method);
|
||||
commandParameters.Add(maPeriod);
|
||||
commandParameters.Add(maShift);
|
||||
commandParameters.Add(maMethod);
|
||||
commandParameters.Add(shift);
|
||||
|
||||
return SendCommand<double>(MtCommandType.iStdDevOnArray, commandParameters);
|
||||
}
|
||||
|
||||
public double iStochastic(string symbol, int timeframe, int pKperiod, int pDperiod, int slowing, int method, int price_field, int mode, int shift)
|
||||
public double iStochastic(string symbol, int timeframe, int pKperiod, int pDperiod, int slowing, int method, int priceField, int mode, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, timeframe, pKperiod, pDperiod, slowing, method, price_field, mode, shift };
|
||||
var commandParameters = new ArrayList { symbol, timeframe, pKperiod, pDperiod, slowing, method, priceField, mode, shift };
|
||||
return SendCommand<double>(MtCommandType.iStochastic, commandParameters);
|
||||
}
|
||||
|
||||
@@ -1353,7 +1416,7 @@ namespace MtApi
|
||||
{
|
||||
result = new DateTime[response.Length];
|
||||
|
||||
for(int i = 0; i < response.Length; i++)
|
||||
for(var i = 0; i < response.Length; i++)
|
||||
{
|
||||
result[i] = MtApiTimeConverter.ConvertFromMtTime(response[i]);
|
||||
}
|
||||
@@ -1367,111 +1430,121 @@ namespace MtApi
|
||||
return SendCommand<bool>(MtCommandType.RefreshRates, null);
|
||||
}
|
||||
|
||||
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, int start_pos, int count)
|
||||
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count)
|
||||
{
|
||||
var response = SendRequest<CopyRatesResponse>(new CopyRates1Request
|
||||
{
|
||||
SymbolName = symbol_name,
|
||||
SymbolName = symbolName,
|
||||
Timeframe = timeframe,
|
||||
StartPos = start_pos,
|
||||
StartPos = startPos,
|
||||
Count = count
|
||||
});
|
||||
return response != null ? response.Rates : null;
|
||||
return response?.Rates;
|
||||
}
|
||||
|
||||
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, DateTime start_time, int count)
|
||||
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count)
|
||||
{
|
||||
var response = SendRequest<CopyRatesResponse>(new CopyRates2Request
|
||||
{
|
||||
SymbolName = symbol_name,
|
||||
SymbolName = symbolName,
|
||||
Timeframe = timeframe,
|
||||
StartTime = MtApiTimeConverter.ConvertToMtTime(start_time),
|
||||
StartTime = MtApiTimeConverter.ConvertToMtTime(startTime),
|
||||
Count = count
|
||||
});
|
||||
return response != null ? response.Rates : null;
|
||||
return response?.Rates;
|
||||
}
|
||||
|
||||
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, DateTime start_time, DateTime stop_time)
|
||||
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime)
|
||||
{
|
||||
var response = SendRequest<CopyRatesResponse>(new CopyRates3Request
|
||||
{
|
||||
SymbolName = symbol_name,
|
||||
SymbolName = symbolName,
|
||||
Timeframe = timeframe,
|
||||
StartTime = MtApiTimeConverter.ConvertToMtTime(start_time),
|
||||
StopTime = MtApiTimeConverter.ConvertToMtTime(stop_time)
|
||||
StartTime = MtApiTimeConverter.ConvertToMtTime(startTime),
|
||||
StopTime = MtApiTimeConverter.ConvertToMtTime(stopTime)
|
||||
});
|
||||
return response != null ? response.Rates : null;
|
||||
}
|
||||
|
||||
private void BaBacktestingReady()
|
||||
{
|
||||
SendCommand<object>(MtCommandType.BacktestingReady, null);
|
||||
return response?.Rates;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Checkup
|
||||
public string TerminalInfoString(ENUM_TERMINAL_INFO_STRING property_id)
|
||||
public string TerminalInfoString(ENUM_TERMINAL_INFO_STRING propertyId)
|
||||
{
|
||||
var commandParameters = new ArrayList { (int)property_id };
|
||||
var commandParameters = new ArrayList { (int)propertyId };
|
||||
return SendCommand<string>(MtCommandType.TerminalInfoString, commandParameters);
|
||||
}
|
||||
|
||||
public string SymbolInfoString(string name, ENUM_SYMBOL_INFO_STRING prop_id)
|
||||
public string SymbolInfoString(string name, ENUM_SYMBOL_INFO_STRING propId)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, (int)prop_id };
|
||||
var commandParameters = new ArrayList { name, (int)propId };
|
||||
return SendCommand<string>(MtCommandType.SymbolInfoString, commandParameters); ;
|
||||
}
|
||||
|
||||
public MtSession SymbolInfoSession(string symbol, DayOfWeek dayOfWeek, uint index, SessionType type)
|
||||
{
|
||||
var responce = SendRequest<SessionResponse>(new SessionRequest { Symbol = symbol, DayOfWeek = dayOfWeek, SessionIndex = (int)index, SessionType = type });
|
||||
return responce != null ? responce.Session : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void Connect(string host, int port)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Connecting, string.Format("Connecting to {0}:{1}", host, port));
|
||||
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to {host}:{port}");
|
||||
try
|
||||
{
|
||||
_client.Open(host, port);
|
||||
_client.Connect();
|
||||
lock (_client)
|
||||
{
|
||||
_client.Open(host, port);
|
||||
_client.Connect();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, string.Format("Failed connection to {0}:{1}. {2}", host, port, e.Message));
|
||||
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to {host}:{port}. {e.Message}");
|
||||
return;
|
||||
}
|
||||
UpdateConnectionState(MtConnectionState.Connected, string.Format("Connected to {0}:{1}", host, port));
|
||||
UpdateConnectionState(MtConnectionState.Connected, $"Connected to {host}:{port}");
|
||||
OnConnected();
|
||||
}
|
||||
|
||||
private void Connect(int port)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Connecting, string.Format("Connecting to 'localhost':{0}", port));
|
||||
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to 'localhost':{port}");
|
||||
try
|
||||
{
|
||||
_client.Open(port);
|
||||
_client.Connect();
|
||||
lock (_client)
|
||||
{
|
||||
_client.Open(port);
|
||||
_client.Connect();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, string.Format("Failed connection to 'localhost':{0}. {1}", port, e.Message));
|
||||
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to 'localhost':{port}. {e.Message}");
|
||||
return;
|
||||
}
|
||||
UpdateConnectionState(MtConnectionState.Connected, string.Format("Connected to 'localhost':{0}", port));
|
||||
UpdateConnectionState(MtConnectionState.Connected, $"Connected to 'localhost':{port}");
|
||||
OnConnected();
|
||||
}
|
||||
|
||||
private void OnConnected()
|
||||
{
|
||||
IsBacktestingMode = IsTesting();
|
||||
if (IsBacktestingMode)
|
||||
{
|
||||
BaBacktestingReady();
|
||||
_isBacktestingMode = IsTesting();
|
||||
if (_isBacktestingMode)
|
||||
{
|
||||
BacktestingReady();
|
||||
}
|
||||
}
|
||||
|
||||
private void Disconnect()
|
||||
{
|
||||
_client.Disconnect();
|
||||
_client.Close();
|
||||
lock (_client)
|
||||
{
|
||||
_client.Disconnect();
|
||||
_client.Close();
|
||||
}
|
||||
|
||||
UpdateConnectionState(MtConnectionState.Disconnected, "Disconnected");
|
||||
}
|
||||
@@ -1499,37 +1572,18 @@ namespace MtApi
|
||||
MtResponse response;
|
||||
try
|
||||
{
|
||||
response = _client.SendCommand((int)commandType, commandParameters);
|
||||
lock (_client)
|
||||
{
|
||||
response = _client.SendCommand((int)commandType, commandParameters);
|
||||
}
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
throw new MtConnectionException(ex.Message, ex);
|
||||
}
|
||||
|
||||
T result = default(T);
|
||||
|
||||
if (response is MtResponseDouble)
|
||||
result = (T)Convert.ChangeType(((MtResponseDouble)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseInt)
|
||||
result = (T)Convert.ChangeType(((MtResponseInt)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseBool)
|
||||
result = (T)Convert.ChangeType(((MtResponseBool)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseString)
|
||||
result = (T)Convert.ChangeType(((MtResponseString)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseDoubleArray)
|
||||
result = (T)Convert.ChangeType(((MtResponseDoubleArray)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseIntArray)
|
||||
result = (T)Convert.ChangeType(((MtResponseIntArray)response).Value, typeof(T));
|
||||
|
||||
if (response is MtResponseArrayList)
|
||||
result = (T)Convert.ChangeType(((MtResponseArrayList)response).Value, typeof(T));
|
||||
|
||||
return result;
|
||||
var responseValue = response.GetValue();
|
||||
return responseValue != null ? (T)responseValue : default(T);
|
||||
}
|
||||
|
||||
private T SendRequest<T>(RequestBase request) where T : ResponseBase, new()
|
||||
@@ -1537,17 +1591,20 @@ namespace MtApi
|
||||
if (request == null)
|
||||
return default(T);
|
||||
|
||||
var serializer = JsonConvert.SerializeObject(request, Newtonsoft.Json.Formatting.None,
|
||||
var serializer = JsonConvert.SerializeObject(request, Formatting.None,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
});
|
||||
});
|
||||
var commandParameters = new ArrayList { serializer };
|
||||
|
||||
MtResponseString res;
|
||||
try
|
||||
{
|
||||
res = (MtResponseString)_client.SendCommand((int)MtCommandType.MtRequest, commandParameters);
|
||||
lock (_client)
|
||||
{
|
||||
res = (MtResponseString)_client.SendCommand((int)MtCommandType.MtRequest, commandParameters);
|
||||
}
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
@@ -1568,44 +1625,44 @@ namespace MtApi
|
||||
return response;
|
||||
}
|
||||
|
||||
private void mClient_QuoteUpdated(MTApiService.MtQuote quote)
|
||||
private void _client_QuoteUpdated(MTApiService.MtQuote quote)
|
||||
{
|
||||
if (quote != null)
|
||||
{
|
||||
if (IsBacktestingMode)
|
||||
if (_isBacktestingMode)
|
||||
{
|
||||
QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QuoteUpdated.FireEventAsync(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mClient_ServerDisconnected(object sender, EventArgs e)
|
||||
private void _client_ServerDisconnected(object sender, EventArgs e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Disconnected, "MtApi is disconnected");
|
||||
}
|
||||
|
||||
private void mClient_ServerFailed(object sender, EventArgs e)
|
||||
private void _client_ServerFailed(object sender, EventArgs e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, "Failed connection with MtApi");
|
||||
}
|
||||
|
||||
private void mClient_QuoteRemoved(MTApiService.MtQuote quote)
|
||||
private void _client_QuoteRemoved(MTApiService.MtQuote quote)
|
||||
{
|
||||
QuoteRemoved.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
|
||||
}
|
||||
|
||||
private void mClient_QuoteAdded(MTApiService.MtQuote quote)
|
||||
private void _client_QuoteAdded(MTApiService.MtQuote quote)
|
||||
{
|
||||
QuoteAdded.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
|
||||
}
|
||||
|
||||
private void _client_MtEventReceived(object sender, MtEventArgs e)
|
||||
{
|
||||
MtEventTypes eventType = (MtEventTypes) e.Event.EventType;
|
||||
var eventType = (MtEventTypes) e.Event.EventType;
|
||||
|
||||
switch(eventType)
|
||||
{
|
||||
@@ -1614,6 +1671,8 @@ namespace MtApi
|
||||
FireOnLastTimeBar(JsonConvert.DeserializeObject<MtTimeBar>(e.Event.Payload));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1622,20 +1681,21 @@ namespace MtApi
|
||||
OnLastTimeBar.FireEventAsync(this, new TimeBarArgs(timeBar));
|
||||
}
|
||||
|
||||
private void BacktestingReady()
|
||||
{
|
||||
SendCommand<object>(MtCommandType.BacktestingReady, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event MtApiQuoteHandler QuoteUpdated;
|
||||
public event EventHandler<MtQuoteEventArgs> QuoteAdded;
|
||||
public event EventHandler<MtQuoteEventArgs> QuoteRemoved;
|
||||
public event EventHandler<MtConnectionEventArgs> ConnectionStateChanged;
|
||||
public event EventHandler<TimeBarArgs> OnLastTimeBar;
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly MtClient _client = new MtClient();
|
||||
private readonly object _locker = new object();
|
||||
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +195,12 @@ namespace MtApi
|
||||
MtRequest = 155,
|
||||
|
||||
//Backtesting
|
||||
BacktestingReady = 156
|
||||
BacktestingReady = 156,
|
||||
|
||||
//Symbols
|
||||
SymbolsTotal = 200,
|
||||
SymbolName = 201,
|
||||
SymbolSelect = 202,
|
||||
SymbolInfoInteger = 203
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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
|
||||
{
|
||||
get { return MtApiTimeConverter.ConvertFromMtTime(MtFromTime); }
|
||||
}
|
||||
public int MtToTime { get; set; }
|
||||
public DateTime To
|
||||
{
|
||||
get { return 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.31.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.31.0")]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
OrderDelete = 6,
|
||||
OrderModify = 7,
|
||||
iCustom = 8,
|
||||
CopyRates = 9
|
||||
CopyRates = 9,
|
||||
Session = 10,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public 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
|
||||
{
|
||||
get { return RequestType.Session; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class SessionResponse : ResponseBase
|
||||
{
|
||||
public MtSession Session { get; 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,15 @@ namespace MtApi5
|
||||
MarketBookRelease = 61,
|
||||
MarketBookGet = 62,
|
||||
OrderCloseAll = 63,
|
||||
PositionClose = 64
|
||||
|
||||
//CTrade
|
||||
PositionClose = 64,
|
||||
PositionOpen = 65,
|
||||
|
||||
//Backtesting
|
||||
BacktestingReady = 66,
|
||||
IsTesting = 67,
|
||||
|
||||
Print = 68
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@
|
||||
<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" />
|
||||
@@ -55,7 +56,7 @@
|
||||
<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="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Mt5Quote.cs" />
|
||||
|
||||
+528
-488
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.10.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.10.0")]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<?define PlatformSystemFolder = "SystemFolder" ?>
|
||||
<?endif ?>
|
||||
|
||||
<?define ProductVersion="1.0.9" ?>
|
||||
<?define ProductVersion="1.0.10" ?>
|
||||
<?define Manufacturer="DW"?>
|
||||
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?define ProductName="MtApi" ?>
|
||||
<?define ProductVersion="1.0.30" ?>
|
||||
<?define ProductVersion="1.0.31" ?>
|
||||
<?define Manufacturer="DW"?>
|
||||
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
|
||||
|
||||
|
||||
@@ -13,11 +13,9 @@ MTApiService library should be placed in Windows GAC (Global Assembly Cache). In
|
||||
|
||||
# How to build solution
|
||||
The project is supported by Visual Studio 2015.
|
||||
To build solution you need to update sign key file in MtApiService project:
|
||||
- open properties of MTApiService project;
|
||||
- go to tab Signing and select item MtApiKey.pfx;
|
||||
- input password "MtApiService".
|
||||
To make api for MetaTrader4 use MtApiInstaller and for MetaTrader5 use MtApi5Installer.
|
||||
It also requires WIX Tools (http://wixtoolset.org/).
|
||||
|
||||
To make api for MetaTrader4 use MtApiInstaller and for MetaTrader5 use MtApi5Installer.
|
||||
All installers will be placed in folder "[root]\build\installers\" and all *.dll files will be placed in "[root]\build\products\".
|
||||
MQL files have been build to ex4 and stored into folders "mq4" for MetaTrader and "mq5" for MetaTrader5. They are ready to using in terminals.
|
||||
If you change source code of MQL expert you have to recompile it with MetaEditor. In this case you need to copy files "hash.mqh" and "json.mqh" to MetaEditor include folder.
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MtApi5TestClient
|
||||
{
|
||||
internal class ListBoxBehavior
|
||||
{
|
||||
static readonly Dictionary<ListBox, Capture> Associations =
|
||||
new Dictionary<ListBox, Capture>();
|
||||
|
||||
public static bool GetScrollOnNewItem(DependencyObject obj)
|
||||
{
|
||||
return (bool)obj.GetValue(ScrollOnNewItemProperty);
|
||||
}
|
||||
|
||||
public static void SetScrollOnNewItem(DependencyObject obj, bool value)
|
||||
{
|
||||
obj.SetValue(ScrollOnNewItemProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ScrollOnNewItemProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"ScrollOnNewItem",
|
||||
typeof(bool),
|
||||
typeof(ListBoxBehavior),
|
||||
new UIPropertyMetadata(false, OnScrollOnNewItemChanged));
|
||||
|
||||
public static void OnScrollOnNewItemChanged(
|
||||
DependencyObject d,
|
||||
DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var listBox = d as ListBox;
|
||||
if (listBox == null) return;
|
||||
bool oldValue = (bool)e.OldValue, newValue = (bool)e.NewValue;
|
||||
if (newValue == oldValue) return;
|
||||
if (newValue)
|
||||
{
|
||||
listBox.Loaded += ListBox_Loaded;
|
||||
listBox.Unloaded += ListBox_Unloaded;
|
||||
var itemsSourcePropertyDescriptor = TypeDescriptor.GetProperties(listBox)["ItemsSource"];
|
||||
itemsSourcePropertyDescriptor.AddValueChanged(listBox, ListBox_ItemsSourceChanged);
|
||||
}
|
||||
else
|
||||
{
|
||||
listBox.Loaded -= ListBox_Loaded;
|
||||
listBox.Unloaded -= ListBox_Unloaded;
|
||||
if (Associations.ContainsKey(listBox))
|
||||
Associations[listBox].Dispose();
|
||||
var itemsSourcePropertyDescriptor = TypeDescriptor.GetProperties(listBox)["ItemsSource"];
|
||||
itemsSourcePropertyDescriptor.RemoveValueChanged(listBox, ListBox_ItemsSourceChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ListBox_ItemsSourceChanged(object sender, EventArgs e)
|
||||
{
|
||||
var listBox = (ListBox)sender;
|
||||
if (Associations.ContainsKey(listBox))
|
||||
Associations[listBox].Dispose();
|
||||
Associations[listBox] = new Capture(listBox);
|
||||
}
|
||||
|
||||
static void ListBox_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var listBox = (ListBox)sender;
|
||||
if (Associations.ContainsKey(listBox))
|
||||
Associations[listBox].Dispose();
|
||||
listBox.Unloaded -= ListBox_Unloaded;
|
||||
}
|
||||
|
||||
static void ListBox_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var listBox = (ListBox)sender;
|
||||
var incc = listBox.Items as INotifyCollectionChanged;
|
||||
if (incc == null) return;
|
||||
listBox.Loaded -= ListBox_Loaded;
|
||||
Associations[listBox] = new Capture(listBox);
|
||||
}
|
||||
|
||||
class Capture : IDisposable
|
||||
{
|
||||
private readonly ListBox listBox;
|
||||
private readonly INotifyCollectionChanged incc;
|
||||
|
||||
public Capture(ListBox listBox)
|
||||
{
|
||||
this.listBox = listBox;
|
||||
incc = listBox.ItemsSource as INotifyCollectionChanged;
|
||||
if (incc != null)
|
||||
{
|
||||
incc.CollectionChanged += incc_CollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void incc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
listBox.ScrollIntoView(e.NewItems[0]);
|
||||
listBox.SelectedItem = e.NewItems[0];
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (incc != null)
|
||||
incc.CollectionChanged -= incc_CollectionChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Regular → Executable
+38
-15
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mtapi5="clr-namespace:MtApi5;assembly=MtApi5"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:mtApi5TestClient="clr-namespace:MtApi5TestClient"
|
||||
Title="MainWindow" Height="700" Width="650"
|
||||
Closing="Window_Closing">
|
||||
<Window.Resources>
|
||||
@@ -262,36 +263,52 @@
|
||||
</TabItem>
|
||||
<TabItem Header="Account Information">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.4*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.4*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ComboBox Grid.Column="0" Grid.Row="0"
|
||||
<ComboBox Grid.Column="0" Grid.Row="0"
|
||||
SelectedItem="{Binding AccountInfoDoublePropertyId}"
|
||||
ItemsSource="{Binding Source={StaticResource ENUM_ACCOUNT_INFO_DOUBLE_Key}}"/>
|
||||
<Button Grid.Column="1" Grid.Row="0" Margin="10,0,0,0"
|
||||
<Button Grid.Column="1" Grid.Row="0" Margin="10,0,0,0"
|
||||
Command="{Binding AccountInfoDoubleCommand}"
|
||||
Content="AccountInfoDouble" HorizontalAlignment="Left" />
|
||||
|
||||
<ComboBox Grid.Column="0" Grid.Row="1"
|
||||
<ComboBox Grid.Column="0" Grid.Row="1"
|
||||
SelectedItem="{Binding AccountInfoIntegerPropertyId}"
|
||||
ItemsSource="{Binding Source={StaticResource ENUM_ACCOUNT_INFO_INTEGER_Key}}"/>
|
||||
<Button Grid.Column="1" Grid.Row="1" Margin="10,0,0,0"
|
||||
<Button Grid.Column="1" Grid.Row="1" Margin="10,0,0,0"
|
||||
Command="{Binding AccountInfoIntegerCommand}"
|
||||
Content="AccountInfoInteger" HorizontalAlignment="Left" />
|
||||
|
||||
<ComboBox Grid.Column="0" Grid.Row="2"
|
||||
<ComboBox Grid.Column="0" Grid.Row="2"
|
||||
SelectedItem="{Binding AccountInfoStringPropertyId}"
|
||||
ItemsSource="{Binding Source={StaticResource ENUM_ACCOUNT_INFO_STRING_Key}}"/>
|
||||
<Button Grid.Column="1" Grid.Row="2" Margin="10,0,0,0"
|
||||
<Button Grid.Column="1" Grid.Row="2" Margin="10,0,0,0"
|
||||
Command="{Binding AccountInfoStringCommand}"
|
||||
Content="AccountInfoString" HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
<Grid Margin="10" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox Grid.Column="0" Text="{Binding MessageText}" Margin="5"/>
|
||||
<Button Grid.Column="1" Content="Print" Command="{Binding PrintCommand}" Margin="5"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
@@ -316,9 +333,9 @@
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox Grid.Row="0" Text="symbol_name"/>
|
||||
<TextBox Grid.Row="0" Text="symbolName"/>
|
||||
<TextBox Grid.Row="1" Text="timeframe"/>
|
||||
<TextBox Grid.Row="2" Text="start_pos"/>
|
||||
<TextBox Grid.Row="2" Text="startPos"/>
|
||||
<TextBox Grid.Row="3" Text="count"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TimeSeriesValues.SymbolValue}"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1"
|
||||
@@ -355,7 +372,7 @@
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header=" Market Info">
|
||||
<TabItem Header="Market Info">
|
||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||
<Button Command="{Binding SymbolsTotalCommand}" Content="SymbolsTotal" Margin="2"/>
|
||||
<Button Command="{Binding SymbolNameCommand}" Content="SymbolName" Margin="2"/>
|
||||
@@ -372,10 +389,16 @@
|
||||
<Button Command="{Binding MarketBookGetCommand}" Content="MarketBookGet" Margin="2"/>
|
||||
</WrapPanel>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="CTrade">
|
||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||
<Button Command="{Binding PositionOpenCommand}" Content="PositionOpen" Margin="2"/>
|
||||
</WrapPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
<Expander Grid.Row="2" Header="History" IsExpanded="True">
|
||||
<ListBox Height="200" ItemsSource="{Binding History}"/>
|
||||
<ListBox mtApi5TestClient:ListBoxBehavior.ScrollOnNewItem="true" Height="200" ItemsSource="{Binding History}"/>
|
||||
</Expander>
|
||||
|
||||
<StatusBar Grid.Row="3">
|
||||
|
||||
Regular → Executable
Regular → Executable
+1
-1
@@ -39,7 +39,7 @@ namespace MtApi5TestClient
|
||||
}
|
||||
}
|
||||
|
||||
public uint Order
|
||||
public ulong Order
|
||||
{
|
||||
get { return TradeRequest.Order; }
|
||||
set
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
@@ -10,8 +10,9 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MtApi5TestClient</RootNamespace>
|
||||
<AssemblyName>MtApi5TestClient</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
@@ -25,6 +26,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -34,6 +36,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -50,6 +53,7 @@
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
@@ -67,6 +71,7 @@
|
||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -97,6 +102,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DelegateCommand.cs" />
|
||||
<Compile Include="ListBoxBehavior.cs" />
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
@@ -124,6 +130,7 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
||||
+18
-26
@@ -1,17 +1,17 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18034
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MtApi5TestClient.Properties
|
||||
{
|
||||
|
||||
|
||||
namespace MtApi5TestClient.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
@@ -22,48 +22,40 @@ namespace MtApi5TestClient.Properties
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MtApi5TestClient.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-14
@@ -1,28 +1,24 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18034
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MtApi5TestClient.Properties
|
||||
{
|
||||
|
||||
|
||||
namespace MtApi5TestClient.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+517
-358
File diff suppressed because it is too large
Load Diff
Executable
+3
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
|
||||
+143
-15
@@ -139,13 +139,21 @@
|
||||
this.button6 = new System.Windows.Forms.Button();
|
||||
this.listBoxProceHistory = new System.Windows.Forms.ListBox();
|
||||
this.tabPage6 = new System.Windows.Forms.TabPage();
|
||||
this.textBoxPrint = new System.Windows.Forms.TextBox();
|
||||
this.button27 = new System.Windows.Forms.Button();
|
||||
this.button14 = new System.Windows.Forms.Button();
|
||||
this.button13 = new System.Windows.Forms.Button();
|
||||
this.tabPage7 = new System.Windows.Forms.TabPage();
|
||||
this.button23 = new System.Windows.Forms.Button();
|
||||
this.iCustomBtn = new System.Windows.Forms.Button();
|
||||
this.button27 = new System.Windows.Forms.Button();
|
||||
this.textBoxPrint = new System.Windows.Forms.TextBox();
|
||||
this.tabPage8 = new System.Windows.Forms.TabPage();
|
||||
this.comboBox4 = new System.Windows.Forms.ComboBox();
|
||||
this.button32 = new System.Windows.Forms.Button();
|
||||
this.button30 = new System.Windows.Forms.Button();
|
||||
this.button29 = new System.Windows.Forms.Button();
|
||||
this.button28 = new System.Windows.Forms.Button();
|
||||
this.label28 = new System.Windows.Forms.Label();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
@@ -161,6 +169,7 @@
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
||||
this.tabPage6.SuspendLayout();
|
||||
this.tabPage7.SuspendLayout();
|
||||
this.tabPage8.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBoxServerName
|
||||
@@ -323,6 +332,7 @@
|
||||
this.tabControl1.Controls.Add(this.tabPage5);
|
||||
this.tabControl1.Controls.Add(this.tabPage6);
|
||||
this.tabControl1.Controls.Add(this.tabPage7);
|
||||
this.tabControl1.Controls.Add(this.tabPage8);
|
||||
this.tabControl1.Location = new System.Drawing.Point(12, 147);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
@@ -1359,6 +1369,23 @@
|
||||
this.tabPage6.Text = "Client Terminal";
|
||||
this.tabPage6.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// textBoxPrint
|
||||
//
|
||||
this.textBoxPrint.Location = new System.Drawing.Point(209, 16);
|
||||
this.textBoxPrint.Name = "textBoxPrint";
|
||||
this.textBoxPrint.Size = new System.Drawing.Size(386, 20);
|
||||
this.textBoxPrint.TabIndex = 3;
|
||||
//
|
||||
// button27
|
||||
//
|
||||
this.button27.Location = new System.Drawing.Point(601, 16);
|
||||
this.button27.Name = "button27";
|
||||
this.button27.Size = new System.Drawing.Size(75, 23);
|
||||
this.button27.TabIndex = 2;
|
||||
this.button27.Text = "Print";
|
||||
this.button27.UseVisualStyleBackColor = true;
|
||||
this.button27.Click += new System.EventHandler(this.button27_Click);
|
||||
//
|
||||
// button14
|
||||
//
|
||||
this.button14.Location = new System.Drawing.Point(13, 45);
|
||||
@@ -1411,22 +1438,113 @@
|
||||
this.iCustomBtn.UseVisualStyleBackColor = true;
|
||||
this.iCustomBtn.Click += new System.EventHandler(this.iCustomBtn_Click);
|
||||
//
|
||||
// button27
|
||||
// tabPage8
|
||||
//
|
||||
this.button27.Location = new System.Drawing.Point(601, 16);
|
||||
this.button27.Name = "button27";
|
||||
this.button27.Size = new System.Drawing.Size(75, 23);
|
||||
this.button27.TabIndex = 2;
|
||||
this.button27.Text = "Print";
|
||||
this.button27.UseVisualStyleBackColor = true;
|
||||
this.button27.Click += new System.EventHandler(this.button27_Click);
|
||||
this.tabPage8.Controls.Add(this.comboBox4);
|
||||
this.tabPage8.Controls.Add(this.button32);
|
||||
this.tabPage8.Controls.Add(this.button30);
|
||||
this.tabPage8.Controls.Add(this.button29);
|
||||
this.tabPage8.Controls.Add(this.button28);
|
||||
this.tabPage8.Controls.Add(this.label28);
|
||||
this.tabPage8.Controls.Add(this.textBox1);
|
||||
this.tabPage8.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage8.Name = "tabPage8";
|
||||
this.tabPage8.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage8.Size = new System.Drawing.Size(682, 377);
|
||||
this.tabPage8.TabIndex = 8;
|
||||
this.tabPage8.Text = "Symbols";
|
||||
this.tabPage8.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// textBoxPrint
|
||||
// comboBox4
|
||||
//
|
||||
this.textBoxPrint.Location = new System.Drawing.Point(209, 16);
|
||||
this.textBoxPrint.Name = "textBoxPrint";
|
||||
this.textBoxPrint.Size = new System.Drawing.Size(386, 20);
|
||||
this.textBoxPrint.TabIndex = 3;
|
||||
this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBox4.FormattingEnabled = true;
|
||||
this.comboBox4.Items.AddRange(new object[] {
|
||||
"SYMBOL_SELECT",
|
||||
"SYMBOL_VISIBLE",
|
||||
"SYMBOL_SESSION_DEALS",
|
||||
"SYMBOL_SESSION_BUY_ORDERS",
|
||||
"SYMBOL_SESSION_SELL_ORDERS",
|
||||
"SYMBOL_VOLUME",
|
||||
"SYMBOL_VOLUMEHIGH",
|
||||
"SYMBOL_VOLUMELOW",
|
||||
"SYMBOL_TIME",
|
||||
"SYMBOL_DIGITS",
|
||||
"SYMBOL_SPREAD",
|
||||
"SYMBOL_SPREAD_FLOAT",
|
||||
"SYMBOL_TRADE_CALC_MODE",
|
||||
"SYMBOL_TRADE_MODE",
|
||||
"SYMBOL_START_TIME",
|
||||
"SYMBOL_EXPIRATION_TIME",
|
||||
"SYMBOL_TRADE_STOPS_LEVEL",
|
||||
"SYMBOL_TRADE_FREEZE_LEVEL",
|
||||
"SYMBOL_TRADE_EXEMODE",
|
||||
"SYMBOL_SWAP_MODE",
|
||||
"SYMBOL_SWAP_ROLLOVER3DAYS",
|
||||
"SYMBOL_EXPIRATION_MODE",
|
||||
"SYMBOL_FILLING_MODE",
|
||||
"SYMBOL_ORDER_MODE"});
|
||||
this.comboBox4.Location = new System.Drawing.Point(10, 87);
|
||||
this.comboBox4.Name = "comboBox4";
|
||||
this.comboBox4.Size = new System.Drawing.Size(174, 21);
|
||||
this.comboBox4.TabIndex = 3;
|
||||
//
|
||||
// button32
|
||||
//
|
||||
this.button32.Location = new System.Drawing.Point(190, 87);
|
||||
this.button32.Name = "button32";
|
||||
this.button32.Size = new System.Drawing.Size(108, 23);
|
||||
this.button32.TabIndex = 2;
|
||||
this.button32.Text = "SymbolInfoInteger";
|
||||
this.button32.UseVisualStyleBackColor = true;
|
||||
this.button32.Click += new System.EventHandler(this.button32_Click);
|
||||
//
|
||||
// button30
|
||||
//
|
||||
this.button30.Location = new System.Drawing.Point(206, 56);
|
||||
this.button30.Name = "button30";
|
||||
this.button30.Size = new System.Drawing.Size(92, 23);
|
||||
this.button30.TabIndex = 2;
|
||||
this.button30.Text = "SymbolSelect";
|
||||
this.button30.UseVisualStyleBackColor = true;
|
||||
this.button30.Click += new System.EventHandler(this.button30_Click);
|
||||
//
|
||||
// button29
|
||||
//
|
||||
this.button29.Location = new System.Drawing.Point(108, 56);
|
||||
this.button29.Name = "button29";
|
||||
this.button29.Size = new System.Drawing.Size(92, 23);
|
||||
this.button29.TabIndex = 2;
|
||||
this.button29.Text = "SymbolName";
|
||||
this.button29.UseVisualStyleBackColor = true;
|
||||
this.button29.Click += new System.EventHandler(this.button29_Click);
|
||||
//
|
||||
// button28
|
||||
//
|
||||
this.button28.Location = new System.Drawing.Point(10, 56);
|
||||
this.button28.Name = "button28";
|
||||
this.button28.Size = new System.Drawing.Size(92, 23);
|
||||
this.button28.TabIndex = 2;
|
||||
this.button28.Text = "SymbolsTotal";
|
||||
this.button28.UseVisualStyleBackColor = true;
|
||||
this.button28.Click += new System.EventHandler(this.button28_Click);
|
||||
//
|
||||
// label28
|
||||
//
|
||||
this.label28.AutoSize = true;
|
||||
this.label28.Location = new System.Drawing.Point(7, 20);
|
||||
this.label28.Name = "label28";
|
||||
this.label28.Size = new System.Drawing.Size(41, 13);
|
||||
this.label28.TabIndex = 1;
|
||||
this.label28.Text = "Symbol";
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(54, 17);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(100, 20);
|
||||
this.textBox1.TabIndex = 0;
|
||||
this.textBox1.Text = "EURUSD";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
@@ -1466,6 +1584,8 @@
|
||||
this.tabPage6.ResumeLayout(false);
|
||||
this.tabPage6.PerformLayout();
|
||||
this.tabPage7.ResumeLayout(false);
|
||||
this.tabPage8.ResumeLayout(false);
|
||||
this.tabPage8.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -1590,6 +1710,14 @@
|
||||
private System.Windows.Forms.Button button25;
|
||||
private System.Windows.Forms.Button button27;
|
||||
private System.Windows.Forms.TextBox textBoxPrint;
|
||||
private System.Windows.Forms.TabPage tabPage8;
|
||||
private System.Windows.Forms.Label label28;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Button button28;
|
||||
private System.Windows.Forms.Button button29;
|
||||
private System.Windows.Forms.Button button30;
|
||||
private System.Windows.Forms.Button button32;
|
||||
private System.Windows.Forms.ComboBox comboBox4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
+142
-49
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
#include <trade/trade.mqh>
|
||||
#property version "1.1"
|
||||
#property description "MtApi (MT5) connection expert"
|
||||
|
||||
#import "MT5Connector.dll"
|
||||
bool initExpert(int expertHandle, int port, string symbol, double bid, double ask, string& err);
|
||||
@@ -32,8 +34,6 @@
|
||||
bool getDoubleValue(int expertHandle, int paramIndex, double& res);
|
||||
bool getStringValue(int expertHandle, int paramIndex, string& res);
|
||||
bool getBooleanValue(int expertHandle, int paramIndex, bool& res);
|
||||
|
||||
// void verify(bool isDemo, string accountName, long accountNumber);
|
||||
#import
|
||||
|
||||
input int Port = 8228;
|
||||
@@ -43,12 +43,11 @@ int ExpertHandle;
|
||||
string message;
|
||||
bool isCrashed = false;
|
||||
|
||||
bool IsRemoteReadyForTesting = false;
|
||||
|
||||
string symbolValue;
|
||||
string commentValue;
|
||||
|
||||
double myBid;
|
||||
double myAsk;
|
||||
|
||||
string PARAM_SEPARATOR = ";";
|
||||
|
||||
int OnInit()
|
||||
@@ -57,6 +56,12 @@ int OnInit()
|
||||
return (result);
|
||||
}
|
||||
|
||||
double OnTester()
|
||||
{
|
||||
Print("OnTester");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
deinit();
|
||||
@@ -69,9 +74,9 @@ void OnTick()
|
||||
|
||||
int preinit()
|
||||
{
|
||||
message = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "";
|
||||
symbolValue = "222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" + "";
|
||||
commentValue = "333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333" + "";
|
||||
StringInit(message, 1000, 0);
|
||||
StringInit(symbolValue, 1000, 0);
|
||||
StringInit(commentValue, 1000, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -84,11 +89,15 @@ bool IsDemo()
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool IsTesting()
|
||||
{
|
||||
bool isTesting = MQLInfoInteger(MQL_TESTER);
|
||||
return isTesting;
|
||||
}
|
||||
|
||||
int init()
|
||||
{
|
||||
preinit();
|
||||
|
||||
// verify(IsDemo(), AccountInfoString(ACCOUNT_NAME), AccountInfoInteger(ACCOUNT_LOGIN));
|
||||
preinit();
|
||||
|
||||
if (TerminalInfoInteger(TERMINAL_DLLS_ALLOWED) == false)
|
||||
{
|
||||
@@ -110,17 +119,14 @@ int init()
|
||||
return (1);
|
||||
}
|
||||
|
||||
long chartID= ChartID();
|
||||
ExpertHandle = ChartGetInteger(chartID, CHART_WINDOW_HANDLE);
|
||||
long chartID = ChartID();
|
||||
ExpertHandle = (int) ChartGetInteger(chartID, CHART_WINDOW_HANDLE);
|
||||
|
||||
MqlTick last_tick;
|
||||
SymbolInfoTick(Symbol(),last_tick);
|
||||
double Bid = last_tick.bid;
|
||||
double Ask = last_tick.ask;
|
||||
|
||||
myBid = Bid;
|
||||
myAsk = Ask;
|
||||
|
||||
if (!initExpert(ExpertHandle, Port, Symbol(), Bid, Ask, message))
|
||||
{
|
||||
MessageBox(message, "MtApi", 0);
|
||||
@@ -133,6 +139,30 @@ int init()
|
||||
isCrashed = true;
|
||||
return (1);
|
||||
}
|
||||
|
||||
PrintFormat("Expert Handle = %d", ExpertHandle);
|
||||
|
||||
//--- Backtesting mode
|
||||
if (false)
|
||||
{
|
||||
if (IsTesting())
|
||||
{
|
||||
Print("Waiting on remote client...");
|
||||
//wait for command (BacktestingReady) from remote side to be ready for work
|
||||
while(!IsRemoteReadyForTesting)
|
||||
{
|
||||
executeCommand();
|
||||
|
||||
//This section uses a while loop to simulate Sleep() during Backtest.
|
||||
unsigned int viSleepUntilTick = GetTickCount() + 100; //100 milliseconds
|
||||
while(GetTickCount() < viSleepUntilTick)
|
||||
{
|
||||
//Do absolutely nothing. Just loop until the desired tick is reached.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -147,6 +177,7 @@ int deinit()
|
||||
isCrashed = true;
|
||||
return (1);
|
||||
}
|
||||
Print("Expert was deinitialized.");
|
||||
}
|
||||
|
||||
return (0);
|
||||
@@ -154,50 +185,46 @@ int deinit()
|
||||
|
||||
int start()
|
||||
{
|
||||
if (isCrashed == 0)
|
||||
{
|
||||
MqlTick last_tick;
|
||||
SymbolInfoTick(Symbol(),last_tick);
|
||||
double Bid = last_tick.bid;
|
||||
double Ask = last_tick.ask;
|
||||
MqlTick last_tick;
|
||||
SymbolInfoTick(Symbol(),last_tick);
|
||||
double Bid = last_tick.bid;
|
||||
double Ask = last_tick.ask;
|
||||
|
||||
if (executeCommand() != 0)
|
||||
{
|
||||
CSymbolInfo mysymbol;
|
||||
mysymbol.Name (_Symbol);
|
||||
mysymbol.RefreshRates();
|
||||
|
||||
Bid = mysymbol.Bid();
|
||||
Ask = mysymbol.Ask();
|
||||
|
||||
if (myBid == Bid && myAsk == Ask)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateQuote(ExpertHandle, Symbol(), Bid, Ask, message))
|
||||
{
|
||||
MessageBox(message, "MtApi", 0);
|
||||
isCrashed = true;
|
||||
return (1);
|
||||
}
|
||||
|
||||
myBid = Bid;
|
||||
myAsk = Ask;
|
||||
if (!updateQuote(ExpertHandle, Symbol(), Bid, Ask, message))
|
||||
{
|
||||
Print("updateQuote: [ERROR] ", message);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void OnTimer()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
int executedCommand = executeCommand();
|
||||
if (executedCommand == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int executeCommand()
|
||||
{
|
||||
int commandType = 0;
|
||||
|
||||
if (!getCommandType(ExpertHandle, commandType))
|
||||
{
|
||||
Print("[ERROR] getCommandType");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (commandType > 0)
|
||||
{
|
||||
Print("executeCommand: commnad type = ", commandType);
|
||||
}
|
||||
|
||||
switch (commandType)
|
||||
{
|
||||
@@ -227,6 +254,7 @@ int executeCommand()
|
||||
sendBooleanResponse(ExpertHandle, retVal);
|
||||
}
|
||||
break;
|
||||
|
||||
case 64: //PositionClose
|
||||
{
|
||||
int ticket;
|
||||
@@ -237,7 +265,7 @@ int executeCommand()
|
||||
sendBooleanResponse(ExpertHandle, trade.PositionClose(ticket));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 2: // OrderCalcMargin
|
||||
{
|
||||
ENUM_ORDER_TYPE action;
|
||||
@@ -1610,7 +1638,72 @@ int executeCommand()
|
||||
sendVoidResponse(ExpertHandle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 65: //PositionOpen
|
||||
{
|
||||
string symbol;
|
||||
StringInit(symbol, 50, 0);
|
||||
ENUM_ORDER_TYPE order_type;
|
||||
double volume;
|
||||
double price;
|
||||
double sl;
|
||||
double tp;
|
||||
string comment;
|
||||
StringInit(comment, 1000, 0);
|
||||
|
||||
getStringValue(ExpertHandle, 0, symbol);
|
||||
int order_type_int = 0;
|
||||
getIntValue(ExpertHandle, 1, order_type_int);
|
||||
order_type = (ENUM_ORDER_TYPE) order_type_int;
|
||||
getDoubleValue(ExpertHandle, 2, volume);
|
||||
getDoubleValue(ExpertHandle, 3, price);
|
||||
getDoubleValue(ExpertHandle, 4, sl);
|
||||
getDoubleValue(ExpertHandle, 5, tp);
|
||||
getStringValue(ExpertHandle, 6, comment);
|
||||
|
||||
PrintFormat("command PositionOpen: symbol = %s, order_type = %d, volume = %f, price = %f, sl = %f, tp = %f, comment = %s",
|
||||
symbol, order_type, volume, price, sl, tp, comment);
|
||||
|
||||
CTrade trade;
|
||||
bool result = trade.PositionOpen(symbol, order_type, volume, price, sl, tp, comment);
|
||||
sendBooleanResponse(ExpertHandle, result);
|
||||
Print("command PositionOpen: result = ", result);
|
||||
}
|
||||
break;
|
||||
|
||||
case 66: //BacktestingReady
|
||||
{
|
||||
if (IsTesting())
|
||||
{
|
||||
Print("Remote client is ready for backteting");
|
||||
IsRemoteReadyForTesting = true;
|
||||
sendBooleanResponse(ExpertHandle, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendBooleanResponse(ExpertHandle, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 67: //IsTesting
|
||||
{
|
||||
sendBooleanResponse(ExpertHandle, IsTesting());
|
||||
}
|
||||
break;
|
||||
|
||||
case 68: //Print
|
||||
{
|
||||
string printMsg;
|
||||
StringInit(printMsg, 1000, 0);
|
||||
|
||||
getStringValue(ExpertHandle, 0, printMsg);
|
||||
|
||||
Print(printMsg);
|
||||
sendBooleanResponse(ExpertHandle, true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Print("Unknown command type = ", commandType);
|
||||
|
||||
Reference in New Issue
Block a user