Compare commits

..

3 Commits

Author SHA1 Message Date
Konstantin Ivanov db4bb44fb3 Add SymbolSelect() and use existing local variables 2016-09-29 17:13:41 +03:00
Konstantin Ivanov 68d5fa98af Add SymbolName() 2016-09-29 16:30:11 +03:00
Konstantin Ivanov dc28823ca9 add SymbolsTotal() 2016-09-29 16:14:53 +03:00
57 changed files with 2193 additions and 3083 deletions
+341 -341
View File
@@ -21,57 +21,57 @@ using namespace System::Security;
#pragma pack(push, 1)
public struct CMqlRates
{
__int64 time; // Period start time
double open; // Open price
double high; // The highest price of the period
double low; // The lowest price of the period
double close; // Close price
__int64 tick_volume; // Tick volume
int spread; // Spread
__int64 real_volume; // Trade volume
__int64 time; // Period start time
double open; // Open price
double high; // The highest price of the period
double low; // The lowest price of the period
double close; // Close price
__int64 tick_volume; // Tick volume
int spread; // Spread
__int64 real_volume; // Trade volume
};
public struct CMqlTick
{
__int64 time; // Time of the last prices update
double bid; // Current Bid price
double ask; // Current Ask price
double last; // Price of the last deal (Last)
unsigned __int64 volume; // Volume for the current Last price
__int64 time; // Time of the last prices update
double bid; // Current Bid price
double ask; // Current Ask price
double last; // Price of the last deal (Last)
unsigned __int64 volume; // Volume for the current Last price
};
public struct CMqlBookInfo
{
int type; // Order type from ENUM_BOOK_TYPE enumeration
double price; // Price
__int64 volume; // Volume
int type; // Order type from ENUM_BOOK_TYPE enumeration
double price; // Price
__int64 volume; // Volume
};
#pragma pack(pop)
void convertSystemString(wchar_t* dest, String^ src)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
}
bool VerifySignature(System::String^ inputData, System::String^ signature, System::String^ publicKey)
{
bool verifyResult = false;
bool verifyResult = false;
try
{
DSACryptoServiceProvider^ dsa = gcnew DSACryptoServiceProvider();
dsa->FromXmlString(publicKey);
array<System::Byte>^ data = UTF8Encoding::ASCII->GetBytes(inputData);
array<System::Byte>^ signatureData = Convert::FromBase64String(signature);
verifyResult = dsa->VerifyData(data, signatureData);
}
catch(Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:VerifySignature(): failed. " + e->Message);
verifyResult = false;
}
try
{
DSACryptoServiceProvider^ dsa = gcnew DSACryptoServiceProvider();
dsa->FromXmlString(publicKey);
array<System::Byte>^ data = UTF8Encoding::ASCII->GetBytes(inputData);
array<System::Byte>^ signatureData = Convert::FromBase64String(signature);
verifyResult = dsa->VerifyData(data, signatureData);
}
catch(Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:VerifySignature(): failed. " + e->Message);
verifyResult = false;
}
return verifyResult;
}
@@ -80,431 +80,431 @@ bool g_IsVerified = true;
void _stdcall verify(int isDemo, wchar_t* accountName, long accountNumber)
{
if (isDemo != 0)
{
g_IsVerified = true;
return;
}
if (isDemo != 0)
{
g_IsVerified = true;
return;
}
System::String^ signature = MtRegistryManager::ReadSignatureKey(gcnew String(accountName), accountNumber.ToString());
Resources::ResourceManager^ rm = gcnew Resources::ResourceManager(L"MT5Connector.cl", Assembly::GetExecutingAssembly());
System::String^ inputData = gcnew System::String(accountName);
inputData += accountNumber.ToString();
System::String^ publicKey = rm->GetString(L"cl");
g_IsVerified = VerifySignature(inputData, gcnew System::String(signature), publicKey);
System::String^ signature = MtRegistryManager::ReadSignatureKey(gcnew String(accountName), accountNumber.ToString());
Resources::ResourceManager^ rm = gcnew Resources::ResourceManager(L"MT5Connector.cl", Assembly::GetExecutingAssembly());
System::String^ inputData = gcnew System::String(accountName);
inputData += accountNumber.ToString();
System::String^ publicKey = rm->GetString(L"cl");
g_IsVerified = VerifySignature(inputData, gcnew System::String(signature), publicKey);
}
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
if (g_IsVerified == false)
{
System::String^ errorVerified = "Verification is failed!\nPlease contact with support.";
convertSystemString(err, errorVerified);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): not verified");
return 0;
}
if (g_IsVerified == false)
{
System::String^ errorVerified = "Verification is failed!\nPlease contact with support.";
convertSystemString(err, errorVerified);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): not verified");
return 0;
}
try
{
MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): " + e->Message);
try
{
MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:deinitExpert(): " + e->Message);
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:updateQuote(): " + e->Message);
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:updateQuote(): " + e->Message);
return 0;
}
return 1;
return 0;
}
return 1;
}
int _stdcall sendIntResponse(int expertHandle, int response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendLongResponse(int expertHandle, __int64 response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendULongResponse(int expertHandle, unsigned __int64 response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendBooleanResponse(int expertHandle, int response)
{
try
{
bool value = (response != 0) ? true : false;
try
{
bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendDoubleResponse(int expertHandle, double response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendVoidResponse(int expertHandle)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
{
try
{
array<double>^ list = gcnew array<double>(size);
try
{
array<double>^ list = gcnew array<double>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
{
try
{
array<int>^ list = gcnew array<int>(size);
try
{
array<int>^ list = gcnew array<int>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendLongArrayResponse(int expertHandle, __int64* values, int size)
{
try
{
array<System::Int64>^ list = gcnew array<System::Int64>(size);
try
{
array<System::Int64>^ list = gcnew array<System::Int64>(size);
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
for(int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int size)
{
try
{
array<MtMqlRates^>^ list = gcnew array<MtMqlRates^>(size);
try
{
array<MtMqlRates^>^ list = gcnew array<MtMqlRates^>(size);
for(int i = 0; i < size; i++)
{
MtMqlRates^ rates = gcnew MtMqlRates();
rates->time = values[i].time;
rates->open = values[i].open;
rates->high = values[i].high;
rates->low = values[i].low;
rates->close = values[i].close;
rates->tick_volume = values[i].tick_volume;
rates->spread = values[i].spread;
rates->real_volume = values[i].real_volume;
for(int i = 0; i < size; i++)
{
MtMqlRates^ rates = gcnew MtMqlRates();
rates->time = values[i].time;
rates->open = values[i].open;
rates->high = values[i].high;
rates->low = values[i].low;
rates->close = values[i].close;
rates->tick_volume = values[i].tick_volume;
rates->spread = values[i].spread;
rates->real_volume = values[i].real_volume;
list[i] = rates;
}
list[i] = rates;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlTickResponse(int expertHandle, CMqlTick* response, int size)
{
try
{
MtMqlTick^ mtResponse = gcnew MtMqlTick();
try
{
MtMqlTick^ mtResponse = gcnew MtMqlTick();
mtResponse->time = response->time;
mtResponse->bid = response->bid;
mtResponse->ask = response->ask;
mtResponse->last = response->last;
mtResponse->volume = response->volume;
mtResponse->time = response->time;
mtResponse->bid = response->bid;
mtResponse->ask = response->ask;
mtResponse->last = response->last;
mtResponse->volume = response->volume;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlTickResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlTickResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlBookInfoArrayResponse(int expertHandle, CMqlBookInfo values[], int size)
{
try
{
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
try
{
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
for(int i = 0; i < size; i++)
{
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
for(int i = 0; i < size; i++)
{
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
info->type = values[i].type;
info->price = values[i].price;
info->volume = values[i].volume;
info->type = values[i].type;
info->price = values[i].price;
info->volume = values[i].volume;
list[i] = info;
}
list[i] = info;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
}
//----------- get values -------------------------------
int _stdcall getCommandType(int expertHandle, int* res)
{
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getCommandType(): " + e->Message);
return 0;
}
return 1;
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getCommandType(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
{
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getIntValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getIntValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
{
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
{
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getStringValue(): " + e->Message);
return 0;
}
return 1;
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getStringValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getULongValue(int expertHandle, int paramIndex, unsigned __int64* res)
{
try
{
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getULongValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getULongValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res)
{
try
{
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getLongValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getLongValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
{
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall getUIntValue(int expertHandle, int paramIndex, unsigned int* res)
{
try
{
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getUIntValue(): " + e->Message);
return 0;
}
return 1;
try
{
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getUIntValue(): " + e->Message);
return 0;
}
return 1;
}
+9 -9
View File
@@ -9,16 +9,16 @@ using namespace MTApiService;
ref class MT5Handler: IMetaTraderHandler
{
public:
MT5Handler()
{
msgId = WM_TIMER;
}
MT5Handler()
{
msgId = WM_USER + 4096;
}
virtual void SendTickToMetaTrader(int handle)
{
PostMessage((HWND)handle, msgId, 0, 0);
}
virtual void SendTickToMetaTrader(int handle)
{
PostMessage((HWND)handle, msgId, 0x00000011, 0);
}
private:
unsigned int msgId;
unsigned int msgId;
};
-67
View File
@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- -->
<!-- ILMerge project-specific settings. Almost never need to be set explicitly. -->
<!-- for details, see http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx -->
<!-- -->
<!-- *** set this file to Type=None, CopyToOutput=Never *** -->
<!-- If True, all copy local dependencies will also be merged from referenced projects whether they are referenced in the current project explicitly or not -->
<ILMergeTransitive>true</ILMergeTransitive>
<!-- Extra ILMerge library paths (semicolon-separated). Dont put your package dependencies here, they will be added automagically -->
<ILMergeLibraryPath></ILMergeLibraryPath>
<!-- The solution NuGet package directory if not standard 'SOLUTION\packages' -->
<ILMergePackagesPath></ILMergePackagesPath>
<!-- The merge order file name if differs from standard 'ILMergeOrder.txt' -->
<ILMergeOrderFile></ILMergeOrderFile>
<!-- The strong key file name if not specified in the project -->
<ILMergeKeyFile>MtApiKey.snk</ILMergeKeyFile>
<!-- The assembly version if differs for the version of the main assembly -->
<ILMergeAssemblyVersion></ILMergeAssemblyVersion>
<!-- added in Version 1.0.4 -->
<ILMergeFileAlignment></ILMergeFileAlignment>
<!-- added in Version 1.0.4, default=none -->
<ILMergeAllowDuplicateType></ILMergeAllowDuplicateType>
<!-- If the <see cref="CopyAttributes"/> is also set, any assembly-level attributes names that have the same type are copied over into the target assembly -->
<ILMergeAllowMultipleAssemblyLevelAttributes></ILMergeAllowMultipleAssemblyLevelAttributes>
<!-- See ILMerge documentation -->
<ILMergeAllowZeroPeKind></ILMergeAllowZeroPeKind>
<!-- The assembly level attributes of each input assembly are copied over into the target assembly -->
<ILMergeCopyAttributes></ILMergeCopyAttributes>
<!-- Creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies, default=true -->
<ILMergeDebugInfo></ILMergeDebugInfo>
<!-- Target assembly will be delay signed -->
<ILMergeDelaySign></ILMergeDelaySign>
<!-- Types in assemblies other than the primary assembly have their visibility modified -->
<ILMergeInternalize></ILMergeInternalize>
<!-- The path name of the file that will be used to identify types that are not to have their visibility modified -->
<ILMergeInternalizeExcludeFile></ILMergeInternalizeExcludeFile>
<!-- XML documentation files are merged to produce an XML documentation file for the target assembly -->
<ILMergeXmlDocumentation></ILMergeXmlDocumentation>
<!-- External assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true, default value) -->
<ILMergePublicKeyTokens></ILMergePublicKeyTokens>
<!-- Types with the same name are all merged into a single type in the target assembly -->
<ILMergeUnionMerge></ILMergeUnionMerge>
<!-- The version of the target framework, default 40 (works for 45 too) -->
<ILTargetPlatform></ILTargetPlatform>
</PropertyGroup>
</Project>
-4
View File
@@ -1,4 +0,0 @@
# 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
+5 -2
View File
@@ -1,10 +1,13 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService
{
public interface IMtApiServer
{
MtResponse SendCommand(MtCommand command);
List<MtQuote> GetQuotes();
IEnumerable<MtQuote> GetQuotes();
}
}
-55
View File
@@ -1,55 +0,0 @@
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;
}
}
}
+3 -27
View File
@@ -1,6 +1,5 @@
<?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>
@@ -15,8 +14,6 @@
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -38,17 +35,12 @@
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>MtApiKey.pfx</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" />
@@ -62,7 +54,6 @@
<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" />
@@ -87,28 +78,13 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ILMerge.props">
<SubType>Designer</SubType>
</None>
<None Include="MtApiKey.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="ILMergeOrder.txt" />
<None Include="MtApiKey.pfx" />
</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">
BIN
View File
Binary file not shown.
Binary file not shown.
+14 -11
View File
@@ -1,17 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace MTApiService
{
internal class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
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)
{
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
InnerDuplexChannel.Open();
base.InnerDuplexChannel.Faulted += new EventHandler(InnerDuplexChannel_Faulted);
base.InnerDuplexChannel.Open();
}
#region IMtApi Members
@@ -31,7 +34,7 @@ namespace MTApiService
return Channel.SendCommand(command);
}
public List<MtQuote> GetQuotes()
public IEnumerable<MtQuote> GetQuotes()
{
return Channel.GetQuotes();
}
@@ -44,19 +47,19 @@ namespace MTApiService
{
try
{
Close();
this.Close();
}
catch (CommunicationException)
{
Abort();
this.Abort();
}
catch (TimeoutException)
{
Abort();
this.Abort();
}
catch (Exception)
{
Abort();
this.Abort();
}
}
@@ -65,9 +68,9 @@ namespace MTApiService
#region Private Methods
private void InnerDuplexChannel_Faulted(object sender, EventArgs e)
{
Faulted?.Invoke(this, e);
if (Faulted != null)
Faulted(this, e);
}
#endregion
#region Events
+133 -171
View File
@@ -1,208 +1,173 @@
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 const string ServiceName = "MtApiService";
private static string SERVICE_NAME = "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)
{
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, port);
Debug.WriteLine("[INFO] MtClient::Open");
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException(nameof(host), "host is null or empty");
throw new ArgumentNullException("host", "host is null or empty");
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
throw new ArgumentOutOfRangeException("port", "port value is invalid");
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
var urlService = string.Format("net.tcp://{0}:{1}/{2}", host, port, SERVICE_NAME);
if (_proxy != null)
lock (mClientLocker)
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
if (mProxy != 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 =
var bind = new NetTcpBinding(SecurityMode.None)
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
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
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
mProxy.Faulted += mProxy_Faulted;
}
}
public void Open(int port)
{
Log.DebugFormat("Open: begin. port = {0}", port);
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
throw new ArgumentOutOfRangeException("port", "port value is invalid");
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
var urlService = string.Format("net.pipe://localhost/{0}_{1}", SERVICE_NAME, port);
if (_proxy != null)
lock (mClientLocker)
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
if (mProxy != 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 =
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
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
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
mProxy.Faulted += mProxy_Faulted;
}
}
public void Close()
{
Log.Debug("Close: begin.");
Debug.WriteLine("[INFO] MtClient::Close");
if (_proxy != null)
lock (mClientLocker)
{
_proxy.Faulted -= ProxyFaulted;
_proxy.Dispose();
_proxy = null;
if (mProxy != null)
{
mProxy.Faulted -= mProxy_Faulted;
mProxy.Dispose();
mProxy = null;
}
mIsConnected = false;
}
_isConnected = false;
Log.Debug("Close: end.");
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public void 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;
}
Debug.WriteLine("[INFO] MtClient::Connect");
try
{
_isConnected = _proxy.Connect();
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
return;
mIsConnected = mProxy.Connect();
if (mIsConnected == false)
throw new Exception("Connected failed");
}
}
catch (Exception ex)
{
Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
Debug.WriteLine("[ERROR] MtClient::Connect: {0}", ex.Message);
Close();
throw new CommunicationException($"Connection failed to service. {ex.Message}");
throw new CommunicationException(string.Format("Connection failed to service"));
}
if (_isConnected == false)
{
Log.Error("Connect: end. Connection failed.");
throw new CommunicationException("Connection failed");
}
Log.Debug("Connect: end.");
}
public void Disconnect()
{
Log.Debug("Disconnect: begin.");
Debug.WriteLine("[INFO] MtClient::Disconnect");
try
{
_isConnected = false;
lock (mClientLocker)
{
mIsConnected = false;
_proxy?.Disconnect();
if (mProxy != null)
mProxy.Disconnect();
}
}
catch (Exception ex)
{
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
Debug.WriteLine("[ERROR] MtClient::Disconnect: {0}", ex.Message);
Close();
}
Log.Debug("Disconnect: end.");
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters)
public MtResponse SendCommand(int commandType, ArrayList commandParameters)
{
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
Debug.WriteLine("[INFO] MtClient::SendCommand: commandType = {0}", commandType);
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.");
}
MtResponse result = null;
try
{
result = _proxy.SendCommand(new MtCommand(commandType, parameters));
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
result = mProxy.SendCommand(new MtCommand(commandType, commandParameters));
}
}
catch (Exception ex)
{
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
Debug.WriteLine("[ERROR] MtClient::SendCommand: {0}", ex.Message);
Close();
@@ -212,41 +177,30 @@ namespace MTApiService
return result;
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public IEnumerable<MtQuote> GetQuotes()
{
Log.Debug("GetQuotes: begin.");
Debug.WriteLine("[INFO] MtClient::GetQuotes");
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;
IEnumerable<MtQuote> result = null;
try
{
result = _proxy.GetQuotes();
lock (mClientLocker)
{
if (mProxy != null && mIsConnected == true)
result = mProxy.GetQuotes();
}
}
catch (Exception ex)
{
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
Debug.WriteLine("[ERROR] MtClient::GetQuotes: {0}", ex.Message);
Close();
throw new CommunicationException($"Service connection failed! {ex.Message}");
throw new CommunicationException("Service connection failed");
}
Log.DebugFormat("GetQuotes: end. quotes count = {0}", result?.Count);
return result;
return result;;
}
#endregion
@@ -255,70 +209,74 @@ namespace MTApiService
public void OnQuoteUpdate(MtQuote quote)
{
Log.DebugFormat("OnQuoteUpdate: begin. quote = {0}", quote);
if (quote != null)
{
if (QuoteUpdated != null)
{
QuoteUpdated(quote);
}
if (quote == null) return;
QuoteUpdated?.Invoke(quote);
Log.Debug("OnQuoteUpdate: end.");
Debug.WriteLine("[INFO] MtClient::OnQuoteUpdate: " + quote);
}
}
public void OnQuoteAdded(MtQuote quote)
{
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
Debug.WriteLine("[INFO] MtClient::OnQuoteAdded");
QuoteAdded?.Invoke(quote);
Log.Debug("OnQuoteAdded: end.");
}
public void OnQuoteRemoved(MtQuote quote)
{
Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved");
QuoteRemoved?.Invoke(quote);
Log.Debug("OnQuoteRemoved: end.");
}
public void OnServerStopped()
{
Log.Debug("OnServerStopped: begin.");
Debug.WriteLine("[INFO] MtClient::OnServerStopped");
Close();
ServerDisconnected?.Invoke(this, EventArgs.Empty);
Log.Debug("OnServerStopped: end.");
ServerDisconnected?.Invoke(this, EventArgs.Empty);
}
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 => _proxy.State == CommunicationState.Opened && _isConnected;
public bool IsConnected
{
get
{
lock (mClientLocker)
{
return mProxy.State == CommunicationState.Opened && mIsConnected == true;
}
}
}
#endregion
#region Private Methods
private void ProxyFaulted(object sender, EventArgs e)
void mProxy_Faulted(object sender, EventArgs e)
{
Log.Debug("ProxyFaulted: begin.");
Debug.WriteLine("[INFO] MtClient::mProxy_Faulted");
Close();
ServerFailed?.Invoke(this, EventArgs.Empty);
Log.Debug("ProxyFaulted: end.");
if (ServerFailed != null)
{
ServerFailed(this, EventArgs.Empty);
}
}
#endregion
@@ -327,11 +285,9 @@ namespace MTApiService
public void Dispose()
{
Log.Debug("Dispose: begin.");
Debug.WriteLine("[INFO] MtClient::Dispose");
Close();
Log.Debug("Dispose: end.");
}
#endregion
@@ -344,5 +300,11 @@ 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
}
}
+5 -5
View File
@@ -1,4 +1,8 @@
using System.Runtime.Serialization;
using System;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Collections;
namespace MTApiService
@@ -18,9 +22,5 @@ namespace MTApiService
[DataMember]
public ArrayList Parameters { get; private set; }
public override string ToString()
{
return $"CommandType = {CommandType}";
}
}
}
Executable → Regular
+3 -11
View File
@@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
namespace MTApiService
{
@@ -11,9 +10,6 @@ namespace MTApiService
public MtCommandTask(MtCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
Command = command;
}
@@ -24,7 +20,7 @@ namespace MTApiService
_responseWaiter.WaitOne(time);
lock (_locker)
{
return _result;
return _result;
}
}
@@ -36,10 +32,6 @@ namespace MTApiService
}
_responseWaiter.Set();
}
public override string ToString()
{
return $"Command = {Command}";
}
}
}
+5 -1
View File
@@ -1,4 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService
{
public class MtConnectionProfile
+11 -45
View File
@@ -1,50 +1,31 @@
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)
throw new ArgumentNullException(nameof(commandExecutor));
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
return;
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)
@@ -60,25 +41,18 @@ namespace MTApiService
{
NotifyCommandReady();
}
Log.Debug("AddCommandExecutor: end.");
}
public void RemoveCommandExecutor(MtExpert commandExecutor)
{
if (commandExecutor == null)
throw new ArgumentNullException(nameof(commandExecutor));
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
return;
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)
@@ -94,31 +68,23 @@ namespace MTApiService
{
NotifyCommandReady();
}
Log.Debug("RemoveCommandExecutor: end.");
}
public void EnqueueCommandTask(MtCommandTask task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
return;
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;
@@ -130,8 +96,6 @@ namespace MTApiService
#region Private Methods
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
var commandExecutors = new List<MtExpert>();
lock (_locker)
{
@@ -142,14 +106,10 @@ 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)
{
@@ -164,8 +124,14 @@ 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
}
}
+68 -93
View File
@@ -1,5 +1,4 @@
using System;
using log4net;
namespace MTApiService
{
@@ -7,103 +6,20 @@ 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;
}
@@ -112,7 +28,7 @@ namespace MTApiService
}
}
public int Handle { get; }
public int Handle { get; private set; }
private bool _isEnable = true;
public bool IsEnable
@@ -153,21 +69,73 @@ 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()
{
_mtHadler.SendTickToMetaTrader(Handle);
if (_mtHadler != null)
{
_mtHadler.SendTickToMetaTrader(Handle);
}
}
private void FireOnQuoteChanged(MtQuote quote)
@@ -197,5 +165,12 @@ 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
}
}
+5 -1
View File
@@ -1,4 +1,8 @@
using System.Runtime.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
{
+5 -1
View File
@@ -1,4 +1,8 @@
using System.Runtime.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
{
+6 -1
View File
@@ -1,4 +1,9 @@
using System.Runtime.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace MTApiService
{
+5 -1
View File
@@ -1,4 +1,8 @@
using System.Runtime.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
{
+18 -15
View File
@@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService
@@ -7,34 +10,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; }
}
}
+84 -90
View File
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Diagnostics;
@@ -7,12 +9,12 @@ namespace MTApiService
{
public class MtRegistryManager
{
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";
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";
#region Public Methods
public static IEnumerable<MtConnectionProfile> LoadConnectionProfiles()
@@ -51,12 +53,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(AppName, true);
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
if (appRegKey != null)
{
using (appRegKey)
@@ -71,7 +73,7 @@ namespace MTApiService
{
using (numberKey)
{
signature = numberKey.GetValue(SignatureRegvalueName).ToString();
signature = numberKey.GetValue(SIGNATURE_REGVALUE_NAME).ToString();
}
}
}
@@ -92,7 +94,7 @@ namespace MTApiService
return null;
}
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
if (softwareRgKey == null)
return null;
@@ -103,33 +105,35 @@ namespace MTApiService
{
//app name
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey != null)
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
if (appRegKey == null)
{
using (appRegKey)
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
}
using (appRegKey)
{
//account name
var accountKey = appRegKey.OpenSubKey(accountName, true);
if (accountKey == null)
{
//account name
var accountKey = appRegKey.OpenSubKey(accountName, true) ?? appRegKey.CreateSubKey(accountName);
accountKey = appRegKey.CreateSubKey(accountName);
}
if (accountKey != null)
using (accountKey)
{
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true);
if (numberKey == null)
{
using (accountKey)
{
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true) ??
accountKey.CreateSubKey(accountNumber);
numberKey = accountKey.CreateSubKey(accountNumber);
}
if (numberKey != null)
{
using (numberKey)
{
numberKey.SetValue(SignatureRegvalueName, signature);
using (numberKey)
{
numberKey.SetValue(SIGNATURE_REGVALUE_NAME, signature);
retVal = numberKey.ToString();
}
}
}
retVal = numberKey.ToString();
}
}
}
@@ -138,19 +142,20 @@ namespace MTApiService
return retVal;
}
public static bool ExportKey(string regKey, string savePath)
public static bool ExportKey(string RegKey, string SavePath)
{
var path = $"\"{savePath}\"";
var key = $"\"{regKey}\"";
string path = "\"" + SavePath + "\"";
string key = "\"" + RegKey + "\"";
var proc = new Process();
Process proc = new Process();
try
{
proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false;
proc = Process.Start("regedit.exe", "/e " + path + " " + key + "");
proc?.WaitForExit();
if (proc != null)
proc.WaitForExit();
}
catch(Exception)
{
@@ -158,7 +163,8 @@ namespace MTApiService
}
finally
{
proc?.Dispose();
if (proc != null)
proc.Dispose();
}
return true;
@@ -171,38 +177,33 @@ 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(AppName, true);
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
if (appRegKey != null)
{
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey != null)
{
using (profilesRegKey)
{
profiles = new List<MtConnectionProfile>();
foreach (var profileNameKey in profilesRegKey.GetSubKeyNames())
foreach (string profileNameKey in profilesRegKey.GetSubKeyNames())
{
var tempKey = profilesRegKey.OpenSubKey(profileNameKey);
if (tempKey != null)
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileNameKey))
{
using (tempKey)
{
var profile = new MtConnectionProfile(profileNameKey)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
var profile = new MtConnectionProfile(profileNameKey);
profiles.Add(profile);
}
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
profiles.Add(profile);
}
}
}
@@ -219,33 +220,27 @@ 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(AppName, true);
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
if (appRegKey != null)
{
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey != null)
{
using (profilesRegKey)
{
var tempKey = profilesRegKey.OpenSubKey(profileName);
if (tempKey != null)
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileName))
{
using (tempKey)
{
profile = new MtConnectionProfile(profileName)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
profile = new MtConnectionProfile(profileName);
}
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
}
}
}
@@ -259,7 +254,7 @@ namespace MTApiService
private static void SaveConnectionProfileToRegistry(MtConnectionProfile profile)
{
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
if (softwareRgKey == null)
return;
@@ -267,30 +262,29 @@ namespace MTApiService
using (softwareRgKey)
{
//app name
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey != null)
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
if (appRegKey == null)
{
using (appRegKey)
{
//ConnectionProfiles key
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true) ??
appRegKey.CreateSubKey(ProfilesRegkey);
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
}
if (profilesRegKey != null)
using (appRegKey)
{
//ConnectionProfiles key
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey == null)
{
profilesRegKey = appRegKey.CreateSubKey(PROFILES_REGKEY);
}
using (profilesRegKey)
{
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
using (profileKey)
{
using (profilesRegKey)
{
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
if (profileKey != null)
{
using (profileKey)
{
profileKey.SetValue(HostRegvalueName, profile.Host);
profileKey.SetValue(PortRegvalueName, profile.Port);
}
}
}
profileKey.SetValue(HOST_REGVALUE_NAME, profile.Host);
profileKey.SetValue(PORT_REGVALUE_NAME, profile.Port);
}
}
}
@@ -299,19 +293,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(AppName, true);
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
if (appRegKey == null)
return;
using (appRegKey)
{
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey == null)
return;
+2 -94
View File
@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Collections;
using System.Globalization;
namespace MTApiService
{
@@ -20,8 +21,6 @@ namespace MTApiService
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
typeof(MtResponseMqlBookInfoArray)};
}
public abstract object GetValue();
}
[DataContract]
@@ -34,13 +33,6 @@ namespace MTApiService
[DataMember]
public int Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -53,13 +45,6 @@ namespace MTApiService
[DataMember]
public long Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -72,13 +57,6 @@ namespace MTApiService
[DataMember]
public ulong Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -91,13 +69,6 @@ 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]
@@ -110,13 +81,6 @@ namespace MTApiService
[DataMember]
public string Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value;
}
}
[DataContract]
@@ -129,13 +93,6 @@ namespace MTApiService
[DataMember]
public bool Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -148,13 +105,6 @@ namespace MTApiService
[DataMember]
public double[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -167,13 +117,6 @@ namespace MTApiService
[DataMember]
public int[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -186,13 +129,6 @@ namespace MTApiService
[DataMember]
public long[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -205,13 +141,6 @@ namespace MTApiService
[DataMember]
public ArrayList Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -224,13 +153,6 @@ namespace MTApiService
[DataMember]
public MtMqlRates[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -243,13 +165,6 @@ namespace MTApiService
[DataMember]
public MtMqlTick Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
@@ -262,13 +177,6 @@ namespace MTApiService
[DataMember]
public MtMqlBookInfo[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
}
+105 -195
View File
@@ -3,26 +3,17 @@ 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 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>();
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec
private const int STOP_EXPERT_INTERVAL = 1000; // 1 sec
#endregion
#region ctor
@@ -34,126 +25,99 @@ namespace MTApiService
#endregion
#region Properties
public int Port { get; }
public int Port { get; private set; }
#endregion
#region Public Methods
public void Start()
{
Log.Debug("Start: begin");
var hostsInitialized = InitHosts(Port);
Log.DebugFormat("Start: end. hostsInitialized = {0}", hostsInitialized);
if (hostsInitialized == false)
{
Debug.WriteLine("Start: InitHosts failed. ");
}
}
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
var localUrl = CreateConnectionAddress(null, port, true);
var localServiceHost = CreateServiceHost(localUrl, true);
string localUrl = CreateConnectionAddress(null, port, true);
ServiceHost localServiceHost = CreateServiceHost(localUrl, true);
if (localServiceHost != null)
{
_hosts.Add(localServiceHost);
}
//init network hosts
var dnsHostName = Dns.GetHostName();
var ips = Dns.GetHostEntry(dnsHostName);
if (ips == null)
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
if (ips != null)
{
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)
foreach (IPAddress ipAddress in ips.AddressList)
{
var ip = ipAddress.ToString();
var networkUrl = CreateConnectionAddress(ip, port, false);
var serviceHost = CreateServiceHost(networkUrl, false);
if (serviceHost != null)
if (ipAddress != null)
{
_hosts.Add(serviceHost);
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);
}
}
}
}
}
count = _hosts.Count;
}
Log.DebugFormat("InitHosts: end. Host's count = {0}", count);
return true;
}
private ServiceHost CreateServiceHost(string serverUrlAdress, bool local)
{
Log.DebugFormat("CreateServiceHost: begin. serverUrlAdress = {0}; local = {1}", serverUrlAdress, local);
if (serverUrlAdress == null)
ServiceHost serviceHost = null;
if (serverUrlAdress != null)
{
Log.Warn("CreateServiceHost: end. serverUrlAdress is not defined");
return null;
}
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
ServiceHost serviceHost;
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
serviceHost.Open();
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
serviceHost.Open();
}
catch(Exception e)
{
Debug.WriteLine("CreateServiceHost: Create ServiceHost failed. " + e.Message);
}
}
catch(Exception e)
{
Log.ErrorFormat("CreateServiceHost: Error! {0}", e.Message);
serviceHost = null;
}
Log.Debug("CreateServiceHost: end.");
return serviceHost;
}
public void AddExpert(MtExpert expert)
{
Log.DebugFormat("AddExpert: begin. expert {0}", expert);
if (expert == null)
if (expert != null)
{
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);
}
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
@@ -162,30 +126,25 @@ namespace MTApiService
public MtResponse SendCommand(MtCommand command)
{
Log.DebugFormat("SendCommand: begin. command {0}", command);
MtResponse response = null;
if (command == null)
if (command != null)
{
Log.Warn("SendCommand: end. command is not defined");
return null;
var task = new MtCommandTask(command);
_executorManager.EnqueueCommandTask(task);
//wait for execute command in MetaTrader
response = task.WaitResult(WAIT_RESPONSE_TIME);
}
var task = new MtCommandTask(command);
_executorManager.EnqueueCommandTask(task);
//wait for execute command in MetaTrader
var response = task.WaitResult(WaitResponseTime);
return response;
}
public List<MtQuote> GetQuotes()
public IEnumerable<MtQuote> GetQuotes()
{
Log.Debug("GetQuotes: called");
lock (_experts)
{
return _experts.Select(s => s.Quote).ToList();
return (from s in _experts select s.Quote);
}
}
@@ -194,131 +153,99 @@ namespace MTApiService
#region Private Methods
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Log.DebugFormat("stopTimer_Elapsed: begin");
int expertsCount;
var expertsCount = 0;
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) return;
stopTimer.Stop();
stopTimer.Elapsed -= stopTimer_Elapsed;
Log.DebugFormat("stopTimer_Elapsed: end");
if (stopTimer != null)
{
stopTimer.Stop();
stopTimer.Elapsed -= stopTimer_Elapsed;
}
}
private static string CreateConnectionAddress(string host, int port, bool local)
private 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)
if (local == true)
{
//by Pipe
connectionAddress = "net.pipe://localhost/MtApiService_" + port;
connectionAddress = "net.pipe://localhost/MtApiService_" + port.ToString();
}
else
{
//by Socket
if (host != null)
{
connectionAddress = "net.tcp://" + host + ":" + port + "/MtApiService";
}
connectionAddress = "net.tcp://" + host.ToString() + ":" + port.ToString() + "/MtApiService";
}
}
Log.DebugFormat("CreateConnectionAddress: end. connectionAddress = {0}", connectionAddress);
return connectionAddress;
}
private static Binding CreateConnectionBinding(bool local)
{
Log.DebugFormat("CreateConnectionBinding: begin. local = {0}", local);
Binding connectionBinding = null;
Binding connectionBinding;
if (local)
if (local == true)
{
//by Pipe
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
}
};
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
bind.MaxReceivedMessageSize = 2147483647;
bind.MaxBufferSize = 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)
{
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
}
};
var bind = new NetTcpBinding(SecurityMode.None);
bind.MaxReceivedMessageSize = 2147483647;
bind.MaxBufferSize = 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
{
@@ -327,18 +254,15 @@ namespace MTApiService
host.Close();
}
}
catch (TimeoutException ex)
catch (TimeoutException)
{
Log.ErrorFormat("Stop: TimeoutException - {0}", ex.Message);
foreach (var host in _hosts)
{
host.Abort();
}
}
catch (Exception ex)
catch (Exception)
{
Log.ErrorFormat("Stop: Exception - {0}", ex.Message);
// ignored
}
finally
@@ -348,27 +272,20 @@ namespace MTApiService
}
FireOnStopped();
Log.Debug("Stop: end.");
}
private void expert_Deinited(object sender, EventArgs e)
{
Log.Debug("expert_Deinited: begin.");
var expert = sender as MtExpert;
if (expert == null)
{
Log.Warn("expert_Deinited: end. Expert is not defined.");
if (sender == null)
return;
}
int expertsCount;
var expert = (MtExpert)sender;
var expertsCount = 0;
lock (_experts)
{
_experts.Remove(expert);
expertsCount = _experts.Count;
expertsCount = _experts.Count();
}
_executorManager.RemoveCommandExecutor(expert);
@@ -382,29 +299,19 @@ namespace MTApiService
{
var stopTimer = new System.Timers.Timer();
stopTimer.Elapsed += stopTimer_Elapsed;
stopTimer.Interval = StopExpertInterval;
stopTimer.Interval = STOP_EXPERT_INTERVAL;
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()
@@ -421,13 +328,16 @@ 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
}
}
+61 -104
View File
@@ -1,35 +1,30 @@
using System;
using System.Collections.Generic;
using log4net;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Net;
using System.Diagnostics;
namespace MTApiService
{
public class MtServerInstance
{
#region Fields
private const string LogProfileName = "MtApiService";
#region Init_Instance
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
static readonly MtServerInstance mInstance = new MtServerInstance();
private MtServerInstance()
{
LogConfigurator.Setup(LogProfileName);
{
}
static MtServerInstance()
{
}
{
}
public static MtServerInstance GetInstance()
{
return Instance;
return mInstance;
}
#endregion
@@ -38,23 +33,20 @@ namespace MTApiService
#region Public Methods
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
Debug.WriteLine("MtApiServerInstance::InitExpert: symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
MtServer server;
lock (_servers)
MtServer server = null;
lock (mServersDictionary)
{
if (_servers.ContainsKey(port))
if (mServersDictionary.ContainsKey(port))
{
server = _servers[port];
server = mServersDictionary[port];
}
else
{
server = new MtServer(port);
server.Stopped += server_Stopped;
_servers[port] = server;
server.Stopped += new EventHandler(server_Stopped);
mServersDictionary[port] = server;
server.Start();
}
@@ -62,172 +54,137 @@ namespace MTApiService
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
lock (_experts)
lock (mExpertsDictionary)
{
_experts[expert.Handle] = expert;
mExpertsDictionary[expert.Handle] = expert;
}
server.AddExpert(expert);
Log.Info("InitExpert: end");
}
public void DeinitExpert(int expertHandle)
{
Log.InfoFormat("DeinitExpert: begin. expertHandle = {0}", expertHandle);
Debug.WriteLine("MtApiServerInstance::DeinitExpert: expertHandle = {0}", expertHandle);
MtExpert expert = null;
lock (_experts)
lock (mExpertsDictionary)
{
if (_experts.ContainsKey(expertHandle))
if (mExpertsDictionary.ContainsKey(expertHandle) == true)
{
expert = _experts[expertHandle];
_experts.Remove(expertHandle);
expert = mExpertsDictionary[expertHandle];
mExpertsDictionary.Remove(expertHandle);
}
}
if (expert != null)
{
expert.Deinit();
}
else
{
Log.WarnFormat("DeinitExpert: expert with id {0} has not been found.", expertHandle);
}
Log.Info("DeinitExpert: end");
}
}
public void SendQuote(int expertHandle, string symbol, double bid, double ask)
{
Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
Debug.WriteLine("MtApiServerInstance::SendQuote: enter. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
MtExpert expert;
lock (_experts)
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = _experts[expertHandle];
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.Quote = new MtQuote(symbol, bid, ask);
}
else
{
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendQuote: end");
Debug.WriteLine("MtApiServerInstance::SendQuote: finish.");
}
public void SendEvent(int expertHandle, int eventType, string payload)
{
Log.DebugFormat("SendEvent: begin. eventType = {0}, payload = {1}", eventType, payload);
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload);
MtExpert expert;
lock (_experts)
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = _experts[expertHandle];
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.SendEvent(new MtEvent(eventType, payload));
}
else
{
Log.WarnFormat("SendEvent: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendEvent: end");
Debug.WriteLine("MtApiServerInstance::SendEvent: finished");
}
public void SendResponse(int expertHandle, MtResponse response)
{
Log.DebugFormat("SendResponse: begin. id = {0}, response = {1}", expertHandle, response);
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response);
MtExpert expert;
lock (_experts)
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = _experts[expertHandle];
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.SendResponse(response);
}
else
{
Log.WarnFormat("SendResponse: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendResponse: end");
Debug.WriteLine("MtApiServerInstance::SendResponse: finish");
}
public int GetCommandType(int expertHandle)
{
Log.DebugFormat("GetCommandType: begin. expertHandle = {0}", expertHandle);
Debug.WriteLine("MtApiServerInstance::GetCommandType: expertHandle = {0}", expertHandle);
MtExpert expert;
lock (_experts)
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = _experts[expertHandle];
expert = mExpertsDictionary[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetCommandType: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandType() ?? 0;
Log.DebugFormat("GetCommandType: end. retval = {0}", retval);
return retval;
return (expert != null) ? expert.GetCommandType() : 0;
}
public object GetCommandParameter(int expertHandle, int index)
{
Log.DebugFormat("GetCommandParameter: begin. expertHandle = {0}, index = {1}", expertHandle, index);
Debug.WriteLine("MtApiServerInstance::GetCommandParameter: expertHandle = {0}, index = {1}", expertHandle, index);
MtExpert expert;
lock (_experts)
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = _experts[expertHandle];
expert = mExpertsDictionary[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetCommandParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandParameter(index);
Log.DebugFormat("GetCommandParameter: end. retval = {0}", retval);
return retval;
return (expert != null) ? expert.GetCommandParameter(index) : null;
}
#endregion
#region Private Methods
private void server_Stopped(object sender, EventArgs e)
{
var server = (MtServer)sender;
MtServer server = (MtServer)sender;
server.Stopped -= server_Stopped;
var port = server.Port;
Log.InfoFormat("server_Stopped: port = {0}", port);
lock (_servers)
lock (mServersDictionary)
{
if (_servers.ContainsKey(port))
if (mServersDictionary.ContainsKey(port))
{
_servers.Remove(port);
mServersDictionary.Remove(port);
}
}
}
#endregion
#region Fields
private readonly MtRegistryManager mConnectionManager = new MtRegistryManager();
private readonly Dictionary<int, MtServer> mServersDictionary = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> mExpertsDictionary = new Dictionary<int, MtExpert>();
#endregion
}
}
+48 -99
View File
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;
using log4net;
namespace MTApiService
{
@@ -19,7 +18,7 @@ namespace MTApiService
MtResponse SendCommand(MtCommand command);
[OperationContract]
List<MtQuote> GetQuotes();
IEnumerable<MtQuote> GetQuotes();
}
[ServiceContract]
@@ -47,149 +46,107 @@ 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(nameof(serverCallback));
throw new ArgumentNullException("serverCallback");
_server = serverCallback;
mServer = serverCallback;
}
#region IMtApi
public bool Connect()
{
Log.Debug("Connect: begin");
bool connected = false;
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
IMtApiCallback 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
{
if (_clientCallbacks.Contains(callback) == false)
_clientCallbacks.Add(callback);
mClientsLocker.AcquireWriterLock(10000);
connected = true;
try
{
if (mClientCallbacks.Contains(callback) == false)
mClientCallbacks.Add(callback);
connected = true;
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
}
finally
catch (ApplicationException)
{
_clientsLocker.ReleaseWriterLock();
}
}
catch (ApplicationException ex)
{
Log.ErrorFormat("Connect: ApplicationException - {0}", ex.Message);
}
Log.DebugFormat("Connect: end. connected = {0}", connected);
return connected;
}
public void Disconnect()
{
Log.Debug("Disconnect: begin");
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
if (callback == null)
if (callback != null)
{
Log.Warn("Disconnect: end. Callback is not definded.");
return;
}
try
{
_clientsLocker.AcquireWriterLock(10000);
try
{
_clientCallbacks.Remove(callback);
}
finally
{
_clientsLocker.ReleaseWriterLock();
}
}
catch (ApplicationException ex)
{
Log.ErrorFormat("Disconnect: ApplicationException - {0}", ex.Message);
}
mClientsLocker.AcquireWriterLock(10000);
Log.Debug("Disconnect: end.");
try
{
mClientCallbacks.Remove(callback);
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
}
catch (ApplicationException)
{
}
}
}
public MtResponse SendCommand(MtCommand command)
{
Log.DebugFormat("SendCommand: called. command = {0}", command);
return _server.SendCommand(command);
return mServer.SendCommand(command);
}
public List<MtQuote> GetQuotes()
public IEnumerable<MtQuote> GetQuotes()
{
Log.Debug("GetQuotes: called.");
return _server.GetQuotes();
return mServer.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
@@ -197,26 +154,22 @@ namespace MTApiService
private void ExecuteCallbackAction(Action<IMtApiCallback> action)
{
Log.Debug("ExecuteCallbackAction: begin.");
try
{
_clientsLocker.AcquireReaderLock(2000);
mClientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientCallbacks = null;
try
{
foreach (var callback in _clientCallbacks)
foreach (var callback in mClientCallbacks)
{
try
{
action(callback);
}
catch (Exception ex)
catch (Exception)
{
Log.ErrorFormat("ExecuteCallbackAction: Exception - {0}", ex.Message);
if (crashedClientCallbacks == null)
crashedClientCallbacks = new List<IMtApiCallback>();
@@ -226,33 +179,29 @@ namespace MTApiService
if (crashedClientCallbacks != null)
{
Log.WarnFormat("ExecuteCallbackAction: crashed callback count = {0}", crashedClientCallbacks.Count);
foreach (var crashedCallback in crashedClientCallbacks)
{
_clientCallbacks.Remove(crashedCallback);
mClientCallbacks.Remove(crashedCallback);
}
}
}
finally
{
_clientsLocker.ReleaseReaderLock();
mClientsLocker.ReleaseReaderLock();
}
}
catch (ApplicationException ex)
catch (ApplicationException)
{
Log.ErrorFormat("ExecuteCallbackAction: ApplicationException - {0}", ex.Message);
//TODO: add logging
}
Log.Debug("ExecuteCallbackAction: end.");
}
#endregion
#region Fields
private readonly IMtApiServer _server;
private readonly List<IMtApiCallback> _clientCallbacks = new List<IMtApiCallback>();
private readonly ReaderWriterLock _clientsLocker = new ReaderWriterLock();
private readonly IMtApiServer mServer;
private readonly List<IMtApiCallback> mClientCallbacks = new List<IMtApiCallback>();
private readonly ReaderWriterLock mClientsLocker = new ReaderWriterLock();
#endregion
}
}
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.22.0")]
[assembly: AssemblyFileVersion("1.0.22.0")]
[assembly: AssemblyVersion("1.0.21.0")]
[assembly: AssemblyFileVersion("1.0.21.0")]
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="2.13.0307" targetFramework="net40" />
<package id="log4net" version="2.0.5" targetFramework="net40" />
<package id="MSBuild.ILMerge.Task" version="1.0.5" targetFramework="net40" />
</packages>
+2
View File
@@ -11,11 +11,13 @@ 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);
}
+15
View File
@@ -255,4 +255,19 @@ int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
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;
}
+2 -1
View File
@@ -14,4 +14,5 @@ EXPORTS initExpert
getCommandType
getIntValue
getDoubleValue
getStringValue
getStringValue
getBooleanValue
+201 -178
View File
@@ -15,34 +15,25 @@ namespace MtApi
public sealed class MtApiClient
{
private volatile bool _isBacktestingMode;
private const int DoubleArrayLimit = 64800;
private volatile bool IsBacktestingMode = false;
#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()
{
LogConfigurator.Setup(LogProfileName);
_client.QuoteAdded += _client_QuoteAdded;
_client.QuoteRemoved += _client_QuoteRemoved;
_client.QuoteUpdated += _client_QuoteUpdated;
_client.ServerDisconnected += _client_ServerDisconnected;
_client.ServerFailed += _client_ServerFailed;
_client.QuoteAdded += mClient_QuoteAdded;
_client.QuoteRemoved += mClient_QuoteRemoved;
_client.QuoteUpdated += mClient_QuoteUpdated;
_client.ServerDisconnected += mClient_ServerDisconnected;
_client.ServerFailed += mClient_ServerFailed;
_client.MtEventReceived += _client_MtEventReceived;
}
#endregion
@@ -55,8 +46,15 @@ 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>
@@ -83,16 +81,12 @@ namespace MtApi
///</summary>
public IEnumerable<MtQuote> GetQuotes()
{
IEnumerable<MTApiService.MtQuote> quotes;
lock (_client)
{
quotes = _client.GetQuotes();
}
return quotes?.Select(q => q.Convert());
var quotes = _client.GetQuotes();
return quotes != null ? (from q in quotes select q.Convert()) : null;
}
#endregion
#region Properties
#region Properties
///<summary>
///Connection status of MetaTrader API.
@@ -180,7 +174,7 @@ namespace MtApi
public double OrderOpenPrice(int ticket)
{
var commandParameters = new ArrayList { ticket };
var retVal = SendCommand<double>(MtCommandType.OrderOpenPriceByTicket, commandParameters);
double retVal = SendCommand<double>(MtCommandType.OrderOpenPriceByTicket, commandParameters);
return retVal;
}
@@ -225,7 +219,7 @@ namespace MtApi
[Obsolete("OrderType is deprecated, please use GetOrder instead.")]
public TradeOperation OrderType()
{
var retVal = SendCommand<int>(MtCommandType.OrderType, null);
int retVal = SendCommand<int>(MtCommandType.OrderType, null);
return (TradeOperation)retVal;
}
@@ -256,7 +250,7 @@ namespace MtApi
Expiration = MtApiTimeConverter.ConvertToMtTime(expiration),
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrowColor)
});
return response?.Ticket ?? -1;
return response != null ? response.Ticket : -1;
}
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
@@ -284,7 +278,7 @@ namespace MtApi
public int OrderSend(string symbol, TradeOperation cmd, double volume, string price, int slippage, double stoploss, double takeprofit)
{
double dPrice;
double dPrice = 0;
return double.TryParse(price, out dPrice) ?
OrderSend(symbol, cmd, volume, dPrice, slippage, stoploss, takeprofit, null, 0, DateTime.MinValue, Color.Empty) : 0;
}
@@ -322,7 +316,7 @@ namespace MtApi
Comment = comment,
Magic = magic,
});
return response?.Ticket ?? -1;
return response != null ? response.Ticket : -1;
}
public int OrderSendSell(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic)
@@ -338,7 +332,7 @@ namespace MtApi
Comment = comment,
Magic = magic,
});
return response?.Ticket ?? -1;
return response != null ? response.Ticket : -1;
}
public bool OrderClose(int ticket, double lots, double price, int slippage, Color color)
@@ -427,7 +421,7 @@ namespace MtApi
return response != null;
}
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration, Color arrowColor)
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration, Color arrow_color)
{
var response = SendRequest<ResponseBase>(new OrderModifyRequest
{
@@ -436,7 +430,7 @@ namespace MtApi
Stoploss = stoploss,
Takeprofit = takeprofit,
Expiration = MtApiTimeConverter.ConvertToMtTime(expiration),
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrowColor)
ArrowColor = MtApiColorConverter.ConvertToMtColor(arrow_color)
});
return response != null;
}
@@ -488,7 +482,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?.Order;
return response != null ? response.Order : null;
}
public List<MtOrder> GetOrders(OrderSelectSource pool)
@@ -658,6 +652,26 @@ namespace MtApi
#endregion
#region Symbols
public int SymbolsTotal(bool selected)
{
var commandParameters = new ArrayList { selected };
return SendCommand<int>(MtCommandType.SymbolsTotal, commandParameters);
}
public string SymbolName(int pos, bool selected)
{
var commandParameters = new ArrayList { pos, selected };
return SendCommand<string>(MtCommandType.SymbolName, commandParameters);
}
public bool SymbolSelect(string name, bool select)
{
var commandParameters = new ArrayList { name, select };
return SendCommand<bool>(MtCommandType.SymbolSelect, commandParameters);
}
#endregion
#region Common Function
public void Alert(string msg)
@@ -718,15 +732,15 @@ namespace MtApi
return SendCommand<bool>(MtCommandType.SendFTP, commandParameters);
}
public bool SendFTP(string filename, string ftpPath)
public bool SendFTP(string filename, string ftp_path)
{
var commandParameters = new ArrayList { filename, ftpPath };
var commandParameters = new ArrayList { filename, ftp_path };
return SendCommand<bool>(MtCommandType.SendFTPA, commandParameters);
}
public void SendMail(string subject, string someText)
public void SendMail(string subject, string some_text)
{
var commandParameters = new ArrayList { subject, someText };
var commandParameters = new ArrayList { subject, some_text };
SendCommand<object>(MtCommandType.SendMail, commandParameters);
}
@@ -894,15 +908,15 @@ namespace MtApi
return MtApiTimeConverter.ConvertFromMtTime(commandResponse);
}
public bool GlobalVariableSetOnCondition(string name, double value, double checkValue)
public bool GlobalVariableSetOnCondition(string name, double value, double check_value)
{
var commandParameters = new ArrayList { name, value, checkValue };
var commandParameters = new ArrayList { name, value, check_value };
return SendCommand<bool>(MtCommandType.GlobalVariableSetOnCondition, commandParameters);
}
public int GlobalVariablesDeleteAll(string prefixName)
public int GlobalVariablesDeleteAll(string prefix_name)
{
var commandParameters = new ArrayList { prefixName };
var commandParameters = new ArrayList { prefix_name };
return SendCommand<int>(MtCommandType.GlobalVariableSetOnCondition, commandParameters);
}
@@ -926,15 +940,15 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iAD, commandParameters);
}
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)
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)
{
var commandParameters = new ArrayList { symbol, timeframe, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, maMethod, appliedPrice, mode, 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 };
return SendCommand<double>(MtCommandType.iAlligator, commandParameters);
}
public double iADX(string symbol, int timeframe, int period, int appliedPrice, int mode, int shift)
public double iADX(string symbol, int timeframe, int period, int applied_price, int mode, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, mode, shift };
return SendCommand<double>(MtCommandType.iADX, commandParameters);
}
@@ -950,50 +964,50 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iAO, commandParameters);
}
public double iBearsPower(string symbol, int timeframe, int period, int appliedPrice, int shift)
public double iBearsPower(string symbol, int timeframe, int period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
return SendCommand<double>(MtCommandType.iBearsPower, commandParameters);
}
public double iBands(string symbol, int timeframe, int period, int deviation, int bandsShift, int appliedPrice, int mode, int shift)
public double iBands(string symbol, int timeframe, int period, int deviation, int bands_shift, int applied_price, int mode, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, deviation, bandsShift, appliedPrice, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, deviation, bands_shift, applied_price, mode, shift };
return SendCommand<double>(MtCommandType.iBands, commandParameters);
}
public double iBandsOnArray(double[] array, int total, int period, int deviation, int bandsShift, int mode, int shift)
public double iBandsOnArray(double[] array, int total, int period, int deviation, int bands_shift, int mode, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(period);
commandParameters.Add(deviation);
commandParameters.Add(bandsShift);
commandParameters.Add(bands_shift);
commandParameters.Add(mode);
commandParameters.Add(shift);
return SendCommand<double>(MtCommandType.iBandsOnArray, commandParameters);
}
public double iBullsPower(string symbol, int timeframe, int period, int appliedPrice, int shift)
public double iBullsPower(string symbol, int timeframe, int period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
return SendCommand<double>(MtCommandType.iBullsPower, commandParameters);
}
public double iCCI(string symbol, int timeframe, int period, int appliedPrice, int shift)
public double iCCI(string symbol, int timeframe, int period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
return SendCommand<double>(MtCommandType.iCCI, commandParameters);
}
public double iCCIOnArray(double[] array, int total, int period, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] { });
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(period);
commandParameters.Add(shift);
@@ -1013,7 +1027,7 @@ namespace MtApi
Params = new ArrayList(parameters),
ParamsType = ICustomRequest.ParametersType.Int
});
return response?.Value ?? double.NaN;
return response != null ? response.Value : double.NaN;
}
public double iCustom(string symbol, int timeframe, string name, double[] parameters, int mode, int shift)
@@ -1028,7 +1042,7 @@ namespace MtApi
Params = new ArrayList(parameters),
ParamsType = ICustomRequest.ParametersType.Double
});
return response?.Value ?? double.NaN;
return response != null ? response.Value : double.NaN;
}
public double iCustom(string symbol, int timeframe, string name, int mode, int shift)
@@ -1041,7 +1055,7 @@ namespace MtApi
Mode = mode,
Shift = shift
});
return response?.Value ?? double.NaN;
return response != null ? response.Value : double.NaN;
}
public double iDeMarker(string symbol, int timeframe, int period, int shift)
@@ -1050,21 +1064,21 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iDeMarker, commandParameters);
}
public double iEnvelopes(string symbol, int timeframe, int maPeriod, int maMethod, int maShift, int appliedPrice, double deviation, int mode, int shift)
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)
{
var commandParameters = new ArrayList { symbol, timeframe, maPeriod, maMethod, maShift, appliedPrice, deviation, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift };
return SendCommand<double>(MtCommandType.iEnvelopes, commandParameters);
}
public double iEnvelopesOnArray(double[] array, int total, int maPeriod, int maMethod, int maShift, double deviation, int mode, int shift)
public double iEnvelopesOnArray(double[] array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(maPeriod);
commandParameters.Add(maMethod);
commandParameters.Add(maShift);
commandParameters.Add(ma_period);
commandParameters.Add(ma_method);
commandParameters.Add(ma_shift);
commandParameters.Add(deviation);
commandParameters.Add(mode);
commandParameters.Add(shift);
@@ -1072,9 +1086,9 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iEnvelopesOnArray, commandParameters);
}
public double iForce(string symbol, int timeframe, int period, int maMethod, int appliedPrice, int shift)
public double iForce(string symbol, int timeframe, int period, int ma_method, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, maMethod, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, ma_method, applied_price, shift };
return SendCommand<double>(MtCommandType.iForce, commandParameters);
}
@@ -1084,15 +1098,15 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iFractals, commandParameters);
}
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)
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)
{
var commandParameters = new ArrayList { symbol, timeframe, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, maMethod, appliedPrice, mode, 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 };
return SendCommand<double>(MtCommandType.iGator, commandParameters);
}
public double iIchimoku(string symbol, int timeframe, int tenkanSen, int kijunSen, int senkouSpanB, int mode, int shift)
public double iIchimoku(string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, tenkanSen, kijunSen, senkouSpanB, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift };
return SendCommand<double>(MtCommandType.iIchimoku, commandParameters);
}
@@ -1102,17 +1116,17 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iBWMFI, commandParameters);
}
public double iMomentum(string symbol, int timeframe, int period, int appliedPrice, int shift)
public double iMomentum(string symbol, int timeframe, int period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
return SendCommand<double>(MtCommandType.iMomentum, commandParameters);
}
public double iMomentumOnArray(double[] array, int total, int period, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(period);
commandParameters.Add(shift);
@@ -1126,41 +1140,41 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iMFI, commandParameters);
}
public double iMA(string symbol, int timeframe, int period, int maShift, int maMethod, int appliedPrice, int shift)
public double iMA(string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, maShift, maMethod, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, ma_shift, ma_method, applied_price, shift };
return SendCommand<double>(MtCommandType.iMA, commandParameters);
}
public double iMAOnArray(double[] array, int total, int period, int maShift, int maMethod, int shift)
double iMAOnArray(double[] array, int total, int period, int ma_shift, int ma_method, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(period);
commandParameters.Add(maShift);
commandParameters.Add(maMethod);
commandParameters.Add(ma_shift);
commandParameters.Add(ma_method);
commandParameters.Add(shift);
return SendCommand<double>(MtCommandType.iMAOnArray, commandParameters);
}
public double iOsMA(string symbol, int timeframe, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, int appliedPrice, int shift)
public double iOsMA(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, fastEmaPeriod, slowEmaPeriod, signalPeriod, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, shift };
return SendCommand<double>(MtCommandType.iOsMA, commandParameters);
}
public double iMACD(string symbol, int timeframe, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, int appliedPrice, int mode, int shift)
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)
{
var commandParameters = new ArrayList { symbol, timeframe, fastEmaPeriod, slowEmaPeriod, signalPeriod, appliedPrice, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift };
return SendCommand<double>(MtCommandType.iMACD, commandParameters);
}
public double iOBV(string symbol, int timeframe, int appliedPrice, int shift)
public double iOBV(string symbol, int timeframe, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, applied_price, shift };
return SendCommand<double>(MtCommandType.iOBV, commandParameters);
}
@@ -1170,17 +1184,17 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iSAR, commandParameters);
}
public double iRSI( string symbol, int timeframe, int period, int appliedPrice, int shift)
public double iRSI( string symbol, int timeframe, int period, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, period, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, period, applied_price, shift };
return SendCommand<double>(MtCommandType.iRSI, commandParameters);
}
public double iRSIOnArray(double[] array, int total, int period, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(period);
commandParameters.Add(shift);
@@ -1194,29 +1208,29 @@ namespace MtApi
return SendCommand<double>(MtCommandType.iRVI, commandParameters);
}
public double iStdDev(string symbol, int timeframe, int maPeriod, int maShift, int maMethod, int appliedPrice, int shift)
public double iStdDev(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, maPeriod, maShift, maMethod, appliedPrice, shift };
var commandParameters = new ArrayList { symbol, timeframe, ma_period, ma_shift, ma_method, applied_price, shift };
return SendCommand<double>(MtCommandType.iStdDev, commandParameters);
}
public double iStdDevOnArray(double[] array, int total, int maPeriod, int maShift, int maMethod, int shift)
public double iStdDevOnArray(double[] array, int total, int ma_period, int ma_shift, int ma_method, int shift)
{
var arraySize = array?.Length ?? 0;
int arraySize = array != null ? array.Length : 0;
var commandParameters = new ArrayList { arraySize };
commandParameters.AddRange(array ?? new double[] {});
commandParameters.AddRange(array);
commandParameters.Add(total);
commandParameters.Add(maPeriod);
commandParameters.Add(maShift);
commandParameters.Add(maMethod);
commandParameters.Add(ma_period);
commandParameters.Add(ma_shift);
commandParameters.Add(ma_method);
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 priceField, int mode, int shift)
public double iStochastic(string symbol, int timeframe, int pKperiod, int pDperiod, int slowing, int method, int price_field, int mode, int shift)
{
var commandParameters = new ArrayList { symbol, timeframe, pKperiod, pDperiod, slowing, method, priceField, mode, shift };
var commandParameters = new ArrayList { symbol, timeframe, pKperiod, pDperiod, slowing, method, price_field, mode, shift };
return SendCommand<double>(MtCommandType.iStochastic, commandParameters);
}
@@ -1359,7 +1373,7 @@ namespace MtApi
{
result = new DateTime[response.Length];
for(var i = 0; i < response.Length; i++)
for(int i = 0; i < response.Length; i++)
{
result[i] = MtApiTimeConverter.ConvertFromMtTime(response[i]);
}
@@ -1373,54 +1387,59 @@ namespace MtApi
return SendCommand<bool>(MtCommandType.RefreshRates, null);
}
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count)
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, int start_pos, int count)
{
var response = SendRequest<CopyRatesResponse>(new CopyRates1Request
{
SymbolName = symbolName,
SymbolName = symbol_name,
Timeframe = timeframe,
StartPos = startPos,
StartPos = start_pos,
Count = count
});
return response?.Rates;
return response != null ? response.Rates : null;
}
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count)
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, DateTime start_time, int count)
{
var response = SendRequest<CopyRatesResponse>(new CopyRates2Request
{
SymbolName = symbolName,
SymbolName = symbol_name,
Timeframe = timeframe,
StartTime = MtApiTimeConverter.ConvertToMtTime(startTime),
StartTime = MtApiTimeConverter.ConvertToMtTime(start_time),
Count = count
});
return response?.Rates;
return response != null ? response.Rates : null;
}
public List<MqlRates> CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime)
public List<MqlRates> CopyRates(string symbol_name, ENUM_TIMEFRAMES timeframe, DateTime start_time, DateTime stop_time)
{
var response = SendRequest<CopyRatesResponse>(new CopyRates3Request
{
SymbolName = symbolName,
SymbolName = symbol_name,
Timeframe = timeframe,
StartTime = MtApiTimeConverter.ConvertToMtTime(startTime),
StopTime = MtApiTimeConverter.ConvertToMtTime(stopTime)
StartTime = MtApiTimeConverter.ConvertToMtTime(start_time),
StopTime = MtApiTimeConverter.ConvertToMtTime(stop_time)
});
return response?.Rates;
return response != null ? response.Rates : null;
}
private void BaBacktestingReady()
{
SendCommand<object>(MtCommandType.BacktestingReady, null);
}
#endregion
#region Checkup
public string TerminalInfoString(ENUM_TERMINAL_INFO_STRING propertyId)
public string TerminalInfoString(ENUM_TERMINAL_INFO_STRING property_id)
{
var commandParameters = new ArrayList { (int)propertyId };
var commandParameters = new ArrayList { (int)property_id };
return SendCommand<string>(MtCommandType.TerminalInfoString, commandParameters);
}
public string SymbolInfoString(string name, ENUM_SYMBOL_INFO_STRING propId)
public string SymbolInfoString(string name, ENUM_SYMBOL_INFO_STRING prop_id)
{
var commandParameters = new ArrayList { name, (int)propId };
var commandParameters = new ArrayList { name, (int)prop_id };
return SendCommand<string>(MtCommandType.SymbolInfoString, commandParameters); ;
}
#endregion
@@ -1428,60 +1447,51 @@ namespace MtApi
#region Private Methods
private void Connect(string host, int port)
{
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to {host}:{port}");
UpdateConnectionState(MtConnectionState.Connecting, string.Format("Connecting to {0}:{1}", host, port));
try
{
lock (_client)
{
_client.Open(host, port);
_client.Connect();
}
_client.Open(host, port);
_client.Connect();
}
catch (Exception e)
{
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to {host}:{port}. {e.Message}");
UpdateConnectionState(MtConnectionState.Failed, string.Format("Failed connection to {0}:{1}. {2}", host, port, e.Message));
return;
}
UpdateConnectionState(MtConnectionState.Connected, $"Connected to {host}:{port}");
UpdateConnectionState(MtConnectionState.Connected, string.Format("Connected to {0}:{1}", host, port));
OnConnected();
}
private void Connect(int port)
{
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to 'localhost':{port}");
UpdateConnectionState(MtConnectionState.Connecting, string.Format("Connecting to 'localhost':{0}", port));
try
{
lock (_client)
{
_client.Open(port);
_client.Connect();
}
_client.Open(port);
_client.Connect();
}
catch (Exception e)
{
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to 'localhost':{port}. {e.Message}");
UpdateConnectionState(MtConnectionState.Failed, string.Format("Failed connection to 'localhost':{0}. {1}", port, e.Message));
return;
}
UpdateConnectionState(MtConnectionState.Connected, $"Connected to 'localhost':{port}");
UpdateConnectionState(MtConnectionState.Connected, string.Format("Connected to 'localhost':{0}", port));
OnConnected();
}
private void OnConnected()
{
_isBacktestingMode = IsTesting();
if (_isBacktestingMode)
{
BacktestingReady();
IsBacktestingMode = IsTesting();
if (IsBacktestingMode)
{
BaBacktestingReady();
}
}
private void Disconnect()
{
lock (_client)
{
_client.Disconnect();
_client.Close();
}
_client.Disconnect();
_client.Close();
UpdateConnectionState(MtConnectionState.Disconnected, "Disconnected");
}
@@ -1509,18 +1519,37 @@ namespace MtApi
MtResponse response;
try
{
lock (_client)
{
response = _client.SendCommand((int)commandType, commandParameters);
}
response = _client.SendCommand((int)commandType, commandParameters);
}
catch (CommunicationException ex)
{
throw new MtConnectionException(ex.Message, ex);
}
var responseValue = response.GetValue();
return responseValue != null ? (T)responseValue : default(T);
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;
}
private T SendRequest<T>(RequestBase request) where T : ResponseBase, new()
@@ -1528,20 +1557,17 @@ namespace MtApi
if (request == null)
return default(T);
var serializer = JsonConvert.SerializeObject(request, Formatting.None,
var serializer = JsonConvert.SerializeObject(request, Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
});
var commandParameters = new ArrayList { serializer };
MtResponseString res;
try
{
lock (_client)
{
res = (MtResponseString)_client.SendCommand((int)MtCommandType.MtRequest, commandParameters);
}
res = (MtResponseString)_client.SendCommand((int)MtCommandType.MtRequest, commandParameters);
}
catch (CommunicationException ex)
{
@@ -1562,44 +1588,44 @@ namespace MtApi
return response;
}
private void _client_QuoteUpdated(MTApiService.MtQuote quote)
private void mClient_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 _client_ServerDisconnected(object sender, EventArgs e)
private void mClient_ServerDisconnected(object sender, EventArgs e)
{
UpdateConnectionState(MtConnectionState.Disconnected, "MtApi is disconnected");
}
private void _client_ServerFailed(object sender, EventArgs e)
private void mClient_ServerFailed(object sender, EventArgs e)
{
UpdateConnectionState(MtConnectionState.Failed, "Failed connection with MtApi");
}
private void _client_QuoteRemoved(MTApiService.MtQuote quote)
private void mClient_QuoteRemoved(MTApiService.MtQuote quote)
{
QuoteRemoved.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
}
private void _client_QuoteAdded(MTApiService.MtQuote quote)
private void mClient_QuoteAdded(MTApiService.MtQuote quote)
{
QuoteAdded.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
}
private void _client_MtEventReceived(object sender, MtEventArgs e)
{
var eventType = (MtEventTypes) e.Event.EventType;
MtEventTypes eventType = (MtEventTypes) e.Event.EventType;
switch(eventType)
{
@@ -1608,8 +1634,6 @@ namespace MtApi
FireOnLastTimeBar(JsonConvert.DeserializeObject<MtTimeBar>(e.Event.Payload));
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
@@ -1618,21 +1642,20 @@ 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
}
}
+6 -1
View File
@@ -195,6 +195,11 @@ namespace MtApi
MtRequest = 155,
//Backtesting
BacktestingReady = 156
BacktestingReady = 156,
//Symbols
SymbolsTotal = 200,
SymbolName = 201,
SymbolSelect = 202
}
}
+12 -3
View File
@@ -1,19 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
internal static class ExtensionMethods
static class ExtensionMethods
{
#region Event Methods
public static void FireEvent(this EventHandler eventHandler, object sender)
{
eventHandler?.Invoke(sender, EventArgs.Empty);
if (eventHandler != null)
{
eventHandler(sender, EventArgs.Empty);
}
}
public static void FireEvent<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
eventHandler?.Invoke(sender, e);
if (eventHandler != null)
{
eventHandler(sender, e);
}
}
#endregion
+11 -12
View File
@@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
@@ -16,17 +19,13 @@ namespace MtApi5
this.real_volume = real_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
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
}
}
+3 -1
View File
@@ -1,4 +1,6 @@
using System;
using System.Linq;
using System.Text;
namespace MtApi5
{
@@ -6,7 +8,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 ulong Order { get; set; } // Order ticket
public uint 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
+1 -2
View File
@@ -35,7 +35,6 @@
<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" />
@@ -56,7 +55,7 @@
<Compile Include="MqlTradeResult.cs" />
<Compile Include="Mt5QuoteEventArgs.cs" />
<Compile Include="MtApi5Client.cs" />
<Compile Include="Mt5CommandType.cs" />
<Compile Include="MtCommandType.cs" />
<Compile Include="MtConverters.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Mt5Quote.cs" />
+493 -533
View File
File diff suppressed because it is too large Load Diff
@@ -5,7 +5,7 @@ using System.Text;
namespace MtApi5
{
internal enum Mt5CommandType
enum Mt5CommandType
{
//NoCommand = 0
@@ -101,15 +101,6 @@ namespace MtApi5
MarketBookRelease = 61,
MarketBookGet = 62,
OrderCloseAll = 63,
//CTrade
PositionClose = 64,
PositionOpen = 65,
//Backtesting
BacktestingReady = 66,
IsTesting = 67,
Print = 68
PositionClose = 64
}
}
+33 -30
View File
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MTApiService;
using System.Collections;
namespace MtApi5
{
internal static class MtConverters
static class MtConverters
{
#region Values Converters
public static Mt5Quote Parse(this MtQuote quote)
@@ -14,29 +17,29 @@ namespace MtApi5
public static bool ParseResult(this string inputString, char separator, out MqlTradeResult result)
{
var retVal = false;
bool retVal = false;
result = null;
if (string.IsNullOrEmpty(inputString) == false)
{
var values = inputString.Split(separator);
string[] values = inputString.Split(separator);
if (values.Length == 10)
{
try
{
retVal = int.Parse(values[0]) != 0;
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]);
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]);
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, requestId);
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, request_id);
}
catch (Exception)
{
@@ -49,28 +52,28 @@ namespace MtApi5
public static bool ParseResult(this string inputString, char separator, out MqlTradeCheckResult result)
{
var retVal = false;
bool retVal = false;
result = null;
if (string.IsNullOrEmpty(inputString) == false)
{
var values = inputString.Split(separator);
string[] values = inputString.Split(separator);
if (values.Length == 10)
{
try
{
retVal = int.Parse(values[0]) != 0;
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];
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];
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, marginFree, marginLevel, comment);
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, margin_free, margin_level, comment);
}
catch (Exception)
{
@@ -84,7 +87,7 @@ namespace MtApi5
public static bool ParseResult(this string inputString, char separator, out double result)
{
var retVal = false;
bool retVal = false;
result = 0;
if (string.IsNullOrEmpty(inputString) == false)
@@ -110,24 +113,24 @@ namespace MtApi5
public static bool ParseResult(this string inputString, char separator, out DateTime from, out DateTime to)
{
var retVal = false;
bool retVal = false;
from = new DateTime();
to = new DateTime();
if (string.IsNullOrEmpty(inputString) == false)
{
var values = inputString.Split(separator);
string[] values = inputString.Split(separator);
if (values.Length == 3)
{
try
{
retVal = int.Parse(values[0]) != 0;
var iFrom = int.Parse(values[1]);
int iFrom = int.Parse(values[1]);
from = Mt5TimeConverter.ConvertFromMtTime(iFrom);
var iTo= int.Parse(values[2]);
int iTo= int.Parse(values[2]);
to = Mt5TimeConverter.ConvertFromMtTime(iTo);
}
catch (Exception)
@@ -145,7 +148,7 @@ namespace MtApi5
if (request == null)
throw new ArgumentNullException();
var exp = Mt5TimeConverter.ConvertToMtTime(request.Expiration);
int 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
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.10.0")]
[assembly: AssemblyFileVersion("1.0.10.0")]
[assembly: AssemblyVersion("1.0.9.0")]
[assembly: AssemblyFileVersion("1.0.9.0")]
+1 -1
View File
@@ -12,7 +12,7 @@
<?define PlatformSystemFolder = "SystemFolder" ?>
<?endif ?>
<?define ProductVersion="1.0.10" ?>
<?define ProductVersion="1.0.9" ?>
<?define Manufacturer="DW"?>
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
+5 -3
View File
@@ -13,9 +13,11 @@ MTApiService library should be placed in Windows GAC (Global Assembly Cache). In
# How to build solution
The project is supported by Visual Studio 2015.
It also requires WIX Tools (http://wixtoolset.org/).
To make api for MetaTrader4 use MtApiInstaller and for MetaTrader5 use MtApi5Installer.
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.
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.
@@ -1,115 +0,0 @@
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;
}
}
}
}
+15 -38
View File
@@ -3,7 +3,6 @@
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>
@@ -263,52 +262,36 @@
</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>
@@ -333,9 +316,9 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Text="symbolName"/>
<TextBox Grid.Row="0" Text="symbol_name"/>
<TextBox Grid.Row="1" Text="timeframe"/>
<TextBox Grid.Row="2" Text="startPos"/>
<TextBox Grid.Row="2" Text="start_pos"/>
<TextBox Grid.Row="3" Text="count"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TimeSeriesValues.SymbolValue}"/>
<ComboBox Grid.Row="1" Grid.Column="1"
@@ -372,7 +355,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"/>
@@ -389,16 +372,10 @@
<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 mtApi5TestClient:ListBoxBehavior.ScrollOnNewItem="true" Height="200" ItemsSource="{Binding History}"/>
<ListBox Height="200" ItemsSource="{Binding History}"/>
</Expander>
<StatusBar Grid.Row="3">
View File
+1 -1
View File
@@ -39,7 +39,7 @@ namespace MtApi5TestClient
}
}
public ulong Order
public uint Order
{
get { return TradeRequest.Order; }
set
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
@@ -10,9 +10,8 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MtApi5TestClient</RootNamespace>
<AssemblyName>MtApi5TestClient</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
@@ -26,7 +25,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
@@ -36,7 +34,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
@@ -53,7 +50,6 @@
<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>
@@ -71,7 +67,6 @@
<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" />
@@ -102,7 +97,6 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="DelegateCommand.cs" />
<Compile Include="ListBoxBehavior.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
@@ -130,7 +124,6 @@
<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>
+26 -18
View File
@@ -1,17 +1,17 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// Runtime Version:4.0.30319.18034
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MtApi5TestClient.Properties {
using System;
namespace MtApi5TestClient.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@@ -22,40 +22,48 @@ 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 (object.ReferenceEquals(resourceMan, null)) {
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((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;
}
}
+14 -10
View File
@@ -1,24 +1,28 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// Runtime Version:4.0.30319.18034
//
// 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", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.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;
}
}
+356 -515
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
+2 -2
View File
@@ -837,7 +837,7 @@ namespace TestApiClientUI
}
//OrderSend
private async void button1_Click(object sender, EventArgs e)
private void button1_Click(object sender, EventArgs e)
{
var symbol = textBoxOrderSymbol.Text;
@@ -878,7 +878,7 @@ namespace TestApiClientUI
break;
}
var ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowColor));
var ticket = Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowColor));
AddToLog(string.Format("Sended order result: ticket = {0}", ticket));
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+49 -142
View File
@@ -3,8 +3,6 @@
#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);
@@ -34,6 +32,8 @@
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,11 +43,12 @@ int ExpertHandle;
string message;
bool isCrashed = false;
bool IsRemoteReadyForTesting = false;
string symbolValue;
string commentValue;
double myBid;
double myAsk;
string PARAM_SEPARATOR = ";";
int OnInit()
@@ -56,12 +57,6 @@ int OnInit()
return (result);
}
double OnTester()
{
Print("OnTester");
return 0;
}
void OnDeinit(const int reason)
{
deinit();
@@ -74,9 +69,9 @@ void OnTick()
int preinit()
{
StringInit(message, 1000, 0);
StringInit(symbolValue, 1000, 0);
StringInit(commentValue, 1000, 0);
message = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "";
symbolValue = "222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" + "";
commentValue = "333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333" + "";
return (0);
}
@@ -89,15 +84,11 @@ bool IsDemo()
return(false);
}
bool IsTesting()
{
bool isTesting = MQLInfoInteger(MQL_TESTER);
return isTesting;
}
int init()
{
preinit();
preinit();
// verify(IsDemo(), AccountInfoString(ACCOUNT_NAME), AccountInfoInteger(ACCOUNT_LOGIN));
if (TerminalInfoInteger(TERMINAL_DLLS_ALLOWED) == false)
{
@@ -119,14 +110,17 @@ int init()
return (1);
}
long chartID = ChartID();
ExpertHandle = (int) ChartGetInteger(chartID, CHART_WINDOW_HANDLE);
long chartID= ChartID();
ExpertHandle = 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);
@@ -139,30 +133,6 @@ 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);
}
@@ -177,7 +147,6 @@ int deinit()
isCrashed = true;
return (1);
}
Print("Expert was deinitialized.");
}
return (0);
@@ -185,46 +154,50 @@ int deinit()
int start()
{
MqlTick last_tick;
SymbolInfoTick(Symbol(),last_tick);
double Bid = last_tick.bid;
double Ask = last_tick.ask;
if (isCrashed == 0)
{
MqlTick last_tick;
SymbolInfoTick(Symbol(),last_tick);
double Bid = last_tick.bid;
double Ask = last_tick.ask;
if (!updateQuote(ExpertHandle, Symbol(), Bid, Ask, message))
{
Print("updateQuote: [ERROR] ", message);
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;
}
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)
{
@@ -254,7 +227,6 @@ int executeCommand()
sendBooleanResponse(ExpertHandle, retVal);
}
break;
case 64: //PositionClose
{
int ticket;
@@ -265,7 +237,7 @@ int executeCommand()
sendBooleanResponse(ExpertHandle, trade.PositionClose(ticket));
}
break;
case 2: // OrderCalcMargin
{
ENUM_ORDER_TYPE action;
@@ -1638,72 +1610,7 @@ int executeCommand()
sendVoidResponse(ExpertHandle);
}
}
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;
break;
default:
Print("Unknown command type = ", commandType);