diff --git a/MTApiService/MTApiService.csproj b/MTApiService/MTApiService.csproj
index 56010ac1..fb9fd2b3 100755
--- a/MTApiService/MTApiService.csproj
+++ b/MTApiService/MTApiService.csproj
@@ -83,7 +83,7 @@
-
+
diff --git a/MTApiService/MtServerInstance.cs b/MTApiService/MtAdapter.cs
old mode 100755
new mode 100644
similarity index 77%
rename from MTApiService/MtServerInstance.cs
rename to MTApiService/MtAdapter.cs
index a1e4e882..ac203b54
--- a/MTApiService/MtServerInstance.cs
+++ b/MTApiService/MtAdapter.cs
@@ -4,13 +4,13 @@ using log4net;
namespace MTApiService
{
- public class MtServerInstance
+ public class MtAdapter
{
#region Fields
private const string LogProfileName = "MtApiService";
- private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
- private static readonly MtServerInstance Instance = new MtServerInstance();
+ private static readonly ILog Log = LogManager.GetLogger(typeof(MtAdapter));
+ private static readonly MtAdapter Instance = new MtAdapter();
private readonly Dictionary _servers = new Dictionary();
private readonly Dictionary _experts = new Dictionary();
@@ -18,16 +18,16 @@ namespace MTApiService
#region Init Instance
- private MtServerInstance()
+ private MtAdapter()
{
LogConfigurator.Setup(LogProfileName);
}
- static MtServerInstance()
+ static MtAdapter()
{
}
- public static MtServerInstance GetInstance()
+ public static MtAdapter GetInstance()
{
return Instance;
}
@@ -208,6 +208,50 @@ namespace MTApiService
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
diff --git a/MTApiService/MtClient.cs b/MTApiService/MtClient.cs
index 5dba56a7..47c0e1d0 100755
--- a/MTApiService/MtClient.cs
+++ b/MTApiService/MtClient.cs
@@ -139,7 +139,7 @@ namespace MTApiService
}
/// Thrown when connection failed
- public MtResponse SendCommand(int commandType, ArrayList parameters, int expertHandle)
+ public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary namedParams, int expertHandle)
{
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
@@ -153,7 +153,11 @@ namespace MTApiService
try
{
- result = _proxy.SendCommand(new MtCommand { CommandType = commandType, Parameters = parameters, ExpertHandle = expertHandle});
+ result = _proxy.SendCommand(new MtCommand {
+ CommandType = commandType,
+ Parameters = parameters,
+ NamedParams = namedParams,
+ ExpertHandle = expertHandle});
}
catch (Exception ex)
{
diff --git a/MTApiService/MtCommand.cs b/MTApiService/MtCommand.cs
index 1ac04d39..eac8e8e9 100755
--- a/MTApiService/MtCommand.cs
+++ b/MTApiService/MtCommand.cs
@@ -1,5 +1,6 @@
using System.Runtime.Serialization;
using System.Collections;
+using System.Collections.Generic;
namespace MTApiService
{
@@ -12,6 +13,9 @@ namespace MTApiService
[DataMember]
public ArrayList Parameters { get; set; }
+ [DataMember]
+ public Dictionary NamedParams { get; set; }
+
[DataMember]
public int ExpertHandle { get; set; }
diff --git a/MTApiService/MtExpert.cs b/MTApiService/MtExpert.cs
index b609ec50..4f05f569 100755
--- a/MTApiService/MtExpert.cs
+++ b/MTApiService/MtExpert.cs
@@ -60,7 +60,7 @@ namespace MTApiService
public object GetCommandParameter(int index)
{
- Log.DebugFormat("GetCommandType: called. index = {0}", index);
+ Log.DebugFormat("GetCommandParameter: called. index = {0}", index);
var command = _currentTask?.Command;
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
@@ -71,6 +71,46 @@ namespace MTApiService
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);
diff --git a/MTApiService/Properties/AssemblyInfo.cs b/MTApiService/Properties/AssemblyInfo.cs
index d89d1407..cb337916 100755
--- a/MTApiService/Properties/AssemblyInfo.cs
+++ b/MTApiService/Properties/AssemblyInfo.cs
@@ -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.24.0")]
-[assembly: AssemblyFileVersion("1.0.24.0")]
+[assembly: AssemblyVersion("1.0.25.0")]
+[assembly: AssemblyFileVersion("1.0.25.0")]
diff --git a/MTConnector/MTConnector.cpp b/MTConnector/MTConnector.cpp
index 7bb5762c..1d3046d6 100755
--- a/MTConnector/MTConnector.cpp
+++ b/MTConnector/MTConnector.cpp
@@ -45,7 +45,7 @@ _DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, do
{
return Execute([&expertHandle, &port, symbol, &bid, &ask]() {
MT4Handler^ mtHandler = gcnew MT4Handler();
- MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
+ MtAdapter::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
return true;
}, err, false);
@@ -54,7 +54,7 @@ _DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, do
_DLLAPI bool _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
return Execute([&expertHandle]() {
- MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
+ MtAdapter::GetInstance()->DeinitExpert(expertHandle);
return true;
}, err, false);
}
@@ -62,7 +62,7 @@ _DLLAPI bool _stdcall deinitExpert(int expertHandle, wchar_t* err)
_DLLAPI bool _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
return Execute([&expertHandle, symbol, &bid, &ask]() {
- MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
+ MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
return true;
}, err, false);
}
@@ -71,7 +71,7 @@ _DLLAPI bool _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid,
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
return Execute([&expertHandle, &eventType, payload]() {
- MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
+ MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
return true;
}, err, false);
}
@@ -79,7 +79,7 @@ _DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payloa
_DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{
return Execute([&expertHandle, &response]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
return true;
}, err, false);
}
@@ -87,7 +87,7 @@ _DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, wchar_t* e
_DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, wchar_t* err)
{
return Execute([&expertHandle, &response]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
return true;
}, err, false);
}
@@ -95,7 +95,7 @@ _DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, wchar
_DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, wchar_t* err)
{
return Execute([&expertHandle, &response]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
return true;
}, err, false);
}
@@ -103,7 +103,7 @@ _DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, wcha
_DLLAPI bool _stdcall sendStringResponse(int expertHandle, wchar_t* response, wchar_t* err)
{
return Execute([&expertHandle, response]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
return true;
}, err, false);
}
@@ -113,7 +113,7 @@ _DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* mes
return Execute([&expertHandle, &code, message]() {
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
res->ErrorCode = code;
- MtServerInstance::GetInstance()->SendResponse(expertHandle, res);
+ MtAdapter::GetInstance()->SendResponse(expertHandle, res);
return true;
}, err, false);
}
@@ -121,7 +121,7 @@ _DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* mes
_DLLAPI bool _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
{
return Execute([&expertHandle]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
return true;
}, err, false);
}
@@ -134,7 +134,7 @@ _DLLAPI bool _stdcall sendDoubleArrayResponse(int expertHandle, double* values,
{
list[i] = values[i];
}
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
return true;
}, err, false);
}
@@ -147,7 +147,7 @@ _DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int si
{
list[i] = values[i];
}
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
return true;
}, err, false);
}
@@ -155,7 +155,7 @@ _DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int si
_DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
{
return Execute([&expertHandle, &response]() {
- MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
+ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
return true;
}, err, false);
}
@@ -163,7 +163,7 @@ _DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar
_DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
{
return Execute([&expertHandle, res]() {
- *res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
+ *res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
return true;
}, err, false);
}
@@ -171,15 +171,17 @@ _DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
_DLLAPI bool _stdcall getIntValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
return Execute([&expertHandle, ¶mIndex, res]() {
- *res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
+ *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([&expertHandle, ¶mIndex, res]() {
- *res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
+ *res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
@@ -187,7 +189,7 @@ _DLLAPI bool _stdcall getDoubleValue(int expertHandle, int paramIndex, double* r
_DLLAPI bool _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res, wchar_t* err)
{
return Execute([&expertHandle, ¶mIndex, res]() {
- convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
+ convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
return true;
}, err, false);
}
@@ -195,7 +197,7 @@ _DLLAPI bool _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t*
_DLLAPI bool _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
return Execute([&expertHandle, ¶mIndex, res]() {
- *res = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
+ *res = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
@@ -203,7 +205,63 @@ _DLLAPI bool _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res
_DLLAPI bool _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
{
return Execute([&expertHandle, ¶mIndex, res]() {
- *res = (__int64)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
+ *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([&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([&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([&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([&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([&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([&expertHandle, paramName, res]() {
+ System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
+ if (obj != nullptr)
+ *res = (__int64)obj;
return true;
}, err, false);
}
\ No newline at end of file
diff --git a/MtApi/EnumObject.cs b/MtApi/EnumObject.cs
new file mode 100644
index 00000000..c5420942
--- /dev/null
+++ b/MtApi/EnumObject.cs
@@ -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.
+ }
+}
diff --git a/MtApi/MtApi.csproj b/MtApi/MtApi.csproj
index 985c00c7..de7bfb08 100755
--- a/MtApi/MtApi.csproj
+++ b/MtApi/MtApi.csproj
@@ -59,6 +59,7 @@
+
diff --git a/MtApi/MtApiClient.cs b/MtApi/MtApiClient.cs
index 719749f1..15b138fe 100755
--- a/MtApi/MtApiClient.cs
+++ b/MtApi/MtApiClient.cs
@@ -16,8 +16,6 @@ namespace MtApi
public sealed class MtApiClient
{
- private volatile bool _isBacktestingMode;
-
#region MetaTrader Constants
//Special constant
@@ -31,6 +29,8 @@ namespace MtApi
private MtClient _client;
private readonly object _locker = new object();
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
+ private volatile bool _isBacktestingMode;
+ private int _executorHandle;
#endregion
#region ctor
@@ -74,7 +74,8 @@ namespace MtApi
///
public List GetQuotes()
{
- var quotes = _client.GetQuotes();
+ var client = Client;
+ var quotes = client != null ? client.GetQuotes() : null;
return quotes?.Select(q => new MtQuote(q)).ToList();
}
#endregion
@@ -95,7 +96,9 @@ namespace MtApi
}
}
- private int _executorHandle;
+ ///
+ ///Connection status of MetaTrader API.
+ ///
public int ExecutorHandle
{
get
@@ -1746,14 +1749,32 @@ namespace MtApi
///The price coordinate of the first anchor point.
///The time coordinate of the second anchor point.
///The price coordinate of the second anchor point.
- ///The price coordinate of the second anchor point.
+ ///The time coordinate of the third anchor point.
+ ///The price coordinate of the third anchor point.
///
- ///Returns various data about securities listed in the "Market Watch" window.
+ ///Returns true or false depending on whether the object is created or not.
///
- bool ObjectCreate(long chartId, string objectName, object objectType, int subWindow,
- DateTime time1, double price1, DateTime? time2 = null, double price2 = 0, DateTime? time3 = null, double price3 = 0)
+ public bool ObjectCreate(long chartId, string objectName, EnumObject objectType, int subWindow,
+ DateTime? time1, double price1, DateTime? time2 = null, double? price2 = null, DateTime? time3 = null, double? price3 = null)
{
- return false;
+ var namedParams = new Dictionary();
+ namedParams.Add(nameof(chartId), chartId);
+ namedParams.Add(nameof(objectName), objectName);
+ namedParams.Add(nameof(objectType), (int)objectType);
+ namedParams.Add(nameof(subWindow), subWindow);
+ namedParams.Add(nameof(time1), time1 == null ? 0 : MtApiTimeConverter.ConvertToMtTime(time1.Value));
+ namedParams.Add(nameof(price1), price1);
+
+ if (time2 != null)
+ namedParams.Add(nameof(time2), MtApiTimeConverter.ConvertToMtTime(time2.Value));
+ if (price2 != null)
+ namedParams.Add(nameof(price2), price2.Value);
+ if (time3 != null)
+ namedParams.Add(nameof(time3), MtApiTimeConverter.ConvertToMtTime(time3.Value));
+ if (price3 != null)
+ namedParams.Add(nameof(price3), price3.Value);
+
+ return SendCommand(MtCommandType.ObjectCreate, null, namedParams);
}
#endregion
@@ -1882,7 +1903,7 @@ namespace MtApi
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(state, message));
}
- private T SendCommand(MtCommandType commandType, ArrayList commandParameters)
+ private T SendCommand(MtCommandType commandType, ArrayList commandParameters, Dictionary namedParams = null)
{
MtResponse response;
@@ -1894,7 +1915,7 @@ namespace MtApi
try
{
- response = client.SendCommand((int)commandType, commandParameters, ExecutorHandle);
+ response = client.SendCommand((int)commandType, commandParameters, namedParams, ExecutorHandle);
}
catch (CommunicationException ex)
{
diff --git a/MtApi/MtConnectionEventArgs.cs b/MtApi/MtConnectionEventArgs.cs
index 15baf021..9254d774 100755
--- a/MtApi/MtConnectionEventArgs.cs
+++ b/MtApi/MtConnectionEventArgs.cs
@@ -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)
{
diff --git a/MtApi5/Mt5ConnectionEventArgs.cs b/MtApi5/Mt5ConnectionEventArgs.cs
index 8f523a6e..14edb7e1 100755
--- a/MtApi5/Mt5ConnectionEventArgs.cs
+++ b/MtApi5/Mt5ConnectionEventArgs.cs
@@ -1,14 +1,11 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace MtApi5
{
public class Mt5ConnectionEventArgs: EventArgs
{
public Mt5ConnectionState Status { get; private set; }
- public String ConnectionMessage { get; private set; }
+ public string ConnectionMessage { get; private set; }
public Mt5ConnectionEventArgs(Mt5ConnectionState status, string message)
{
diff --git a/MtApi5/MtApi5Client.cs b/MtApi5/MtApi5Client.cs
index cf3e527d..ba931151 100755
--- a/MtApi5/MtApi5Client.cs
+++ b/MtApi5/MtApi5Client.cs
@@ -7,6 +7,7 @@ using System.ServiceModel;
using MtApi5.Requests;
using MtApi5.Responses;
using Newtonsoft.Json;
+using System.Threading.Tasks;
namespace MtApi5
{
@@ -31,22 +32,17 @@ namespace MtApi5
#region Private Fields
- private readonly MtClient _client = new MtClient();
+ private MtClient _client;
+ private readonly object _locker = new object();
private volatile bool _isBacktestingMode = false;
+ private Mt5ConnectionState _connectionState = Mt5ConnectionState.Disconnected;
+ private int _executorHandle;
#endregion
#region Public Methods
public MtApi5Client()
{
LogConfigurator.Setup(LogProfileName);
-
- ConnectionState = Mt5ConnectionState.Disconnected;
-
- _client.QuoteAdded += mClient_QuoteAdded;
- _client.QuoteRemoved += mClient_QuoteRemoved;
- _client.QuoteUpdated += mClient_QuoteUpdated;
- _client.ServerDisconnected += mClient_ServerDisconnected;
- _client.ServerFailed += mClient_ServerFailed;
}
///
@@ -56,15 +52,7 @@ namespace MtApi5
///Port of host connection (default 8222)
public void BeginConnect(string host, int port)
{
- //if (string.IsNullOrEmpty(host) == false && (host.Equals("localhost") || host.Equals("127.0.0.1")))
- //{
- // this.BeginConnect(port);
- //}
- //else
- //{
- Action connectAction = Connect;
- connectAction.BeginInvoke(host, port, null, null);
- //}
+ Task.Factory.StartNew(() => Connect(host, port));
}
///
@@ -73,8 +61,7 @@ namespace MtApi5
///Port of host connection (default 8222)
public void BeginConnect(int port)
{
- Action connectAction = Connect;
- connectAction.BeginInvoke(port, null, null);
+ Task.Factory.StartNew(() => Connect(port));
}
///
@@ -82,8 +69,7 @@ namespace MtApi5
///
public void BeginDisconnect()
{
- Action disconnectAction = Disconnect;
- disconnectAction.BeginInvoke(null, null);
+ Task.Factory.StartNew(() => Disconnect(false));
}
///
@@ -91,11 +77,8 @@ namespace MtApi5
///
public IEnumerable GetQuotes()
{
- IEnumerable quotes;
- lock (_client)
- {
- quotes = _client.GetQuotes();
- }
+ var client = Client;
+ var quotes = client != null ? client.GetQuotes() : null;
return quotes?.Select(q => q.Parse());
}
@@ -1432,7 +1415,34 @@ namespace MtApi5
///
///Connection status of MetaTrader API.
///
- public Mt5ConnectionState ConnectionState { get; private set; }
+ public Mt5ConnectionState ConnectionState
+ {
+ get
+ {
+ lock (_locker)
+ {
+ return _connectionState;
+ }
+ }
+ }
+
+ public int ExecutorHandle
+ {
+ get
+ {
+ lock (_locker)
+ {
+ return _executorHandle;
+ }
+ }
+ set
+ {
+ lock (_locker)
+ {
+ _executorHandle = value;
+ }
+ }
+ }
#endregion
#region Events
@@ -1443,94 +1453,148 @@ namespace MtApi5
#endregion
#region Private Methods
- private void Connect(string host, int port)
+ private MtClient Client
{
- ConnectionState = Mt5ConnectionState.Connecting;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, "Connecting to " + host + ":" + port));
-
- try
+ get
{
- lock (_client)
+ lock (_locker)
{
- _client.Open(host, port);
- _client.Connect();
+ return _client;
}
}
- catch (Exception e)
+ }
+
+ private void Connect(MtClient client)
+ {
+ lock (_locker)
{
- ConnectionState = Mt5ConnectionState.Failed;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection to " + host + ":" + port + ". " + e.Message));
- return;
+ if (_connectionState == Mt5ConnectionState.Connected
+ || _connectionState == Mt5ConnectionState.Connecting)
+ {
+ return;
+ }
+
+ _connectionState = Mt5ConnectionState.Connecting;
}
- ConnectionState = Mt5ConnectionState.Connected;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, "Connected to " + host + ":" + port));
+ string message = string.IsNullOrEmpty(client.Host) ? $"Connecting to localhost:{client.Port}" : $"Connecting to {client.Host}:{client.Port}";
+ ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, message));
- OnConnected();
+ var state = Mt5ConnectionState.Failed;
+
+ lock (_locker)
+ {
+ try
+ {
+ client.Connect();
+ state = Mt5ConnectionState.Connected;
+ }
+ catch (Exception e)
+ {
+ client.Dispose();
+ message = string.IsNullOrEmpty(client.Host) ? $"Failed connection to localhost:{client.Port}. {e.Message}" : $"Failed connection to {client.Host}:{client.Port}. {e.Message}";
+ }
+
+ if (state == Mt5ConnectionState.Connected)
+ {
+ _client = client;
+ _client.QuoteAdded += _client_QuoteAdded;
+ _client.QuoteRemoved += _client_QuoteRemoved;
+ _client.QuoteUpdated += _client_QuoteUpdated;
+ _client.ServerDisconnected += _client_ServerDisconnected;
+ _client.ServerFailed += _client_ServerFailed;
+ message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}";
+ }
+
+ _connectionState = state;
+ }
+
+ ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(state, message));
+
+ if (state == Mt5ConnectionState.Connected)
+ {
+ OnConnected();
+ }
+ }
+
+ private void Connect(string host, int port)
+ {
+ var client = new MtClient(host, port);
+ Connect(client);
}
private void Connect(int port)
{
- ConnectionState = Mt5ConnectionState.Connecting;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, "Connecting to 'localhost':" + port));
-
- try
- {
- lock (_client)
- {
- _client.Open(port);
- _client.Connect();
- }
- }
- catch (Exception e)
- {
- ConnectionState = Mt5ConnectionState.Failed;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection to 'localhost':" + port + ". " + e.Message));
-
- return;
- }
-
- ConnectionState = Mt5ConnectionState.Connected;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, "Connected to 'localhost':" + port));
-
- OnConnected();
+ var client = new MtClient(port);
+ Connect(client);
}
- private void Disconnect()
+ private void Disconnect(bool failed)
{
- lock (_client)
+ var state = failed ? Mt5ConnectionState.Failed : Mt5ConnectionState.Disconnected;
+ var message = failed ? "Connection Failed" : "Disconnected";
+
+ lock (_locker)
{
- _client.Disconnect();
- _client.Close();
+ if (_connectionState == Mt5ConnectionState.Disconnected
+ || _connectionState == Mt5ConnectionState.Failed)
+ return;
+
+ if (_client != null)
+ {
+ _client.QuoteAdded -= _client_QuoteAdded;
+ _client.QuoteRemoved -= _client_QuoteRemoved;
+ _client.QuoteUpdated -= _client_QuoteUpdated;
+ _client.ServerDisconnected -= _client_ServerDisconnected;
+ _client.ServerFailed -= _client_ServerFailed;
+
+ if (!failed)
+ {
+ _client.Disconnect();
+ }
+
+ _client.Dispose();
+
+ _client = null;
+ }
+
+ _connectionState = state;
}
- ConnectionState = Mt5ConnectionState.Disconnected;
- ConnectionStateChanged.FireEvent(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Disconnected, "Disconnected"));
+ ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(state, message));
}
- private T SendCommand(Mt5CommandType commandType, ArrayList commandParameters)
+ private T SendCommand(Mt5CommandType commandType, ArrayList commandParameters, Dictionary namedParams = null)
{
MtResponse response;
+
+ var client = Client;
+ if (client == null)
+ {
+ throw new Exception("No connection");
+ }
+
try
{
- lock (_client)
- {
- response = _client.SendCommand((int) commandType, commandParameters);
- }
+ response = client.SendCommand((int)commandType, commandParameters, namedParams, ExecutorHandle);
}
catch (CommunicationException ex)
{
throw new Exception(ex.Message, ex);
}
- var responseValue = response?.GetValue();
- return responseValue != null ? (T) responseValue : default(T);
+ if (response == null)
+ {
+ throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null");
+ }
+
+ if (response.ErrorCode != 0)
+ {
+ throw new ExecutionException((ErrorCode)response.ErrorCode, response.ToString());
+ }
+
+ var responseValue = response.GetValue();
+ return responseValue != null ? (T)responseValue : default(T);
}
private T SendRequest(RequestBase request) where T : ResponseBase, new()
@@ -1545,25 +1609,14 @@ namespace MtApi5
});
var commandParameters = new ArrayList { serializer };
- MtResponseString res;
- try
- {
- lock (_client)
- {
- res = (MtResponseString)_client.SendCommand((int)Mt5CommandType.MtRequest, commandParameters);
- }
- }
- catch (CommunicationException ex)
- {
- throw new Exception(ex.Message, ex);
- }
+ var res = SendCommand(Mt5CommandType.MtRequest, commandParameters);
if (res == null)
{
throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null");
}
- var response = JsonConvert.DeserializeObject(res.Value);
+ var response = JsonConvert.DeserializeObject(res);
if (response.ErrorCode != 0)
{
throw new ExecutionException((ErrorCode)response.ErrorCode, response.ErrorMessage);
@@ -1573,7 +1626,7 @@ namespace MtApi5
}
- private void mClient_QuoteUpdated(MtQuote quote)
+ private void _client_QuoteUpdated(MtQuote quote)
{
if (quote != null)
{
@@ -1581,26 +1634,22 @@ namespace MtApi5
}
}
- private void mClient_ServerDisconnected(object sender, EventArgs e)
+ private void _client_ServerDisconnected(object sender, EventArgs e)
{
- ConnectionState = Mt5ConnectionState.Disconnected;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Disconnected, "MtApi is disconnected"));
+ Disconnect(false);
}
- private void mClient_ServerFailed(object sender, EventArgs e)
+ private void _client_ServerFailed(object sender, EventArgs e)
{
- ConnectionState = Mt5ConnectionState.Failed;
- ConnectionStateChanged.FireEvent(this
- , new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection with MtApi"));
+ Disconnect(true);
}
- private void mClient_QuoteRemoved(MtQuote quote)
+ private void _client_QuoteRemoved(MtQuote quote)
{
QuoteRemoved.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse()));
}
- private void mClient_QuoteAdded(MtQuote quote)
+ private void _client_QuoteAdded(MtQuote quote)
{
QuoteAdded.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse()));
}
diff --git a/TestClients/TestApiClientUI/Form1.Designer.cs b/TestClients/TestApiClientUI/Form1.Designer.cs
index 0e0f80c4..c7f09913 100644
--- a/TestClients/TestApiClientUI/Form1.Designer.cs
+++ b/TestClients/TestApiClientUI/Form1.Designer.cs
@@ -195,6 +195,10 @@
this.tabPage9 = new System.Windows.Forms.TabPage();
this.button38 = new System.Windows.Forms.Button();
this.button37 = new System.Windows.Forms.Button();
+ this.tabPage10 = new System.Windows.Forms.TabPage();
+ this.button4 = new System.Windows.Forms.Button();
+ this.comboBox11 = new System.Windows.Forms.ComboBox();
+ this.textBoxChartId = new System.Windows.Forms.TextBox();
this.groupBox1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.groupBox2.SuspendLayout();
@@ -212,6 +216,7 @@
this.tabPage7.SuspendLayout();
this.tabPage8.SuspendLayout();
this.tabPage9.SuspendLayout();
+ this.tabPage10.SuspendLayout();
this.SuspendLayout();
//
// textBoxServerName
@@ -393,6 +398,7 @@
this.tabControl1.Controls.Add(this.tabPage7);
this.tabControl1.Controls.Add(this.tabPage8);
this.tabControl1.Controls.Add(this.tabPage9);
+ this.tabControl1.Controls.Add(this.tabPage10);
this.tabControl1.Location = new System.Drawing.Point(324, 12);
this.tabControl1.Multiline = true;
this.tabControl1.Name = "tabControl1";
@@ -1951,6 +1957,7 @@
//
// tabPage9
//
+ this.tabPage9.Controls.Add(this.textBoxChartId);
this.tabPage9.Controls.Add(this.button38);
this.tabPage9.Controls.Add(this.button37);
this.tabPage9.Location = new System.Drawing.Point(4, 40);
@@ -1980,6 +1987,44 @@
this.button37.UseVisualStyleBackColor = true;
this.button37.Click += new System.EventHandler(this.button37_Click);
//
+ // tabPage10
+ //
+ this.tabPage10.Controls.Add(this.comboBox11);
+ this.tabPage10.Controls.Add(this.button4);
+ this.tabPage10.Location = new System.Drawing.Point(4, 40);
+ this.tabPage10.Name = "tabPage10";
+ this.tabPage10.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage10.Size = new System.Drawing.Size(638, 383);
+ this.tabPage10.TabIndex = 10;
+ this.tabPage10.Text = "Object Functions";
+ this.tabPage10.UseVisualStyleBackColor = true;
+ //
+ // button4
+ //
+ this.button4.Location = new System.Drawing.Point(133, 3);
+ this.button4.Name = "button4";
+ this.button4.Size = new System.Drawing.Size(97, 23);
+ this.button4.TabIndex = 0;
+ this.button4.Text = "ObjectCreate";
+ this.button4.UseVisualStyleBackColor = true;
+ this.button4.Click += new System.EventHandler(this.button4_Click);
+ //
+ // comboBox11
+ //
+ this.comboBox11.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboBox11.FormattingEnabled = true;
+ this.comboBox11.Location = new System.Drawing.Point(6, 5);
+ this.comboBox11.Name = "comboBox11";
+ this.comboBox11.Size = new System.Drawing.Size(121, 21);
+ this.comboBox11.TabIndex = 1;
+ //
+ // textBoxChartId
+ //
+ this.textBoxChartId.Location = new System.Drawing.Point(115, 8);
+ this.textBoxChartId.Name = "textBoxChartId";
+ this.textBoxChartId.Size = new System.Drawing.Size(100, 20);
+ this.textBoxChartId.TabIndex = 2;
+ //
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -2022,6 +2067,8 @@
this.tabPage8.ResumeLayout(false);
this.tabPage8.PerformLayout();
this.tabPage9.ResumeLayout(false);
+ this.tabPage9.PerformLayout();
+ this.tabPage10.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@@ -2195,6 +2242,10 @@
private System.Windows.Forms.Button button65;
private System.Windows.Forms.Button button66;
private System.Windows.Forms.Button button67;
+ private System.Windows.Forms.TabPage tabPage10;
+ private System.Windows.Forms.Button button4;
+ private System.Windows.Forms.ComboBox comboBox11;
+ private System.Windows.Forms.TextBox textBoxChartId;
}
}
diff --git a/TestClients/TestApiClientUI/Form1.cs b/TestClients/TestApiClientUI/Form1.cs
index dfccb0ba..befbfd3f 100644
--- a/TestClients/TestApiClientUI/Form1.cs
+++ b/TestClients/TestApiClientUI/Form1.cs
@@ -33,6 +33,7 @@ namespace TestApiClientUI
comboBox8.DataSource = Enum.GetNames(typeof(MarketInfoModeType));
comboBox9.DataSource = Enum.GetNames(typeof(EnumTerminalInfoInteger));
comboBox10.DataSource = Enum.GetNames(typeof(EnumTerminalInfoDouble));
+ comboBox11.DataSource = Enum.GetNames(typeof(EnumObject));
comboBoxAccountInfoCmd.DataSource = Enum.GetNames(typeof(TradeOperation));
_apiClient.QuoteUpdated += apiClient_QuoteUpdated;
@@ -49,6 +50,7 @@ namespace TestApiClientUI
comboBox3.SelectedIndex = 0;
comboBox4.SelectedIndex = 0;
comboBox5.SelectedIndex = 0;
+ comboBox11.SelectedIndex = 0;
comboBoxAccountInfoCmd.SelectedIndex = 0;
_timerTradeMonitor = new TimerTradeMonitor(_apiClient) { Interval = 10000 }; // 10 sec
@@ -1369,6 +1371,7 @@ namespace TestApiClientUI
{
var result = await Execute(_apiClient.ChartId);
PrintLog($"CharID: result = {result}");
+ RunOnUiThread(() => textBoxChartId.Text = result.ToString());
}
//ChartRedraw
@@ -1377,5 +1380,18 @@ namespace TestApiClientUI
await Execute(() => _apiClient.ChartRedraw());
PrintLog($"ChartRedraw: called.");
}
+
+ //ObjectCreate
+ private async void button4_Click(object sender, EventArgs e)
+ {
+ long chartId = 0;
+ string objectName = "label_object";
+ //long.TryParse(textBoxChartId.Text, )
+ EnumObject objectType;
+ Enum.TryParse(comboBox11.Text, out objectType);
+
+ var result = await Execute(() => _apiClient.ObjectCreate(chartId, objectName, objectType, 0, null, 0));
+ PrintLog($"ObjectCreate result: {result}");
+ }
}
}
diff --git a/mq4/MtApi.ex4 b/mq4/MtApi.ex4
index 2f5e3b3d..4ae51c9e 100755
Binary files a/mq4/MtApi.ex4 and b/mq4/MtApi.ex4 differ
diff --git a/mq4/MtApi.mq4 b/mq4/MtApi.mq4
index 75c3ff35..03d52d3e 100755
Binary files a/mq4/MtApi.mq4 and b/mq4/MtApi.mq4 differ