mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 02:57:56 +00:00
Compare commits
22 Commits
mt4-1.0.32
...
mt4-1.0.33
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b76bf0547 | |||
| 1c269f7339 | |||
| 21fb790d8c | |||
| 7c9a0aa8cc | |||
| 18ddf3df1c | |||
| a8832b79ba | |||
| 39146d68b2 | |||
| 5b03f01e9b | |||
| 8f5a1c8222 | |||
| f5f13a13cc | |||
| 9ef970cf1e | |||
| b5878ccb62 | |||
| 4a7bb6f2cb | |||
| 5abfeebc90 | |||
| e333164552 | |||
| 9a6968f618 | |||
| d63a53b8a9 | |||
| 7e821fcade | |||
| 88e2d22abe | |||
| fcfd741e5b | |||
| c722511c03 | |||
| 39599436ab |
@@ -1,8 +1,7 @@
|
||||
namespace MTApiService
|
||||
{
|
||||
public interface ICommandManager
|
||||
internal interface ICommandManager
|
||||
{
|
||||
void EnqueueCommandTask(MtCommandTask task);
|
||||
MtCommandTask DequeueCommandTask();
|
||||
MtCommandTask SendCommand(MtCommand task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MTApiService
|
||||
{
|
||||
internal interface ITaskExecutor
|
||||
{
|
||||
void Execute(MtCommandTask task);
|
||||
|
||||
int Handle { get; }
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,6 @@ namespace MTApiService
|
||||
roller.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(roller);
|
||||
|
||||
var memory = new MemoryAppender();
|
||||
memory.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(memory);
|
||||
|
||||
#if (DEBUG)
|
||||
hierarchy.Root.Level = Level.Debug;
|
||||
#else
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ICommandManager.cs" />
|
||||
<Compile Include="IMetaTraderHandler.cs" />
|
||||
<Compile Include="ITaskExecutor.cs" />
|
||||
<Compile Include="LogConfigurator.cs" />
|
||||
<Compile Include="MtCommandEventArgs.cs" />
|
||||
<Compile Include="IDisposableChannel.cs" />
|
||||
@@ -78,11 +79,11 @@
|
||||
<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>
|
||||
|
||||
Executable → Regular
+53
-9
@@ -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;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ namespace MTApiService
|
||||
}
|
||||
}
|
||||
|
||||
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
|
||||
var expert = new MtExpert(expertHandle, new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle }, mtHandler);
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
@@ -111,7 +111,7 @@ namespace MTApiService
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.Quote = new MtQuote(symbol, bid, ask);
|
||||
expert.Quote = new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle };
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -133,7 +133,7 @@ namespace MTApiService
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.SendEvent(new MtEvent(eventType, payload));
|
||||
expert.SendEvent(new MtEvent { EventType = eventType, Payload = payload, ExpertHandle = expertHandle });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -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
|
||||
@@ -11,13 +11,13 @@ namespace MTApiService
|
||||
: base(callbackContext, binding, remoteAddress)
|
||||
{
|
||||
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
|
||||
InnerDuplexChannel.Open();
|
||||
}
|
||||
|
||||
#region IMtApi Members
|
||||
|
||||
public bool Connect()
|
||||
{
|
||||
InnerDuplexChannel.Open();
|
||||
return Channel.Connect();
|
||||
}
|
||||
|
||||
|
||||
+42
-90
@@ -6,38 +6,33 @@ using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
[CallbackBehavior(UseSynchronizationContext = false)]
|
||||
public class MtClient: IMtApiCallback, IDisposable
|
||||
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
|
||||
public class MtClient : IMtApiCallback, IDisposable
|
||||
{
|
||||
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 MtApiProxy _proxy;
|
||||
private bool _isConnected;
|
||||
private readonly MtApiProxy _proxy;
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void Open(string host, int port)
|
||||
#region ctor
|
||||
public MtClient(string host, int port)
|
||||
{
|
||||
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, 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");
|
||||
|
||||
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
|
||||
Host = host;
|
||||
Port = port;
|
||||
|
||||
if (_proxy != null)
|
||||
{
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
|
||||
|
||||
var bind = new NetTcpBinding(SecurityMode.None)
|
||||
{
|
||||
@@ -55,28 +50,19 @@ namespace MTApiService
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Open(int port)
|
||||
public MtClient(int port)
|
||||
{
|
||||
Log.DebugFormat("Open: begin. port = {0}", port);
|
||||
|
||||
if (port < 0 || port > 65536)
|
||||
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
|
||||
|
||||
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
|
||||
Port = port;
|
||||
|
||||
if (_proxy != null)
|
||||
{
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
|
||||
|
||||
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
|
||||
{
|
||||
@@ -94,61 +80,40 @@ namespace MTApiService
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Log.Debug("Close: begin.");
|
||||
|
||||
if (_proxy != null)
|
||||
{
|
||||
_proxy.Faulted -= ProxyFaulted;
|
||||
_proxy.Dispose();
|
||||
_proxy = null;
|
||||
}
|
||||
|
||||
_isConnected = false;
|
||||
|
||||
Log.Debug("Close: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public void Connect()
|
||||
{
|
||||
Log.Debug("Connect: begin.");
|
||||
|
||||
if (_proxy == null)
|
||||
if (_proxy.State != CommunicationState.Created)
|
||||
{
|
||||
Log.Error("Connect: _proxy is not defined.");
|
||||
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
|
||||
}
|
||||
|
||||
if (_isConnected)
|
||||
{
|
||||
Log.Warn("Connected: end. Client is already connected.");
|
||||
Log.ErrorFormat("Connected: end. Client has invalid state {0}", _proxy.State);
|
||||
return;
|
||||
}
|
||||
|
||||
bool coonected;
|
||||
|
||||
try
|
||||
{
|
||||
_isConnected = _proxy.Connect();
|
||||
coonected = _proxy.Connect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
throw new CommunicationException($"Connection failed to service. {ex.Message}");
|
||||
}
|
||||
|
||||
if (_isConnected == false)
|
||||
if (coonected == false)
|
||||
{
|
||||
Log.Error("Connect: end. Connection failed.");
|
||||
throw new CommunicationException("Connection failed");
|
||||
@@ -163,72 +128,60 @@ namespace MTApiService
|
||||
|
||||
try
|
||||
{
|
||||
_isConnected = false;
|
||||
|
||||
_proxy?.Disconnect();
|
||||
_proxy.Disconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
Log.Debug("Disconnect: end.");
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public MtResponse SendCommand(int commandType, ArrayList parameters)
|
||||
public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> namedParams, int expertHandle)
|
||||
{
|
||||
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
|
||||
|
||||
MtResponse result;
|
||||
|
||||
if (_isConnected == false)
|
||||
if (IsConnected == false)
|
||||
{
|
||||
Log.Error("SendCommand: Client is not connected.");
|
||||
throw new CommunicationException("Client is not connected.");
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Error("SendCommand: Proxy is not defined.");
|
||||
throw new CommunicationException("Proxy is not defined.");
|
||||
}
|
||||
MtResponse result;
|
||||
|
||||
try
|
||||
{
|
||||
result = _proxy.SendCommand(new MtCommand(commandType, parameters));
|
||||
result = _proxy.SendCommand(new MtCommand {
|
||||
CommandType = commandType,
|
||||
Parameters = parameters,
|
||||
NamedParams = namedParams,
|
||||
ExpertHandle = expertHandle});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
throw new CommunicationException("Service connection failed! " + ex.Message);
|
||||
}
|
||||
|
||||
Log.DebugFormat("SendCommand: end. result = {0}", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
public List<MtQuote> GetQuotes()
|
||||
{
|
||||
Log.Debug("GetQuotes: begin.");
|
||||
|
||||
if (_isConnected == false)
|
||||
if (IsConnected == false)
|
||||
{
|
||||
Log.Warn("GetQuotes: end. Client is not connected.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Warn("GetQuotes: end. _proxy is not defined.");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<MtQuote> result;
|
||||
|
||||
try
|
||||
@@ -239,8 +192,6 @@ namespace MTApiService
|
||||
{
|
||||
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
throw new CommunicationException($"Service connection failed! {ex.Message}");
|
||||
}
|
||||
|
||||
@@ -286,18 +237,17 @@ namespace MTApiService
|
||||
{
|
||||
Log.Debug("OnServerStopped: begin.");
|
||||
|
||||
Close();
|
||||
ServerDisconnected?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
Log.Debug("OnServerStopped: end.");
|
||||
}
|
||||
|
||||
|
||||
public void OnMtEvent(MtEvent mtEvent)
|
||||
public void OnMtEvent(MtEvent e)
|
||||
{
|
||||
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent);
|
||||
Log.DebugFormat("OnMtEvent: begin. event = {0}", e);
|
||||
|
||||
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
|
||||
MtEventReceived?.Invoke(e);
|
||||
|
||||
Log.Debug("OnMtEvent: end.");
|
||||
}
|
||||
@@ -305,7 +255,10 @@ namespace MTApiService
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool IsConnected => _proxy.State == CommunicationState.Opened && _isConnected;
|
||||
public string Host { get; private set; }
|
||||
public int Port { get; private set; }
|
||||
|
||||
private bool IsConnected => _proxy.State == CommunicationState.Opened;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -315,7 +268,6 @@ namespace MTApiService
|
||||
{
|
||||
Log.Debug("ProxyFaulted: begin.");
|
||||
|
||||
Close();
|
||||
ServerFailed?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
Log.Debug("ProxyFaulted: end.");
|
||||
@@ -329,7 +281,7 @@ namespace MTApiService
|
||||
{
|
||||
Log.Debug("Dispose: begin.");
|
||||
|
||||
Close();
|
||||
_proxy.Dispose();
|
||||
|
||||
Log.Debug("Dispose: end.");
|
||||
}
|
||||
@@ -342,7 +294,7 @@ namespace MTApiService
|
||||
public event MtQuoteHandler QuoteUpdated;
|
||||
public event EventHandler ServerDisconnected;
|
||||
public event EventHandler ServerFailed;
|
||||
public event EventHandler<MtEventArgs> MtEventReceived;
|
||||
public event MtEventHandler MtEventReceived;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
[DataContract]
|
||||
public class MtCommand
|
||||
{
|
||||
public MtCommand(int commandType, ArrayList parameters)
|
||||
{
|
||||
CommandType = commandType;
|
||||
Parameters = parameters;
|
||||
}
|
||||
[DataMember]
|
||||
public int CommandType { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public int CommandType { get; private set; }
|
||||
public ArrayList Parameters { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public ArrayList Parameters { get; private set; }
|
||||
public Dictionary<string, object> NamedParams { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public int ExpertHandle { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CommandType = {CommandType}";
|
||||
return $"CommandType = {CommandType}; ExpertHandle = {ExpertHandle}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-18
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,13 @@ using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
internal class MtCommandExecutorManager : ICommandManager
|
||||
internal class MtExecutorManager : ICommandManager
|
||||
{
|
||||
#region Private Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager));
|
||||
|
||||
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
|
||||
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
|
||||
private 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
|
||||
|
||||
@@ -23,149 +22,94 @@ namespace MTApiService
|
||||
|
||||
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)
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
if (executor == null)
|
||||
throw new ArgumentNullException(nameof(executor));
|
||||
|
||||
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
Log.DebugFormat("AddExecutor: begin. executor = {0}", executor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor))
|
||||
if (_executorList.Contains(executor))
|
||||
{
|
||||
Log.Warn("AddCommandExecutor: end. Command executor already exist.");
|
||||
Log.Warn("AddExecutor: end. Executor already exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
_commandExecutors.Add(commandExecutor);
|
||||
if (_commandTasks.Count > 0)
|
||||
{
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted;
|
||||
commandExecutor.CommandManager = this;
|
||||
|
||||
if (notify)
|
||||
{
|
||||
NotifyCommandReady();
|
||||
_executorList.Add(executor);
|
||||
_executorMap[executor.Handle] = executor;
|
||||
}
|
||||
|
||||
Log.Debug("AddCommandExecutor: end.");
|
||||
}
|
||||
|
||||
public void RemoveCommandExecutor(MtExpert commandExecutor)
|
||||
public void RemoveExecutor(ITaskExecutor executor)
|
||||
{
|
||||
if (commandExecutor == null)
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
if (executor == null)
|
||||
throw new ArgumentNullException(nameof(executor));
|
||||
|
||||
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
Log.DebugFormat("RemoveExecutor: begin. executor = {0}", executor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor) == false)
|
||||
if (_executorList.Contains(executor) == false)
|
||||
{
|
||||
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection.");
|
||||
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("RemoveCommandExecutor: end.");
|
||||
Log.Debug("SendTask: end.");
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
public void EnqueueCommandTask(MtCommandTask task)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
|
||||
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_commandTasks.Enqueue(task);
|
||||
}
|
||||
|
||||
NotifyCommandReady();
|
||||
|
||||
Log.Debug("EnqueueCommandTask: end.");
|
||||
}
|
||||
|
||||
public MtCommandTask DequeueCommandTask()
|
||||
{
|
||||
Log.Debug("DequeueCommandTask: called.");
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void NotifyCommandReady()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
var commandExecutors = new List<MtExpert>();
|
||||
lock (_locker)
|
||||
{
|
||||
commandExecutors.AddRange(_commandExecutors);
|
||||
}
|
||||
|
||||
foreach (var executor in commandExecutors)
|
||||
{
|
||||
executor.NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
|
||||
}
|
||||
|
||||
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
|
||||
{
|
||||
Log.Debug("CommandExecutor_CommandExecuted: begin.");
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandTasks.Count > 0)
|
||||
{
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify)
|
||||
{
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("CommandExecutor_CommandExecuted: end.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+91
-52
@@ -1,18 +1,20 @@
|
||||
using System;
|
||||
using log4net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class MtExpert
|
||||
internal 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 _commandTask;
|
||||
private ICommandManager _commandManager;
|
||||
private MtCommandTask _currentTask;
|
||||
private readonly Queue<MtCommandTask> _taskQueue = new Queue<MtCommandTask>();
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
|
||||
@@ -41,9 +43,8 @@ namespace MTApiService
|
||||
{
|
||||
Log.DebugFormat("SendResponse: begin. response = {0}", response);
|
||||
|
||||
_commandTask.SetResult(response);
|
||||
_commandTask = null;
|
||||
FireOnCommandExecuted();
|
||||
_currentTask.SetResult(response);
|
||||
_currentTask = null;
|
||||
|
||||
Log.Debug("SendResponse: end.");
|
||||
}
|
||||
@@ -52,20 +53,16 @@ namespace MTApiService
|
||||
{
|
||||
Log.Debug("GetCommandType: called.");
|
||||
|
||||
var commandManager = CommandManager;
|
||||
if (commandManager != null)
|
||||
{
|
||||
_commandTask = commandManager.DequeueCommandTask();
|
||||
}
|
||||
_currentTask = DequeueTask();
|
||||
|
||||
return _commandTask?.Command?.CommandType ?? 0;
|
||||
return _currentTask?.Command?.CommandType ?? 0;
|
||||
}
|
||||
|
||||
public object GetCommandParameter(int index)
|
||||
{
|
||||
Log.DebugFormat("GetCommandType: called. index = {0}", index);
|
||||
Log.DebugFormat("GetCommandParameter: called. index = {0}", index);
|
||||
|
||||
var command = _commandTask?.Command;
|
||||
var command = _currentTask?.Command;
|
||||
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
|
||||
{
|
||||
return command.Parameters[index];
|
||||
@@ -74,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);
|
||||
@@ -90,7 +127,22 @@ namespace MTApiService
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITaskExecutor
|
||||
|
||||
public void Execute(MtCommandTask task)
|
||||
{
|
||||
lock (_taskQueue)
|
||||
{
|
||||
_taskQueue.Enqueue(task);
|
||||
}
|
||||
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private MtQuote _quote;
|
||||
public MtQuote Quote
|
||||
{
|
||||
@@ -133,41 +185,34 @@ namespace MTApiService
|
||||
}
|
||||
}
|
||||
|
||||
public ICommandManager CommandManager
|
||||
{
|
||||
private get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _commandManager;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_commandManager = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMtCommandExecutor
|
||||
public void NotifyCommandReady()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
SendTickToMetaTrader();
|
||||
|
||||
Log.Debug("NotifyCommandReady: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void SendTickToMetaTrader()
|
||||
private MtCommandTask DequeueTask()
|
||||
{
|
||||
Log.Debug("DequeueTask: called.");
|
||||
|
||||
MtCommandTask task;
|
||||
int count;
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
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)
|
||||
@@ -180,22 +225,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;
|
||||
public event MtEventHandler OnMtEvent;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,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),
|
||||
@@ -22,6 +23,28 @@ namespace MTApiService
|
||||
}
|
||||
|
||||
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]
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace MTApiService
|
||||
|
||||
private readonly MtService _service;
|
||||
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
|
||||
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
|
||||
private readonly MtExecutorManager _executorManager = new MtExecutorManager();
|
||||
private readonly List<MtExpert> _experts = new List<MtExpert>();
|
||||
#endregion
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace MTApiService
|
||||
_experts.Add(expert);
|
||||
}
|
||||
|
||||
_executorManager.AddCommandExecutor(expert);
|
||||
_executorManager.AddExecutor(expert);
|
||||
|
||||
_service.OnQuoteAdded(expert.Quote);
|
||||
|
||||
@@ -170,11 +170,20 @@ namespace MTApiService
|
||||
return null;
|
||||
}
|
||||
|
||||
var task = new MtCommandTask(command);
|
||||
_executorManager.EnqueueCommandTask(task);
|
||||
var task = _executorManager.SendCommand(command);
|
||||
|
||||
//wait for execute command in MetaTrader
|
||||
var response = task.WaitResult(WaitResponseTime);
|
||||
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;
|
||||
}
|
||||
@@ -371,7 +380,7 @@ namespace MTApiService
|
||||
expertsCount = _experts.Count;
|
||||
}
|
||||
|
||||
_executorManager.RemoveCommandExecutor(expert);
|
||||
_executorManager.RemoveExecutor(expert);
|
||||
|
||||
expert.Deinited -= expert_Deinited;
|
||||
expert.QuoteChanged -= expert_QuoteChanged;
|
||||
@@ -398,11 +407,11 @@ namespace MTApiService
|
||||
Log.Debug("expert_QuoteChanged: end.");
|
||||
}
|
||||
|
||||
private void Expert_OnMtEvent(object sender, MtEventArgs e)
|
||||
private void Expert_OnMtEvent(MtExpert expert, MtEvent e)
|
||||
{
|
||||
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event);
|
||||
Log.DebugFormat("Expert_OnMtEvent: begin. expert = {0}, event = {1}", expert, e);
|
||||
|
||||
_service.OnMtEvent(e.Event);
|
||||
_service.OnMtEvent(e);
|
||||
|
||||
Log.Debug("Expert_OnMtEvent: end.");
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace MTApiService
|
||||
|
||||
if (callback == null)
|
||||
{
|
||||
Log.Warn("Connect: end. Callback is not definded.");
|
||||
Log.Warn("Connect: end. Callback is not defined.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace MTApiService
|
||||
|
||||
public void QuoteUpdate(MtQuote quote)
|
||||
{
|
||||
Log.Debug("QuoteUpdate: begin.");
|
||||
Log.DebugFormat("QuoteUpdate: begin. quote = {0}", quote);
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace MTApiService
|
||||
|
||||
public void OnQuoteAdded(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteAdded: begin.");
|
||||
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
|
||||
|
||||
@@ -176,18 +176,18 @@ namespace MTApiService
|
||||
|
||||
public void OnQuoteRemoved(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteRemoved: begin.");
|
||||
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)
|
||||
{
|
||||
Log.Debug("OnMtEvent: begin.");
|
||||
Log.DebugFormat("OnMtEvent: begin.quote = {0}", e);
|
||||
|
||||
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
|
||||
ExecuteCallbackAction(a => a.OnMtEvent(e));
|
||||
|
||||
Log.Debug("OnMtEvent: end.");
|
||||
}
|
||||
|
||||
Executable → Regular
+2
-2
@@ -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.23.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.23.0")]
|
||||
[assembly: AssemblyVersion("1.0.25.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.25.0")]
|
||||
+179
-199
@@ -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,6 +18,8 @@ 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);
|
||||
@@ -24,264 +27,241 @@ void convertSystemString(wchar_t* dest, String^ src)
|
||||
dest[wcslen(wch)] = '\0';
|
||||
}
|
||||
|
||||
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
|
||||
template <typename T> T Execute(std::function<T()> func, wchar_t* err, T default_value)
|
||||
{
|
||||
T result = default_value;
|
||||
try
|
||||
{
|
||||
result = func();
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
_DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
|
||||
{
|
||||
return Execute<bool>([&expertHandle, &port, symbol, &bid, &ask]() {
|
||||
MT4Handler^ mtHandler = gcnew MT4Handler();
|
||||
MtAdapter::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
|
||||
return true;
|
||||
}, err, false);
|
||||
|
||||
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)
|
||||
_DLLAPI bool _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;
|
||||
return Execute<bool>([&expertHandle]() {
|
||||
MtAdapter::GetInstance()->DeinitExpert(expertHandle);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
|
||||
_DLLAPI bool _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;
|
||||
return Execute<bool>([&expertHandle, symbol, &bid, &ask]() {
|
||||
MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
|
||||
int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
|
||||
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:updateTimeBar(): " + 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 sendIntResponse(int expertHandle, int response)
|
||||
_DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, 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, &response]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendBooleanResponse(int expertHandle, int response)
|
||||
_DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, 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, &response]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendDoubleResponse(int expertHandle, double response)
|
||||
_DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, 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, &response]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
|
||||
_DLLAPI bool _stdcall sendStringResponse(int expertHandle, wchar_t* response, 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, response]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendVoidResponse(int expertHandle)
|
||||
_DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, 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, &code, message]() {
|
||||
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
|
||||
res->ErrorCode = code;
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, res);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
|
||||
_DLLAPI bool _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Execute<bool>([&expertHandle]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
_DLLAPI bool _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size, wchar_t* err)
|
||||
{
|
||||
return Execute<bool>([&expertHandle, values, &size]() {
|
||||
array<double>^ list = gcnew array<double>(size);
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
|
||||
_DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int size, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Execute<bool>([&expertHandle, values, &size]() {
|
||||
array<int>^ list = gcnew array<int>(size);
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall sendLongResponse(int expertHandle, __int64 response)
|
||||
_DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendLongResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return Execute<bool>([&expertHandle, &response]() {
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall getCommandType(int expertHandle, int* res)
|
||||
_DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, 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, res]() {
|
||||
*res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
|
||||
_DLLAPI bool _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] MTConnector:getIntValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return Execute<bool>([&expertHandle, ¶mIndex, res]() {
|
||||
*res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
|
||||
// --- index parameters
|
||||
|
||||
_DLLAPI bool _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] MTConnector:getDoubleValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return Execute<bool>([&expertHandle, ¶mIndex, res]() {
|
||||
*res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
|
||||
_DLLAPI bool _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] MTConnector:getStringValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return Execute<bool>([&expertHandle, ¶mIndex, res]() {
|
||||
convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
|
||||
_DLLAPI bool _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<bool>([&expertHandle, ¶mIndex, 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, ¶mIndex, 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);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
LIBRARY MTConnector
|
||||
|
||||
EXPORTS initExpert
|
||||
deinitExpert
|
||||
updateQuote
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
sendLongResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
getBooleanValue
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -59,12 +59,17 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChartPeriod.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="ExtensionMethods.cs" />
|
||||
<Compile Include="FlagFontStyle.cs" />
|
||||
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
<Compile Include="MqlTick.cs" />
|
||||
|
||||
+633
-108
@@ -8,6 +8,7 @@ using System.ServiceModel;
|
||||
using MtApi.Requests;
|
||||
using MtApi.Responses;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
@@ -15,8 +16,6 @@ namespace MtApi
|
||||
|
||||
public sealed class MtApiClient
|
||||
{
|
||||
private volatile bool _isBacktestingMode;
|
||||
|
||||
#region MetaTrader Constants
|
||||
|
||||
//Special constant
|
||||
@@ -27,9 +26,11 @@ namespace MtApi
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly MtClient _client = new MtClient();
|
||||
private MtClient _client;
|
||||
private readonly object _locker = new object();
|
||||
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
|
||||
private volatile bool _isBacktestingMode;
|
||||
private int _executorHandle;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
@@ -37,13 +38,6 @@ namespace MtApi
|
||||
public MtApiClient()
|
||||
{
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
|
||||
_client.QuoteAdded += _client_QuoteAdded;
|
||||
_client.QuoteRemoved += _client_QuoteRemoved;
|
||||
_client.QuoteUpdated += _client_QuoteUpdated;
|
||||
_client.ServerDisconnected += _client_ServerDisconnected;
|
||||
_client.ServerFailed += _client_ServerFailed;
|
||||
_client.MtEventReceived += _client_MtEventReceived;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -55,8 +49,7 @@ namespace MtApi
|
||||
///<param name="port">Port of host connection (default 8222) </param>
|
||||
public void BeginConnect(string host, int port)
|
||||
{
|
||||
Action<string, int> connectAction = Connect;
|
||||
connectAction.BeginInvoke(host, port, null, null);
|
||||
Task.Factory.StartNew(() => Connect(host, port));
|
||||
}
|
||||
|
||||
///<summary>
|
||||
@@ -65,8 +58,7 @@ namespace MtApi
|
||||
///<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>
|
||||
@@ -74,21 +66,17 @@ namespace MtApi
|
||||
///</summary>
|
||||
public void BeginDisconnect()
|
||||
{
|
||||
Action disconnectAction = Disconnect;
|
||||
disconnectAction.BeginInvoke(null, null);
|
||||
Task.Factory.StartNew(() => Disconnect(false));
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Load quotes connected into MetaTrader API.
|
||||
///</summary>
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
public List<MtQuote> GetQuotes()
|
||||
{
|
||||
IEnumerable<MTApiService.MtQuote> quotes;
|
||||
lock (_client)
|
||||
{
|
||||
quotes = _client.GetQuotes();
|
||||
}
|
||||
return quotes?.Select(q => q.Convert());
|
||||
var client = Client;
|
||||
var quotes = client != null ? client.GetQuotes() : null;
|
||||
return quotes?.Select(q => new MtQuote(q)).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -107,6 +95,27 @@ namespace MtApi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Handle of expert used to execute commands
|
||||
///</summary>
|
||||
public int ExecutorHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _executorHandle;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_executorHandle = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -852,10 +861,10 @@ namespace MtApi
|
||||
return SendCommand<int>(MtCommandType.MessageBox, commandParameters);
|
||||
}
|
||||
|
||||
public void PlaySound(string filename)
|
||||
public bool PlaySound(string filename)
|
||||
{
|
||||
var commandParameters = new ArrayList { filename };
|
||||
SendCommand<object>(MtCommandType.PlaySound, commandParameters);
|
||||
return SendCommand<bool>(MtCommandType.PlaySound, commandParameters);
|
||||
}
|
||||
|
||||
public void Print(string msg)
|
||||
@@ -876,10 +885,10 @@ namespace MtApi
|
||||
return SendCommand<bool>(MtCommandType.SendFTPA, commandParameters);
|
||||
}
|
||||
|
||||
public void SendMail(string subject, string someText)
|
||||
public bool SendMail(string subject, string someText)
|
||||
{
|
||||
var commandParameters = new ArrayList { subject, someText };
|
||||
SendCommand<object>(MtCommandType.SendMail, commandParameters);
|
||||
return SendCommand<bool>(MtCommandType.SendMail, commandParameters);
|
||||
}
|
||||
|
||||
public void Sleep(int milliseconds)
|
||||
@@ -1704,45 +1713,555 @@ namespace MtApi
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void Connect(string host, int port)
|
||||
#region Chart Operations
|
||||
|
||||
///<summary>
|
||||
///Returns the ID of the current chart.
|
||||
///</summary>
|
||||
///<returns>
|
||||
/// Value of long type.
|
||||
///</returns>
|
||||
public long ChartId()
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to {host}:{port}");
|
||||
try
|
||||
return SendCommand<long>(MtCommandType.ChartId, null);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///This function calls a forced redrawing of a specified chart.
|
||||
///</summary>
|
||||
public void ChartRedraw(long chartId = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId };
|
||||
SendCommand<object>(MtCommandType.ChartRedraw, commandParameters);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object Functions
|
||||
|
||||
///<summary>
|
||||
///The function creates an object with the specified name, type, and the initial coordinates in the specified chart subwindow of the specified chart.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object. The name must be unique within a chart, including its subwindows.</param>
|
||||
///<param name="objectType">Object type.</param>
|
||||
///<param name="subWindow">Number of the chart subwindow. 0 means the main chart window.</param>
|
||||
///<param name="time1">The time coordinate of the first anchor point.</param>
|
||||
///<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 time coordinate of the third anchor point.</param>
|
||||
///<param name="price3">The price coordinate of the third anchor point.</param>
|
||||
///<returns>
|
||||
///Returns true or false depending on whether the object is created or not.
|
||||
///</returns>
|
||||
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)
|
||||
{
|
||||
var namedParams = new Dictionary<string, object>
|
||||
{
|
||||
lock (_client)
|
||||
{nameof(chartId), chartId},
|
||||
{nameof(objectName), objectName},
|
||||
{nameof(objectType), (int) objectType},
|
||||
{nameof(subWindow), subWindow},
|
||||
{nameof(time1), MtApiTimeConverter.ConvertToMtTime(time1)},
|
||||
{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);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the name of the corresponding object by its index in the objects list.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectIndex">Object index. This value must be greater or equal to 0 and less than ObjectsTotal().</param>
|
||||
///<param name="subWindow">Number of the chart window. Must be greater or equal to -1 (-1 mean all subwindows, 0 means the main chart window) and less than WindowsTotal().</param>
|
||||
///<param name="objectType">Type of the object. The value can be one of the values of the EnumObject enumeration. EMPTY (-1) means all types.</param>
|
||||
///<returns>
|
||||
///Name of the object is returned in case of success.
|
||||
///</returns>
|
||||
public string ObjectName(long chartId, int objectIndex, int subWindow = EMPTY, int objectType = EMPTY)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectIndex, subWindow, objectType };
|
||||
return SendCommand<string>(MtCommandType.ObjectName, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function removes the object with the specified name at the specified chart.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of object to be deleted.</param>
|
||||
///<returns>
|
||||
///Returns true if the removal was successful, otherwise returns false.
|
||||
///</returns>
|
||||
public bool ObjectDelete(long chartId, string objectName)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName };
|
||||
return SendCommand<bool>(MtCommandType.ObjectDelete, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function removes the object with the specified name at the specified chart.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="subWindow">Number of the chart window. Must be greater or equal to -1 (-1 mean all subwindows, 0 means the main chart window) and less than WindowsTotal().</param>
|
||||
///<param name="objectType">Type of the object. The value can be one of the values of the EnumObject enumeration. EMPTY (-1) means all types.</param>
|
||||
///<returns>
|
||||
///Returns true if the removal was successful, otherwise returns false.
|
||||
///</returns>
|
||||
public int ObjectsDeleteAll(long chartId, int subWindow = EMPTY, int objectType = EMPTY)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, subWindow, objectType };
|
||||
return SendCommand<int>(MtCommandType.ObjectsDeleteAll, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function searches for an object having the specified name.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">The name of the object to find.</param>
|
||||
///<returns>
|
||||
///If successful the function returns the number of the subwindow (0 means the main window of the chart), in which the object is found.
|
||||
///</returns>
|
||||
public int ObjectFind(long chartId, string objectName)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName };
|
||||
return SendCommand<int>(MtCommandType.ObjectFind, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the time value for the specified price value of the specified object.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="value">Price value.</param>
|
||||
///<param name="lineId">Line identifier.</param>
|
||||
///<returns>
|
||||
///The time value for the specified price value of the specified object.
|
||||
///</returns>
|
||||
public DateTime ObjectGetTimeByValue(long chartId, string objectName, double value, int lineId = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, value, lineId };
|
||||
var res = SendCommand<int>(MtCommandType.ObjectGetTimeByValue, commandParameters);
|
||||
return MtApiTimeConverter.ConvertFromMtTime(res);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the price value for the specified time value of the specified object.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="time">Time value.</param>
|
||||
///<param name="lineId">Line identifier.</param>
|
||||
///<returns>
|
||||
///The price value for the specified time value of the specified object.
|
||||
///</returns>
|
||||
public double ObjectGetValueByTime(long chartId, string objectName, DateTime? time, int lineId = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, time, lineId };
|
||||
return SendCommand<double>(MtCommandType.ObjectGetValueByTime, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function changes coordinates of the specified anchor point of the object at the specified chart
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="pointIndex">Index of the anchor point.</param>
|
||||
///<param name="time">Time coordinate of the selected anchor point.</param>
|
||||
///<param name="price">Price coordinate of the selected anchor point.</param>
|
||||
///<returns>
|
||||
///If successful, returns true, in case of failure returns false.
|
||||
///</returns>
|
||||
public bool ObjectMove(long chartId, string objectName, int pointIndex, DateTime? time, double price)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, pointIndex, MtApiTimeConverter.ConvertToMtTime(time), price };
|
||||
return SendCommand<bool>(MtCommandType.ObjectMove, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function changes coordinates of the specified anchor point of the object at the specified chart.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="subWindow">Number of the chart subwindow. 0 means the main chart window, -1 means all the subwindows of the chart, including the main window.</param>
|
||||
///<param name="type">Type of the object. The value can be one of the values of the EnumObject enumeration. EMPTY(-1) means all types.</param>
|
||||
///<returns>
|
||||
///The number of objects.
|
||||
///</returns>
|
||||
public int ObjectsTotal(long chartId, int subWindow = EMPTY, int type = EMPTY)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, subWindow, type };
|
||||
return SendCommand<int>(MtCommandType.ObjectsTotal, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the value of the corresponding object property.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyDouble enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier.</param>
|
||||
///<returns>
|
||||
///Value of the double type.
|
||||
///</returns>
|
||||
public double ObjectGetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, int propModifier = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier };
|
||||
return SendCommand<double>(MtCommandType.ObjectGetDouble, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the value of the corresponding object property. The object property must be of the datetime, int, color, bool or char type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyDouble enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier.</param>
|
||||
///<returns>
|
||||
///The long value.
|
||||
///</returns>
|
||||
public long ObjectGetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, int propModifier = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier };
|
||||
return SendCommand<long>(MtCommandType.ObjectGetInteger, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the value of the corresponding object property. The object property must be of the string type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyString enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero.</param>
|
||||
///<returns>
|
||||
///String value.
|
||||
///</returns>
|
||||
public string ObjectGetString(long chartId, string objectName, EnumObjectPropertyString propId, int propModifier = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier };
|
||||
return SendCommand<string>(MtCommandType.ObjectGetString, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the double type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyDouble enumeration.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully.
|
||||
///</returns>
|
||||
public bool ObjectSetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, double propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetDouble, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the double type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyDouble enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully.
|
||||
///</returns>
|
||||
public bool ObjectSetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, int propModifier, double propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
var namedParams = new Dictionary<string, object> {{nameof(propModifier), propModifier}};
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetDouble, commandParameters, namedParams);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the int type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyInteger enumeration.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false.
|
||||
///</returns>
|
||||
public bool ObjectSetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, long propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetInteger, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the int type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyInteger enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false.
|
||||
///</returns>
|
||||
public bool ObjectSetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, int propModifier, long propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
var namedParams = new Dictionary<string, object> {{nameof(propModifier), propModifier}};
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetInteger, commandParameters, namedParams);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the string type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyString enumeration.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false.
|
||||
///</returns>
|
||||
public bool ObjectSetString(long chartId, string objectName, EnumObjectPropertyString propId, string propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetString, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the value of the corresponding object property. The object property must be of the string type.
|
||||
///</summary>
|
||||
///<param name="chartId">Chart identifier. 0 means the current chart.</param>
|
||||
///<param name="objectName">Name of the object.</param>
|
||||
///<param name="propId">ID of the object property. The value can be one of the values of the EnumObjectPropertyString enumeration.</param>
|
||||
///<param name="propModifier">Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero.</param>
|
||||
///<param name="propValue">The value of the property.</param>
|
||||
///<returns>
|
||||
///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false.
|
||||
///</returns>
|
||||
public bool ObjectSetString(long chartId, string objectName, EnumObjectPropertyString propId, int propModifier, string propValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue };
|
||||
var namedParams = new Dictionary<string, object> {{nameof(propModifier), propModifier}};
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetString, commandParameters, namedParams);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets the font for displaying the text using drawing methods and returns the result of that operation. Arial font with the size -120 (12 pt) is used by default.
|
||||
///</summary>
|
||||
///<param name="name">Font name in the system or the name of the resource containing the font or the path to font file on the disk.</param>
|
||||
///<param name="size">The font size that can be set using positive and negative values. In case of positive values, the size of a displayed text does not depend on the operating system's font size settings. In case of negative values, the value is set in tenths of a point and the text size depends on the operating system settings ("standard scale" or "large scale"). See the Note below for more information about the differences between the modes.</param>
|
||||
///<param name="flags">Combination of flags describing font style.</param>
|
||||
///<param name="orientation">Text's horizontal inclination to X axis, the unit of measurement is 0.1 degrees. It means that orientation=450 stands for inclination equal to 45 degrees.</param>
|
||||
///<returns>
|
||||
///Returns true if the current font is successfully installed, otherwise false.
|
||||
///</returns>
|
||||
public bool TextSetFont(string name, int size, FlagFontStyle flags = 0, int orientation = 0)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, size, (uint)flags, orientation };
|
||||
return SendCommand<bool>(MtCommandType.TextSetFont, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the object description.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<returns>
|
||||
///Object description. For objects of OBJ_TEXT and OBJ_LABEL types, the text drawn by these objects will be returned.
|
||||
///</returns>
|
||||
public string ObjectDescription(string objectName)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName };
|
||||
return SendCommand<string>(MtCommandType.ObjectDescription, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the level description of a Fibonacci object.
|
||||
///</summary>
|
||||
///<param name="objectName">Fibonacci object name.</param>
|
||||
///<param name="index">Index of the Fibonacci level (0-31).</param>
|
||||
///<returns>
|
||||
///The level description of a Fibonacci object.
|
||||
///</returns>
|
||||
public string ObjectGetFiboDescription(string objectName, int index)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, index };
|
||||
return SendCommand<string>(MtCommandType.ObjectGetFiboDescription, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function calculates and returns bar index (shift related to the current bar) for the given price.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<param name="value">Price value.</param>
|
||||
///<returns>
|
||||
///The function calculates and returns bar index (shift related to the current bar) for the given price. The bar index is calculated by the first and second coordinates using a linear equation. Applied to trendlines and similar objects.
|
||||
///</returns>
|
||||
public int ObjectGetShiftByValue(string objectName, double value)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, value };
|
||||
return SendCommand<int>(MtCommandType.ObjectGetShiftByValue, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function calculates and returns the price value for the specified bar (shift related to the current bar).
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<param name="shift">Bar index.</param>
|
||||
///<returns>
|
||||
///The function calculates and returns the price value for the specified bar (shift related to the current bar). The price value is calculated by the first and second coordinates using a linear equation. Applied to trendlines and similar objects.
|
||||
///</returns>
|
||||
public double ObjectGetValueByShift(string objectName, int shift)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, shift };
|
||||
return SendCommand<double>(MtCommandType.ObjectGetValueByShift, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Changes the value of the specified object property.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<param name="index">Object property index. It can be any of object properties enumeration values.</param>
|
||||
///<param name="value">New value of the given property.</param>
|
||||
///<returns>
|
||||
///If the function succeeds, the returned value will be true, otherwise it returns false.
|
||||
///</returns>
|
||||
public bool ObjectSet(string objectName, int index, double value)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, index, value };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSet, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function sets a new description to a level of a Fibonacci object.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<param name="index">Index of the Fibonacci level (0-31).</param>
|
||||
///<param name="text">New description of the level.</param>
|
||||
///<returns>
|
||||
///The function returns true if successful, otherwise false.
|
||||
///</returns>
|
||||
public bool ObjectSetFiboDescription(string objectName, int index, string text)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, index, text };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetFiboDescription, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function changes the object description.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<param name="text">A text describing the object.</param>
|
||||
///<param name="fontSize">Font size in points.</param>
|
||||
///<param name="fontName">Font name.</param>
|
||||
///<param name="textColor">Font color.</param>
|
||||
///<returns>
|
||||
///Changes the object description. If the function succeeds, the returned value will be true, otherwise false.
|
||||
///</returns>
|
||||
public bool ObjectSetText(string objectName, string text, int fontSize = 0, string fontName = null, Color? textColor = null)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName, text, fontSize, fontName, MtApiColorConverter.ConvertToMtColor(textColor) };
|
||||
return SendCommand<bool>(MtCommandType.ObjectSetText, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns the object type value.
|
||||
///</summary>
|
||||
///<param name="objectName">Object name.</param>
|
||||
///<returns>
|
||||
///The function returns the object type value.
|
||||
///</returns>
|
||||
public EnumObject ObjectType(string objectName)
|
||||
{
|
||||
var commandParameters = new ArrayList { objectName };
|
||||
return (EnumObject)SendCommand<int>(MtCommandType.ObjectType, commandParameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private MtClient Client
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(_locker)
|
||||
{
|
||||
_client.Open(host, port);
|
||||
_client.Connect();
|
||||
return _client;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
}
|
||||
|
||||
private void Connect(MtClient client)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to {host}:{port}. {e.Message}");
|
||||
return;
|
||||
if (_connectionState == MtConnectionState.Connected
|
||||
|| _connectionState == MtConnectionState.Connecting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_connectionState = MtConnectionState.Connecting;
|
||||
}
|
||||
UpdateConnectionState(MtConnectionState.Connected, $"Connected to {host}:{port}");
|
||||
OnConnected();
|
||||
|
||||
string message = string.IsNullOrEmpty(client.Host) ? $"Connecting to localhost:{client.Port}" : $"Connecting to {client.Host}:{client.Port}";
|
||||
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(MtConnectionState.Connecting, message));
|
||||
|
||||
var state = MtConnectionState.Failed;
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
try
|
||||
{
|
||||
client.Connect();
|
||||
state = MtConnectionState.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 == MtConnectionState.Connected)
|
||||
{
|
||||
_client = client;
|
||||
_client.QuoteAdded += _client_QuoteAdded;
|
||||
_client.QuoteRemoved += _client_QuoteRemoved;
|
||||
_client.QuoteUpdated += _client_QuoteUpdated;
|
||||
_client.ServerDisconnected += _client_ServerDisconnected;
|
||||
_client.ServerFailed += _client_ServerFailed;
|
||||
_client.MtEventReceived += _client_MtEventReceived;
|
||||
message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}";
|
||||
}
|
||||
|
||||
_connectionState = state;
|
||||
}
|
||||
|
||||
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(state, message));
|
||||
|
||||
if (state == MtConnectionState.Connected)
|
||||
{
|
||||
OnConnected();
|
||||
}
|
||||
}
|
||||
|
||||
private void Connect(string host, int port)
|
||||
{
|
||||
var client = new MtClient(host, port);
|
||||
Connect(client);
|
||||
}
|
||||
|
||||
private void Connect(int port)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Connecting, $"Connecting to 'localhost':{port}");
|
||||
try
|
||||
{
|
||||
lock (_client)
|
||||
{
|
||||
_client.Open(port);
|
||||
_client.Connect();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, $"Failed connection to 'localhost':{port}. {e.Message}");
|
||||
return;
|
||||
}
|
||||
UpdateConnectionState(MtConnectionState.Connected, $"Connected to 'localhost':{port}");
|
||||
OnConnected();
|
||||
var client = new MtClient(port);
|
||||
Connect(client);
|
||||
}
|
||||
|
||||
private void OnConnected()
|
||||
@@ -1754,50 +2273,72 @@ namespace MtApi
|
||||
}
|
||||
}
|
||||
|
||||
private void Disconnect()
|
||||
private void Disconnect(bool failed)
|
||||
{
|
||||
lock (_client)
|
||||
{
|
||||
_client.Disconnect();
|
||||
_client.Close();
|
||||
}
|
||||
var state = failed ? MtConnectionState.Failed : MtConnectionState.Disconnected;
|
||||
var message = failed ? "Connection Failed" : "Disconnected";
|
||||
|
||||
UpdateConnectionState(MtConnectionState.Disconnected, "Disconnected");
|
||||
}
|
||||
|
||||
private void UpdateConnectionState(MtConnectionState state, string message)
|
||||
{
|
||||
var changed = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_connectionState != state)
|
||||
if (_connectionState == MtConnectionState.Disconnected
|
||||
|| _connectionState == MtConnectionState.Failed)
|
||||
return;
|
||||
|
||||
if (_client != null)
|
||||
{
|
||||
_connectionState = state;
|
||||
changed = true;
|
||||
_client.QuoteAdded -= _client_QuoteAdded;
|
||||
_client.QuoteRemoved -= _client_QuoteRemoved;
|
||||
_client.QuoteUpdated -= _client_QuoteUpdated;
|
||||
_client.ServerDisconnected -= _client_ServerDisconnected;
|
||||
_client.ServerFailed -= _client_ServerFailed;
|
||||
_client.MtEventReceived -= _client_MtEventReceived;
|
||||
|
||||
if (!failed)
|
||||
{
|
||||
_client.Disconnect();
|
||||
}
|
||||
|
||||
_client.Dispose();
|
||||
|
||||
_client = null;
|
||||
}
|
||||
|
||||
_connectionState = state;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
ConnectionStateChanged.FireEventAsync(this, new MtConnectionEventArgs(state, message));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
var client = Client;
|
||||
if (client == null)
|
||||
{
|
||||
throw new MtConnectionException("No connection");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (_client)
|
||||
{
|
||||
response = _client.SendCommand((int)commandType, commandParameters);
|
||||
}
|
||||
response = client.SendCommand((int)commandType, commandParameters, namedParams, ExecutorHandle);
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
throw new MtConnectionException(ex.Message, ex);
|
||||
}
|
||||
|
||||
if (response == null)
|
||||
{
|
||||
throw new MtExecutionException(MtErrorCode.MtApiCustomError, "Response from MetaTrader is null");
|
||||
}
|
||||
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
throw new MtExecutionException((MtErrorCode)response.ErrorCode, response.ToString());
|
||||
}
|
||||
|
||||
var responseValue = response.GetValue();
|
||||
return responseValue != null ? (T)responseValue : default(T);
|
||||
}
|
||||
@@ -1814,25 +2355,14 @@ namespace MtApi
|
||||
});
|
||||
var commandParameters = new ArrayList { serializer };
|
||||
|
||||
MtResponseString res;
|
||||
try
|
||||
{
|
||||
lock (_client)
|
||||
{
|
||||
res = (MtResponseString)_client.SendCommand((int)MtCommandType.MtRequest, commandParameters);
|
||||
}
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
throw new MtConnectionException(ex.Message, ex);
|
||||
}
|
||||
var res = SendCommand<string>(MtCommandType.MtRequest, commandParameters);
|
||||
|
||||
if (res == null)
|
||||
{
|
||||
throw new MtExecutionException(MtErrorCode.MtApiCustomError, "Response from MetaTrader is null");
|
||||
}
|
||||
|
||||
var response = JsonConvert.DeserializeObject<T>(res.Value);
|
||||
var response = JsonConvert.DeserializeObject<T>(res);
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
throw new MtExecutionException((MtErrorCode)response.ErrorCode, response.ErrorMessage);
|
||||
@@ -1845,46 +2375,40 @@ namespace MtApi
|
||||
{
|
||||
if (quote != null)
|
||||
{
|
||||
if (_isBacktestingMode)
|
||||
{
|
||||
QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
}
|
||||
else
|
||||
{
|
||||
QuoteUpdated.FireEventAsync(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
}
|
||||
QuoteUpdate?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote)));
|
||||
QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
}
|
||||
}
|
||||
|
||||
private void _client_ServerDisconnected(object sender, EventArgs e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Disconnected, "MtApi is disconnected");
|
||||
Disconnect(false);
|
||||
}
|
||||
|
||||
private void _client_ServerFailed(object sender, EventArgs e)
|
||||
{
|
||||
UpdateConnectionState(MtConnectionState.Failed, "Failed connection with MtApi");
|
||||
Disconnect(true);
|
||||
}
|
||||
|
||||
private void _client_QuoteRemoved(MTApiService.MtQuote quote)
|
||||
{
|
||||
QuoteRemoved.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
|
||||
QuoteRemoved?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote)));
|
||||
}
|
||||
|
||||
private void _client_QuoteAdded(MTApiService.MtQuote quote)
|
||||
{
|
||||
QuoteAdded.FireEventAsync(this, new MtQuoteEventArgs(quote.Convert()));
|
||||
QuoteAdded?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote)));
|
||||
}
|
||||
|
||||
private void _client_MtEventReceived(object sender, MtEventArgs e)
|
||||
private void _client_MtEventReceived(MtEvent e)
|
||||
{
|
||||
var eventType = (MtEventTypes) e.Event.EventType;
|
||||
var eventType = (MtEventTypes) e.EventType;
|
||||
|
||||
switch(eventType)
|
||||
{
|
||||
case MtEventTypes.LastTimeBar:
|
||||
{
|
||||
FireOnLastTimeBar(JsonConvert.DeserializeObject<MtTimeBar>(e.Event.Payload));
|
||||
FireOnLastTimeBar(JsonConvert.DeserializeObject<MtTimeBar>(e.Payload));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1894,7 +2418,7 @@ namespace MtApi
|
||||
|
||||
private void FireOnLastTimeBar(MtTimeBar timeBar)
|
||||
{
|
||||
OnLastTimeBar.FireEventAsync(this, new TimeBarArgs(timeBar));
|
||||
OnLastTimeBar?.Invoke(this, new TimeBarArgs(timeBar));
|
||||
}
|
||||
|
||||
private void BacktestingReady()
|
||||
@@ -1907,6 +2431,7 @@ namespace MtApi
|
||||
#region Events
|
||||
|
||||
public event MtApiQuoteHandler QuoteUpdated;
|
||||
public event EventHandler<MtQuoteEventArgs> QuoteUpdate;
|
||||
public event EventHandler<MtQuoteEventArgs> QuoteAdded;
|
||||
public event EventHandler<MtQuoteEventArgs> QuoteRemoved;
|
||||
public event EventHandler<MtConnectionEventArgs> ConnectionStateChanged;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+35
-9
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
enum MtCommandType
|
||||
{
|
||||
@@ -140,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,
|
||||
@@ -201,6 +196,37 @@ namespace MtApi
|
||||
SymbolsTotal = 200,
|
||||
SymbolName = 201,
|
||||
SymbolSelect = 202,
|
||||
SymbolInfoInteger = 203
|
||||
SymbolInfoInteger = 203,
|
||||
ChartId = 206,
|
||||
ChartRedraw = 207,
|
||||
|
||||
//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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
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)
|
||||
{
|
||||
@@ -12,5 +13,13 @@
|
||||
Bid = bid;
|
||||
Ask = ask;
|
||||
}
|
||||
|
||||
internal MtQuote(MTApiService.MtQuote quote)
|
||||
{
|
||||
Instrument = quote.Instrument;
|
||||
Bid = quote.Bid;
|
||||
Ask = quote.Ask;
|
||||
ExpertHandle = quote.ExpertHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
|
||||
Executable → Regular
+2
-2
@@ -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.32.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.32.0")]
|
||||
[assembly: AssemblyVersion("1.0.33.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.33.0")]
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
#region Event Methods
|
||||
public static void FireEvent(this EventHandler eventHandler, object sender)
|
||||
{
|
||||
eventHandler?.Invoke(sender, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void FireEvent<T>(this EventHandler<T> eventHandler, object sender, T e)
|
||||
where T : EventArgs
|
||||
{
|
||||
eventHandler?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
<Compile Include="Mt5Enums.cs" />
|
||||
<Compile Include="Mt5ConnectionEventArgs.cs" />
|
||||
<Compile Include="Mt5ConnectionState.cs" />
|
||||
<Compile Include="ExtensionMethods.cs" />
|
||||
<Compile Include="MqlTradeRequest.cs" />
|
||||
<Compile Include="MqlTradeResult.cs" />
|
||||
<Compile Include="Mt5QuoteEventArgs.cs" />
|
||||
|
||||
+163
-111
@@ -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,37 @@ namespace MtApi5
|
||||
///<summary>
|
||||
///Connection status of MetaTrader API.
|
||||
///</summary>
|
||||
public Mt5ConnectionState ConnectionState { get; private set; }
|
||||
public Mt5ConnectionState ConnectionState
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _connectionState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Handle of expert used to execute commands
|
||||
///</summary>
|
||||
public int ExecutorHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _executorHandle;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_executorHandle = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
@@ -1443,94 +1456,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 +1612,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 +1629,7 @@ namespace MtApi5
|
||||
}
|
||||
|
||||
|
||||
private void mClient_QuoteUpdated(MtQuote quote)
|
||||
private void _client_QuoteUpdated(MtQuote quote)
|
||||
{
|
||||
if (quote != null)
|
||||
{
|
||||
@@ -1581,28 +1637,24 @@ 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()));
|
||||
QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse()));
|
||||
}
|
||||
|
||||
private void mClient_QuoteAdded(MtQuote quote)
|
||||
private void _client_QuoteAdded(MtQuote quote)
|
||||
{
|
||||
QuoteAdded.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse()));
|
||||
QuoteAdded?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse()));
|
||||
}
|
||||
|
||||
private void OnConnected()
|
||||
|
||||
@@ -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.11.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.11.0")]
|
||||
[assembly: AssemblyVersion("1.0.11.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.11.1")]
|
||||
|
||||
+646
-225
File diff suppressed because it is too large
Load Diff
@@ -33,8 +33,11 @@ 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;
|
||||
_apiClient.QuoteUpdate += _apiClient_QuoteUpdate;
|
||||
_apiClient.QuoteAdded += apiClient_QuoteAdded;
|
||||
_apiClient.QuoteRemoved += apiClient_QuoteRemoved;
|
||||
_apiClient.ConnectionStateChanged += apiClient_ConnectionStateChanged;
|
||||
@@ -47,6 +50,8 @@ 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
|
||||
_timerTradeMonitor.AvailabilityOrdersChanged += _tradeMonitor_AvailabilityOrdersChanged;
|
||||
@@ -112,12 +117,18 @@ namespace TestApiClientUI
|
||||
|
||||
private void apiClient_QuoteRemoved(object sender, MtQuoteEventArgs e)
|
||||
{
|
||||
RunOnUiThread(() => RemoveQuote(e.Quote) );
|
||||
if (e.Quote != null)
|
||||
{
|
||||
RunOnUiThread(() => RemoveQuote(e.Quote));
|
||||
}
|
||||
}
|
||||
|
||||
private void apiClient_QuoteAdded(object sender, MtQuoteEventArgs e)
|
||||
{
|
||||
RunOnUiThread(() => AddNewQuote(e.Quote));
|
||||
if (e.Quote != null)
|
||||
{
|
||||
RunOnUiThread(() => AddNewQuote(e.Quote));
|
||||
}
|
||||
}
|
||||
|
||||
private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e)
|
||||
@@ -130,73 +141,53 @@ namespace TestApiClientUI
|
||||
|
||||
private void apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
|
||||
{
|
||||
Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}", symbol, bid, ask);
|
||||
Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}", symbol, bid, ask);
|
||||
}
|
||||
|
||||
private void _apiClient_QuoteUpdate(object sender, MtQuoteEventArgs e)
|
||||
{
|
||||
//if UI of quite is busy we are skipping this update
|
||||
if (_isUiQuoteUpdateReady)
|
||||
{
|
||||
RunOnUiThread(() => ChangeQuote(symbol, bid, ask));
|
||||
RunOnUiThread(() => ChangeQuote(e.Quote));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNewQuote(MtQuote quote)
|
||||
{
|
||||
if (quote == null)
|
||||
return;
|
||||
var key = quote.ExpertHandle.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(quote.Instrument) == false
|
||||
&& listViewQuotes.Items.ContainsKey(quote.Instrument) == false)
|
||||
if (listViewQuotes.Items.ContainsKey(key) == false)
|
||||
{
|
||||
var item = new ListViewItem(quote.Instrument) { Name = quote.Instrument };
|
||||
var item = new ListViewItem(quote.Instrument) { Name = key };
|
||||
item.SubItems.Add(quote.Bid.ToString(CultureInfo.CurrentCulture));
|
||||
item.SubItems.Add(quote.Ask.ToString(CultureInfo.CurrentCulture));
|
||||
item.SubItems.Add("1");
|
||||
item.SubItems.Add(key);
|
||||
listViewQuotes.Items.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = listViewQuotes.Items[quote.Instrument];
|
||||
int feedCount;
|
||||
int.TryParse(item.SubItems[3].Text, out feedCount);
|
||||
feedCount++;
|
||||
item.SubItems[3].Text = feedCount.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveQuote(MtQuote quote)
|
||||
{
|
||||
if (quote == null)
|
||||
return;
|
||||
var key = quote.ExpertHandle.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(quote.Instrument) == false
|
||||
&& listViewQuotes.Items.ContainsKey(quote.Instrument))
|
||||
if (listViewQuotes.Items.ContainsKey(key))
|
||||
{
|
||||
var item = listViewQuotes.Items[quote.Instrument];
|
||||
int feedCount;
|
||||
int.TryParse(item.SubItems[3].Text, out feedCount);
|
||||
feedCount--;
|
||||
if (feedCount <= 0)
|
||||
{
|
||||
listViewQuotes.Items.RemoveByKey(quote.Instrument);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SubItems[3].Text = feedCount.ToString();
|
||||
}
|
||||
listViewQuotes.Items.RemoveByKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeQuote(string symbol, double bid, double ask)
|
||||
private void ChangeQuote(MtQuote quote)
|
||||
{
|
||||
_isUiQuoteUpdateReady = false;
|
||||
|
||||
if (string.IsNullOrEmpty(symbol) == false)
|
||||
var key = quote.ExpertHandle.ToString();
|
||||
|
||||
if (listViewQuotes.Items.ContainsKey(key))
|
||||
{
|
||||
if (listViewQuotes.Items.ContainsKey(symbol))
|
||||
{
|
||||
var item = listViewQuotes.Items[symbol];
|
||||
item.SubItems[1].Text = bid.ToString(CultureInfo.CurrentCulture);
|
||||
item.SubItems[2].Text = ask.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
var item = listViewQuotes.Items[key];
|
||||
item.SubItems[1].Text = quote.Bid.ToString(CultureInfo.CurrentCulture);
|
||||
item.SubItems[2].Text = quote.Ask.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
_isUiQuoteUpdateReady = true;
|
||||
@@ -256,6 +247,12 @@ namespace TestApiClientUI
|
||||
textBoxOrderSymbol.Text = listViewQuotes.SelectedItems[0].Text;
|
||||
txtMarketInfoSymbol.Text = listViewQuotes.SelectedItems[0].Text;
|
||||
textBoxSelectedSymbol.Text = listViewQuotes.SelectedItems[0].Text;
|
||||
textBoxAccountInfoSymbol.Text = listViewQuotes.SelectedItems[0].Text;
|
||||
|
||||
if (checkBox2.Checked)
|
||||
{
|
||||
_apiClient.ExecutorHandle = int.Parse(listViewQuotes.SelectedItems[0].SubItems[3].Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,206 +523,6 @@ namespace TestApiClientUI
|
||||
});
|
||||
}
|
||||
|
||||
private void button3_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (comboBoxStatusCommand.SelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
var result = _apiClient.GetLastError();
|
||||
PrintLog($"GetLastError result: {result}");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
var result = _apiClient.IsConnected();
|
||||
PrintLog($"IsConnected result: {result}");
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
var result = _apiClient.IsDemo();
|
||||
PrintLog($"IsDemo result: {result}");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
var result = _apiClient.IsDllsAllowed();
|
||||
PrintLog($"IsDllsAllowed result: {result}");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
var result = _apiClient.IsExpertEnabled();
|
||||
PrintLog($"IsExpertEnabled result: {result}");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
var result = _apiClient.IsLibrariesAllowed();
|
||||
PrintLog($"IsLibrariesAllowed result: {result}");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
var result = _apiClient.IsOptimization();
|
||||
PrintLog($"IsOptimization result: {result}");
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
var result = _apiClient.IsStopped();
|
||||
PrintLog($"IsStopped result: {result}");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
var result = _apiClient.IsTesting();
|
||||
PrintLog($"IsTesting result: {result}");
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
{
|
||||
var result = _apiClient.IsTradeAllowed();
|
||||
PrintLog($"IsTradeAllowed result: {result}");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
var result = _apiClient.IsTradeContextBusy();
|
||||
PrintLog($"IsTradeContextBusy result: {result}");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
var result = _apiClient.IsVisualMode();
|
||||
PrintLog($"IsVisualMode result: {result}");
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
{
|
||||
var result = _apiClient.UninitializeReason();
|
||||
PrintLog($"UninitializeReason result: {result}");
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
{
|
||||
int errorCode;
|
||||
int.TryParse(textBoxErrorCode.Text, out errorCode);
|
||||
var result = _apiClient.ErrorDescription(errorCode);
|
||||
PrintLog($"ErrorDescription result: {result}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void button4_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (listBoxAccountInfo.SelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
var result = _apiClient.AccountBalance();
|
||||
PrintLog($"AccountBalance result: {result}");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
var result = _apiClient.AccountCredit();
|
||||
PrintLog($"AccountCredit result: {result}");
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
var result = _apiClient.AccountCompany();
|
||||
PrintLog($"AccountCompany result: {result}");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
var result = _apiClient.AccountCurrency();
|
||||
PrintLog($"AccountCurrency result: {result}");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
var result = _apiClient.AccountEquity();
|
||||
PrintLog($"AccountEquity result: {result}");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
var result = _apiClient.AccountFreeMargin();
|
||||
PrintLog($"AccountFreeMargin result: {result}");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
var result = _apiClient.AccountFreeMarginCheck(textBoxAccountInfoSymbol.Text, (TradeOperation)comboBoxAccountInfoCmd.SelectedIndex, int.Parse(textBoxAccountInfoVolume.Text));
|
||||
PrintLog($"AccountFreeMarginCheck result: {result}");
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
var result = _apiClient.AccountFreeMarginMode();
|
||||
PrintLog($"AccountFreeMarginMode result: {result}");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
var result = _apiClient.AccountLeverage();
|
||||
PrintLog($"AccountLeverage result: {result}");
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
{
|
||||
var result = _apiClient.AccountMargin();
|
||||
PrintLog($"AccountMargin result: {result}");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
var result = _apiClient.AccountName();
|
||||
PrintLog($"AccountName result: {result}");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
var result = _apiClient.AccountNumber();
|
||||
PrintLog($"AccountNumber result: {result}");
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
{
|
||||
var result = _apiClient.AccountProfit();
|
||||
PrintLog($"AccountProfit result: {result}");
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
{
|
||||
var result = _apiClient.AccountServer();
|
||||
PrintLog($"AccountServer result: {result}");
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
{
|
||||
var result = _apiClient.AccountStopoutLevel();
|
||||
PrintLog($"AccountStopoutLevel result: {result}");
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
{
|
||||
var result = _apiClient.AccountStopoutMode();
|
||||
PrintLog($"AccountStopoutMode result: {result}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//MarketInfo
|
||||
private async void button5_Click(object sender, EventArgs e)
|
||||
{
|
||||
@@ -753,13 +550,13 @@ namespace TestApiClientUI
|
||||
|
||||
Console.WriteLine($"Finished time: {DateTime.Now}");
|
||||
|
||||
using (var file = new System.IO.StreamWriter($@"{System.IO.Path.GetTempPath()}\MtApi\test.txt"))
|
||||
{
|
||||
foreach (var value in openPriceList)
|
||||
{
|
||||
file.WriteLine(value);
|
||||
}
|
||||
}
|
||||
//using (var file = new System.IO.StreamWriter($@"{System.IO.Path.GetTempPath()}\MtApi\test.txt"))
|
||||
//{
|
||||
// foreach (var value in openPriceList)
|
||||
// {
|
||||
// file.WriteLine(value);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
private void button7_Click(object sender, EventArgs e)
|
||||
@@ -832,9 +629,9 @@ namespace TestApiClientUI
|
||||
listBoxEventLog.Items.Clear();
|
||||
}
|
||||
|
||||
private async Task<TResult> Execute<TResult>(Func<TResult> func)
|
||||
private Task<TResult> Execute<TResult>(Func<TResult> func)
|
||||
{
|
||||
return await Task.Factory.StartNew(() =>
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
var result = default(TResult);
|
||||
try
|
||||
@@ -854,6 +651,25 @@ namespace TestApiClientUI
|
||||
});
|
||||
}
|
||||
|
||||
private Task Execute(Action action)
|
||||
{
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (MtConnectionException ex)
|
||||
{
|
||||
PrintLog("MtExecutionException: " + ex.Message);
|
||||
}
|
||||
catch (MtExecutionException ex)
|
||||
{
|
||||
PrintLog("MtExecutionException: " + ex.Message + "; ErrorCode = " + ex.ErrorCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//OrderSend
|
||||
private async void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
@@ -1286,5 +1102,305 @@ namespace TestApiClientUI
|
||||
var result = await Execute(() => _apiClient.TerminalInfoDouble(propId));
|
||||
PrintLog($"TerminalInfoDouble: result = {result}");
|
||||
}
|
||||
|
||||
private void checkBox2_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
var checkbox = sender as CheckBox;
|
||||
if (checkbox == null)
|
||||
return;
|
||||
|
||||
int expertHandle = 0;
|
||||
if (checkbox.Checked)
|
||||
{
|
||||
if (listViewQuotes.SelectedItems.Count > 0)
|
||||
{
|
||||
expertHandle = int.Parse(listViewQuotes.SelectedItems[0].SubItems[3].Text);
|
||||
}
|
||||
}
|
||||
|
||||
_apiClient.ExecutorHandle = expertHandle;
|
||||
}
|
||||
|
||||
//GetLastError
|
||||
private async void button40_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.GetLastError);
|
||||
PrintLog($"GetLastError: result = {result}");
|
||||
RunOnUiThread(() => { textBoxErrorCode.Text = result.ToString(); });
|
||||
}
|
||||
|
||||
//ErrorDescription
|
||||
private async void button39_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textBoxErrorCode.Text))
|
||||
{
|
||||
MessageBox.Show(@"Error code is not defined!");
|
||||
textBoxErrorCode.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
int errorCode;
|
||||
if (int.TryParse(textBoxErrorCode.Text, out errorCode) == false)
|
||||
{
|
||||
MessageBox.Show(@"Failed to parse error code!");
|
||||
textBoxErrorCode.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await Execute(() => _apiClient.ErrorDescription(errorCode));
|
||||
PrintLog($"ErrorDescription: code = {errorCode}, description = {result}");
|
||||
}
|
||||
|
||||
//IsConnected
|
||||
private async void button41_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsConnected);
|
||||
PrintLog($"IsConnected: result = {result}");
|
||||
}
|
||||
|
||||
//IsDemo
|
||||
private async void button42_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsDemo);
|
||||
PrintLog($"IsDemo: result = {result}");
|
||||
}
|
||||
|
||||
//IsDllsAllowed
|
||||
private async void button43_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsDllsAllowed);
|
||||
PrintLog($"IsDllsAllowed: result = {result}");
|
||||
}
|
||||
|
||||
//IsExpertEnabled
|
||||
private async void button44_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsExpertEnabled);
|
||||
PrintLog($"IsExpertEnabled: result = {result}");
|
||||
}
|
||||
|
||||
//IsLibrariesAllowed
|
||||
private async void button45_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsLibrariesAllowed);
|
||||
PrintLog($"IsLibrariesAllowed: result = {result}");
|
||||
}
|
||||
|
||||
//IsOptimization
|
||||
private async void button46_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsOptimization);
|
||||
PrintLog($"IsOptimization: result = {result}");
|
||||
}
|
||||
|
||||
//IsStopped
|
||||
private async void button47_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsStopped);
|
||||
PrintLog($"IsStopped: result = {result}");
|
||||
}
|
||||
|
||||
//IsTesting
|
||||
private async void button48_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsTesting);
|
||||
PrintLog($"IsTesting: result = {result}");
|
||||
}
|
||||
|
||||
//IsTradeAllowed
|
||||
private async void button49_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsTradeAllowed);
|
||||
PrintLog($"IsTradeAllowed: result = {result}");
|
||||
}
|
||||
|
||||
//IsTradeContextBusy
|
||||
private async void button50_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsTradeContextBusy);
|
||||
PrintLog($"IsTradeContextBusy: result = {result}");
|
||||
}
|
||||
|
||||
//IsVisualMode
|
||||
private async void button51_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.IsVisualMode);
|
||||
PrintLog($"IsVisualMode: result = {result}");
|
||||
}
|
||||
|
||||
//UninitializeReason
|
||||
private async void button52_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.UninitializeReason);
|
||||
PrintLog($"UninitializeReason: result = {result}");
|
||||
}
|
||||
|
||||
//AccountBalance
|
||||
private async void button3_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountBalance);
|
||||
PrintLog($"AccountBalance result: {result}");
|
||||
}
|
||||
|
||||
//AccountCredit
|
||||
private async void button53_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountCredit);
|
||||
PrintLog($"AccountCredit result: {result}");
|
||||
}
|
||||
|
||||
//AccountCompany
|
||||
private async void button54_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountCompany);
|
||||
PrintLog($"AccountCompany result: {result}");
|
||||
}
|
||||
|
||||
//AccountCurrency
|
||||
private async void button55_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountCurrency);
|
||||
PrintLog($"AccountCurrency result: {result}");
|
||||
}
|
||||
|
||||
//AccountEquity
|
||||
private async void button56_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountEquity);
|
||||
PrintLog($"AccountEquity result: {result}");
|
||||
}
|
||||
|
||||
//AccountFreeMargin
|
||||
private async void button57_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountFreeMargin);
|
||||
PrintLog($"AccountFreeMargin result: {result}");
|
||||
}
|
||||
|
||||
//AccountFreeMarginCheck
|
||||
private async void button58_Click(object sender, EventArgs e)
|
||||
{
|
||||
var symbol = textBoxAccountInfoSymbol.Text;
|
||||
if (string.IsNullOrEmpty(symbol))
|
||||
{
|
||||
MessageBox.Show(@"Symbol is not defined!");
|
||||
textBoxAccountInfoSymbol.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
double volume;
|
||||
if (double.TryParse(textBoxAccountInfoVolume.Text, out volume) == false)
|
||||
{
|
||||
MessageBox.Show(@"Failed to parse volume value!");
|
||||
textBoxAccountInfoVolume.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
TradeOperation cmd;
|
||||
Enum.TryParse(comboBoxAccountInfoCmd.Text, out cmd);
|
||||
|
||||
var result = await Execute(() => _apiClient.AccountFreeMarginCheck(symbol, cmd, volume));
|
||||
PrintLog($"AccountFreeMarginCheck result: {result}");
|
||||
}
|
||||
|
||||
//AccountFreeMarginMode
|
||||
private async void button59_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountFreeMarginMode);
|
||||
PrintLog($"AccountFreeMarginMode result: {result}");
|
||||
}
|
||||
|
||||
//AccountLeverage
|
||||
private async void button60_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountLeverage);
|
||||
PrintLog($"AccountLeverage result: {result}");
|
||||
}
|
||||
|
||||
//AccountMargin
|
||||
private async void button61_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountMargin);
|
||||
PrintLog($"AccountMargin result: {result}");
|
||||
}
|
||||
|
||||
//AccountName
|
||||
private async void button62_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountName);
|
||||
PrintLog($"AccountName result: {result}");
|
||||
}
|
||||
|
||||
//AccountNumber
|
||||
private async void button63_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountNumber);
|
||||
PrintLog($"AccountNumber result: {result}");
|
||||
}
|
||||
|
||||
//AccountProfit
|
||||
private async void button64_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountProfit);
|
||||
PrintLog($"AccountProfit result: {result}");
|
||||
}
|
||||
|
||||
//AccountServer
|
||||
private async void button65_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountServer);
|
||||
PrintLog($"AccountServer result: {result}");
|
||||
}
|
||||
|
||||
//AccountStopoutLevel
|
||||
private async void button66_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountStopoutLevel);
|
||||
PrintLog($"AccountStopoutLevel result: {result}");
|
||||
}
|
||||
|
||||
//AccountStopoutMode
|
||||
private async void button67_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.AccountStopoutMode);
|
||||
PrintLog($"AccountStopoutMode result: {result}");
|
||||
}
|
||||
|
||||
//CharID
|
||||
private async void button37_Click(object sender, EventArgs e)
|
||||
{
|
||||
var result = await Execute(_apiClient.ChartId);
|
||||
PrintLog($"CharID: result = {result}");
|
||||
RunOnUiThread(() => textBoxChartId.Text = result.ToString());
|
||||
}
|
||||
|
||||
//ChartRedraw
|
||||
private async void button38_Click(object sender, EventArgs e)
|
||||
{
|
||||
await Execute(() => _apiClient.ChartRedraw());
|
||||
PrintLog($"ChartRedraw: called.");
|
||||
}
|
||||
|
||||
//ObjectCreate
|
||||
private async void button4_Click(object sender, EventArgs e)
|
||||
{
|
||||
const long chartId = 0;
|
||||
const string objectName = "label_object";
|
||||
EnumObject objectType;
|
||||
Enum.TryParse(comboBox11.Text, out objectType);
|
||||
|
||||
var result = await Execute(() => _apiClient.ObjectCreate(chartId, objectName, objectType, 0, null, 0));
|
||||
PrintLog($"ObjectCreate result: {result}");
|
||||
}
|
||||
|
||||
//ObjectName
|
||||
private async void button68_Click(object sender, EventArgs e)
|
||||
{
|
||||
const long chartId = 0;
|
||||
const int objectIndex = 0;
|
||||
|
||||
var result = await Execute(() => _apiClient.ObjectName(chartId, objectIndex));
|
||||
PrintLog($"ObjectName result: {result}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.17929
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
|
||||
+13
-12
@@ -1,7 +1,7 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.17929
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
@@ -11,6 +11,7 @@
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
Imports System
|
||||
|
||||
Namespace My.Resources
|
||||
|
||||
@@ -21,20 +22,20 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' A strongly-typed resource class, for looking up localized strings, etc.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
Friend Module Resources
|
||||
|
||||
|
||||
Private resourceMan As Global.System.Resources.ResourceManager
|
||||
|
||||
|
||||
Private resourceCulture As Global.System.Globalization.CultureInfo
|
||||
|
||||
|
||||
'''<summary>
|
||||
''' Returns the cached ResourceManager instance used by this class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||
Get
|
||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||
@@ -44,17 +45,17 @@ Namespace My.Resources
|
||||
Return resourceMan
|
||||
End Get
|
||||
End Property
|
||||
|
||||
|
||||
'''<summary>
|
||||
''' Overrides the current thread's CurrentUICulture property for all
|
||||
''' resource lookups using this strongly typed resource class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
||||
Get
|
||||
Return resourceCulture
|
||||
End Get
|
||||
Set(ByVal value As Global.System.Globalization.CultureInfo)
|
||||
Set
|
||||
resourceCulture = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
+26
-26
@@ -1,7 +1,7 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.17929
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
@@ -13,42 +13,42 @@ Option Explicit On
|
||||
|
||||
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
|
||||
|
||||
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
|
||||
|
||||
#Region "My.Settings Auto-Save Functionality"
|
||||
#If _MyType = "WindowsForms" Then
|
||||
Private Shared addedHandler As Boolean
|
||||
Private Shared addedHandler As Boolean
|
||||
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
#End If
|
||||
#End Region
|
||||
|
||||
|
||||
Public Shared ReadOnly Property [Default]() As MySettings
|
||||
Get
|
||||
|
||||
|
||||
#If _MyType = "WindowsForms" Then
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
#End If
|
||||
Return defaultInstance
|
||||
End Get
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
<AssemblyName>TestMtApi</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>WindowsForms</MyType>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
@@ -40,6 +41,7 @@
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DocumentationFile>TestMtApi.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -50,6 +52,7 @@
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DocumentationFile>TestMtApi.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionExplicit>On</OptionExplicit>
|
||||
@@ -67,7 +70,6 @@
|
||||
<ApplicationManifest>My Project\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="MtApi, Version=1.0.7.0, Culture=neutral, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
@@ -126,6 +128,7 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="My Project\app.manifest" />
|
||||
<None Include="My Project\Application.myapp">
|
||||
<Generator>MyApplicationCodeGenerator</Generator>
|
||||
@@ -159,6 +162,12 @@
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\MtApi\MtApi.csproj">
|
||||
<Project>{7a76c388-a8fb-4949-8170-24d4742e934e}</Project>
|
||||
<Name>MtApi</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.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.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user