Compare commits

..

132 Commits

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

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