Issue #32: Added function ObjectCreate in MtApi (MT4)

This commit is contained in:
DW
2016-12-27 17:41:11 +02:00
parent 39146d68b2
commit a8832b79ba
17 changed files with 487 additions and 159 deletions
+1 -1
View File
@@ -83,7 +83,7 @@
<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>
+50 -6
View File
@@ -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<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
@@ -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
+6 -2
View File
@@ -139,7 +139,7 @@ namespace MTApiService
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters, int expertHandle)
public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> 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)
{
+4
View File
@@ -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<string, object> NamedParams { get; set; }
[DataMember]
public int ExpertHandle { get; set; }
+41 -1
View File
@@ -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);
+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.24.0")]
[assembly: AssemblyFileVersion("1.0.24.0")]
[assembly: AssemblyVersion("1.0.25.0")]
[assembly: AssemblyFileVersion("1.0.25.0")]
+77 -19
View File
@@ -45,7 +45,7 @@ _DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, do
{
return Execute<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&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<bool>([&expertHandle, &paramIndex, 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<bool>([&expertHandle, &paramIndex, 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<bool>([&expertHandle, &paramIndex, 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<bool>([&expertHandle, &paramIndex, 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<bool>([&expertHandle, &paramIndex, 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<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);
}
+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.
}
}
+1
View File
@@ -59,6 +59,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ChartPeriod.cs" />
<Compile Include="EnumObject.cs" />
<Compile Include="EnumSeriesInfoInteger.cs" />
<Compile Include="EnumSymbolInfoDouble.cs" />
<Compile Include="EnumSymbolInfoInteger.cs" />
+32 -11
View File
@@ -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
///</summary>
public List<MtQuote> 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;
///<summary>
///Connection status of MetaTrader API.
///</summary>
public int ExecutorHandle
{
get
@@ -1746,14 +1749,32 @@ namespace MtApi
///<param name="price1">The price coordinate of the first anchor point.</param>
///<param name="time2">The time coordinate of the second anchor point.</param>
///<param name="price2">The price coordinate of the second anchor point.</param>
///<param name="time3">The price coordinate of the second anchor point.</param>
///<param name="time3">The time coordinate of the third anchor point.</param>
///<param name="price3">The price coordinate of the third anchor point.</param>
///<returns>
///Returns various data about securities listed in the "Market Watch" window.
///Returns true or false depending on whether the object is created or not.
///</returns>
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<string, object>();
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<bool>(MtCommandType.ObjectCreate, null, namedParams);
}
#endregion
@@ -1882,7 +1903,7 @@ namespace MtApi
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(state, message));
}
private T SendCommand<T>(MtCommandType commandType, ArrayList commandParameters)
private T SendCommand<T>(MtCommandType commandType, ArrayList commandParameters, Dictionary<string, object> 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)
{
+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)
{
+1 -4
View File
@@ -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)
{
+158 -109
View File
@@ -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;
}
///<summary>
@@ -56,15 +52,7 @@ namespace MtApi5
///<param name="port">Port of host connection (default 8222) </param>
public void BeginConnect(string host, int port)
{
//if (string.IsNullOrEmpty(host) == false && (host.Equals("localhost") || host.Equals("127.0.0.1")))
//{
// this.BeginConnect(port);
//}
//else
//{
Action<string, int> connectAction = Connect;
connectAction.BeginInvoke(host, port, null, null);
//}
Task.Factory.StartNew(() => Connect(host, port));
}
///<summary>
@@ -73,8 +61,7 @@ namespace MtApi5
///<param name="port">Port of host connection (default 8222) </param>
public void BeginConnect(int port)
{
Action<int> connectAction = Connect;
connectAction.BeginInvoke(port, null, null);
Task.Factory.StartNew(() => Connect(port));
}
///<summary>
@@ -82,8 +69,7 @@ namespace MtApi5
///</summary>
public void BeginDisconnect()
{
Action disconnectAction = Disconnect;
disconnectAction.BeginInvoke(null, null);
Task.Factory.StartNew(() => Disconnect(false));
}
///<summary>
@@ -91,11 +77,8 @@ namespace MtApi5
///</summary>
public IEnumerable<Mt5Quote> GetQuotes()
{
IEnumerable<MtQuote> 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
///<summary>
///Connection status of MetaTrader API.
///</summary>
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<T>(Mt5CommandType commandType, ArrayList commandParameters)
private T SendCommand<T>(Mt5CommandType commandType, ArrayList commandParameters, Dictionary<string, object> 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<T>(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<string>(Mt5CommandType.MtRequest, commandParameters);
if (res == null)
{
throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null");
}
var response = JsonConvert.DeserializeObject<T>(res.Value);
var response = JsonConvert.DeserializeObject<T>(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()));
}
+51
View File
@@ -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;
}
}
+16
View File
@@ -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}");
}
}
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.