Compare commits

..

36 Commits

Author SHA1 Message Date
DW 5b76bf0547 Merge master fixed conflict. 2017-01-05 21:36:55 +02:00
DW 1c269f7339 Issue #32: Added function ObjectName into test client 2017-01-05 02:14:13 +02:00
DW 21fb790d8c Issue #32: Fixed small bugs in EA MtApi.mq4 2017-01-05 01:02:55 +02:00
DW 7c9a0aa8cc Issue #32: Implement object functions in EA MtApi.mq4 2017-01-03 21:29:41 +02:00
DW 18ddf3df1c Issue #32: Added c# implementations of most object functions in MtApi client 2016-12-30 17:16:48 +02:00
DW a8832b79ba Issue #32: Added function ObjectCreate in MtApi (MT4) 2016-12-27 17:41:11 +02:00
vdemydiuk 39146d68b2 Starting work on Object Functions 2016-12-26 17:49:06 +02:00
DW 5b03f01e9b Clear unnecessary witespaces in MtApi.mq4 2016-12-21 14:26:37 +02:00
vdemydiuk 8f5a1c8222 Refactored MtApi.mq4 2016-12-21 12:01:15 +02:00
vdemydiuk f5f13a13cc Issue #32: Added function ChartRedraw 2016-12-12 17:29:52 +02:00
vdemydiuk 9ef970cf1e Refactoring TestApiUiClient (Account Information tab) 2016-11-30 10:57:33 +02:00
vdemydiuk b5878ccb62 Refactoring TestApiUiClient (Check Status tab) 2016-11-29 19:08:53 +02:00
DW 4a7bb6f2cb MtApi (MT5) ver. 1.0.11.1 HotFix 2016-11-29 10:20:55 +02:00
vdemydiuk 5abfeebc90 Issue #32: Added function ChartId 2016-11-28 16:03:40 +02:00
vdemydiuk e333164552 Issue #32: Added ExecutorHandle property to determine which expert will be used for execution command 2016-11-28 14:45:33 +02:00
vdemydiuk 9a6968f618 Refactoring MtApi 2016-11-26 19:27:09 +02:00
DW d63a53b8a9 MtApi (MT4) version 1.0.32.1 (HotFix) 2016-11-25 16:06:11 +02:00
DW 7e821fcade Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-25 15:50:56 +02:00
DW 88e2d22abe Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-23 13:09:47 +02:00
DW fcfd741e5b Issue #37: Used ConcurrencyMode.Multiple for server and client side to avoid deadlocks and freezes of MtApiService 2016-11-23 10:51:50 +02:00
DW c722511c03 Refactored MtApiService (ver. 1.0.24): Added ExpertHandle to MtQuote and MtEvent. Added event QuoteUpdate to MtApiClient. 2016-11-18 15:47:55 +02:00
DW 39599436ab Started version 1.0.33 of MtApi MT4 2016-11-18 12:13:00 +02:00
vdemydiuk 8e3f206c76 Issue #35: Implemented function TerminalInfoDouble in MtApi MT4 2016-11-15 11:06:43 +02:00
vdemydiuk 8e5dcbd2ee Issue #31: Implemented function TerminalInfoInteger in MtApi MT4 2016-11-15 10:02:30 +02:00
vdemydiuk 563a5a895b Issue #31: Implemented function SymbolInfoTick in MtApi MT4 2016-11-14 16:31:01 +02:00
vdemydiuk 32f6018858 Issue #31: Implemented function SymbolInfoDouble in MtApi MT4 2016-11-14 14:04:31 +02:00
vdemydiuk c64417474a Issue #33: Implemented function SeriesInfoInteger (MtApi MT4) 2016-11-13 23:24:38 +02:00
vdemydiuk 6d4b5f4c00 Issue #27: Created bootstrapper project for MtApi MT4 with vcredist package 2016-11-11 17:56:17 +02:00
vdemydiuk 601c95369e Recovered MtApi.ex4 2016-11-11 17:54:33 +02:00
vdemydiuk 0542dd3e71 Started MtApi (MT4) version 1.0.32 2016-11-11 17:53:43 +02:00
vdemydiuk 15068ca99c Issue #30: Added MtApi5 Bootstrapper project to merge installer and vcredist packages 2016-11-08 17:38:51 +02:00
vdemydiuk c3617549f8 Updated version of MtApiService to 1.0.23 2016-11-08 14:16:09 +02:00
vdemydiuk aa91196e31 Updated license text in MtApi5 installer 2016-11-07 13:45:18 +02:00
vdemydiuk ba7b50e241 Issue #29: Added process Id into name of log file 2016-11-07 13:05:36 +02:00
vdemydiuk ddcd6fa2d5 Issue #25: Implemented function CopyTicks. Used json request 2016-11-05 00:52:52 +02:00
vdemydiuk ad55740bc7 Started MtApi (MT5) version 1.0.11 2016-11-03 13:07:48 +02:00
123 changed files with 5953 additions and 5063 deletions
Executable
BIN
View File
Binary file not shown.
+2 -3
View File
@@ -1,8 +1,7 @@
namespace MTApiService
{
public interface ICommandManager
internal interface ICommandManager
{
void EnqueueCommandTask(MtCommandTask task);
MtCommandTask DequeueCommandTask();
MtCommandTask SendCommand(MtCommand task);
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MTApiService
{
internal interface ITaskExecutor
{
void Execute(MtCommandTask task);
int Handle { get; }
}
}
+2 -5
View File
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using log4net;
using log4net.Appender;
using log4net.Core;
@@ -24,7 +25,7 @@ namespace MTApiService
};
patternLayout.ActivateOptions();
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}.{LogFileNameExtension}";
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
var roller = new RollingFileAppender
{
@@ -40,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
+3 -2
View File
@@ -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>
+53 -9
View File
@@ -4,13 +4,13 @@ using log4net;
namespace MTApiService
{
public class MtServerInstance
public class MtAdapter
{
#region Fields
private const string LogProfileName = "MtApiService";
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
private static readonly MtServerInstance Instance = new MtServerInstance();
private static readonly ILog Log = LogManager.GetLogger(typeof(MtAdapter));
private static readonly MtAdapter Instance = new MtAdapter();
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
@@ -18,16 +18,16 @@ namespace MTApiService
#region Init Instance
private MtServerInstance()
private MtAdapter()
{
LogConfigurator.Setup(LogProfileName);
}
static MtServerInstance()
static MtAdapter()
{
}
public static MtServerInstance GetInstance()
public static MtAdapter GetInstance()
{
return Instance;
}
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
}
}
+9 -8
View File
@@ -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
View File
@@ -7,30 +7,17 @@ namespace MTApiService
public class MtEvent
{
[DataMember]
public int EventType { get; private set; }
public int EventType { get; internal set; }
[DataMember]
public string Payload { get; private set; }
public string Payload { get; internal set; }
public MtEvent(int eventType, string payload)
{
EventType = eventType;
Payload = payload;
}
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return "MtEvent = " + EventType + ", Payload = " + Payload;
return $"EventType = {EventType}; Payload = {Payload}; ExpertHandle = {ExpertHandle}";
}
}
public class MtEventArgs: EventArgs
{
public MtEventArgs(MtEvent e)
{
Event = e;
}
public MtEvent Event { get; private set; }
}
}
+55 -111
View File
@@ -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
View File
@@ -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
}
}
-29
View File
@@ -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;
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; internal set; }
[DataMember]
public double Bid { get; internal set; }
[DataMember]
public double Ask { get; internal set; }
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return $"Instrument = {Instrument}; Bid = {Bid}; Ask = {Ask}; ExpertHandle = {ExpertHandle}";
}
}
}
+24 -1
View File
@@ -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]
+18 -9
View File
@@ -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.");
}
+7 -7
View File
@@ -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.");
}
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.22.0")]
[assembly: AssemblyFileVersion("1.0.22.0")]
[assembly: AssemblyVersion("1.0.25.0")]
[assembly: AssemblyFileVersion("1.0.25.0")]
+179 -199
View File
@@ -4,7 +4,8 @@
#include "MT4Handler.h"
#include "Windows.h"
#include < vcclr.h >
#include <vcclr.h>
#include <functional>
using namespace System;
using namespace MTApiService;
@@ -17,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, &paramIndex, 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, &paramIndex, 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, &paramIndex, 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, &paramIndex, res]() {
*res = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (__int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
// --- named parameters
_DLLAPI bool _stdcall containsNamedValue(int expertHandle, wchar_t* paramName)
{
wchar_t err[1000];
return Execute<bool>([&expertHandle, paramName]() {
return MtAdapter::GetInstance()->ContainsNamedParameter(expertHandle, gcnew String(paramName));
}, err, false);
}
_DLLAPI bool _stdcall getNamedIntValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (int)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedDoubleValue(int expertHandle, wchar_t* paramName, double* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (double)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedStringValue(int expertHandle, wchar_t* paramName, wchar_t* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
convertSystemString(res, (String^)obj);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedBooleanValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (bool)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedLongValue(int expertHandle, wchar_t* paramName, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
if (obj != nullptr)
*res = (__int64)obj;
return true;
}, err, false);
}
-19
View File
@@ -1,19 +0,0 @@
LIBRARY MTConnector
EXPORTS initExpert
deinitExpert
updateQuote
sendEvent
sendIntResponse
sendBooleanResponse
sendDoubleResponse
sendStringResponse
sendVoidResponse
sendDoubleArrayResponse
sendIntArrayResponse
sendLongResponse
getCommandType
getIntValue
getDoubleValue
getStringValue
getBooleanValue
-5
View File
@@ -96,7 +96,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -109,7 +108,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -121,7 +119,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -133,7 +130,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -154,7 +150,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="MTConnector.def" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
-3
View File
@@ -44,9 +44,6 @@
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="MTConnector.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
+37 -1
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApiClientUI", "TestClients\TestApiClientUI\TestApiClientUI.csproj", "{663CC515-EAAE-47D4-8933-5008C2DA1160}"
EndProject
@@ -37,6 +37,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MtApiSetupActions", "MtApiS
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestClients", "TestClients", "{B91FF338-E05D-4EF1-948B-A2376DB37ECA}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApi5Bootstrapper", "MtApi5Bootstrapper\MtApi5Bootstrapper.wixproj", "{1497E285-C228-490B-9638-565E118548FB}"
ProjectSection(ProjectDependencies) = postProject
{A9ED070F-AB4D-4380-9DDE-5D931AC71333} = {A9ED070F-AB4D-4380-9DDE-5D931AC71333}
EndProjectSection
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApiBootstrapper", "MtApiBootstrapper\MtApiBootstrapper.wixproj", "{8E63046B-56E5-4623-8808-558AD72A8F2B}"
ProjectSection(ProjectDependencies) = postProject
{78B94552-DB17-40EC-B7C6-23D32DB85DC1} = {78B94552-DB17-40EC-B7C6-23D32DB85DC1}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -196,6 +206,32 @@ Global
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x64.ActiveCfg = Release|x86
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.ActiveCfg = Release|x86
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.Build.0 = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Any CPU.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.Build.0 = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.ActiveCfg = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Build.0 = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Deploy.0 = Debug|x64
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.ActiveCfg = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.Build.0 = Debug|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Any CPU.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.Build.0 = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|x64.ActiveCfg = Release|x64
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.ActiveCfg = Release|x86
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.Build.0 = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Any CPU.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.Build.0 = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x64.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.ActiveCfg = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.Build.0 = Debug|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Any CPU.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.Build.0 = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x64.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.ActiveCfg = Release|x86
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi
{
enum EnumColorFormat
{
COLOR_FORMAT_XRGB_NOALPHA = 0, //The component of the alpha channel is ignored
COLOR_FORMAT_ARGB_RAW = 1, //Color components are not handled by the terminal (must be correctly set by the user)
COLOR_FORMAT_ARGB_NORMALIZE = 2 //Color components are handled by the terminal
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
public enum EnumObject
{
OBJ_VLINE = 0, //Vertical Line
OBJ_HLINE = 1, //Horizontal Line
OBJ_TREND = 2, //Trend Line
BJ_TRENDBYANGLE = 3, //Trend Line By Angle
OBJ_CYCLES = 20, //Cycle Lines
OBJ_CHANNEL = 5, //Equidistant Channel
OBJ_STDDEVCHANNEL = 6, //Standard Deviation Channel
OBJ_REGRESSION = 4, //Linear Regression Channel
OBJ_PITCHFORK = 19, //Andrews’ Pitchfork
OBJ_GANNLINE = 7, //Gann Line
OBJ_GANNFAN = 8, //Gann Fan
OBJ_GANNGRID = 9, //Gann Grid
OBJ_FIBO = 10, //Fibonacci Retracement
OBJ_FIBOTIMES = 11, //Fibonacci Time Zones
OBJ_FIBOFAN = 12, //Fibonacci Fan
OBJ_FIBOARC = 13, //Fibonacci Arcs
OBJ_FIBOCHANNEL = 15, //Fibonacci Channel
OBJ_EXPANSION = 14, //Fibonacci Expansion
OBJ_RECTANGLE = 16, //Rectangle
OBJ_TRIANGLE = 17, //Triangle
OBJ_ELLIPSE = 18, //Ellipse
OBJ_ARROW_THUMB_UP = 29, //Thumbs Up
OBJ_ARROW_THUMB_DOWN = 30, //Thumbs Down
OBJ_ARROW_UP = 31, //Arrow Up
OBJ_ARROW_DOWN = 32, //Arrow Down
OBJ_ARROW_STOP = 33, //Stop Sign
OBJ_ARROW_CHECK = 34, //Check Sign
OBJ_ARROW_LEFT_PRICE = 35, //Left Price Label
OBJ_ARROW_RIGHT_PRICE = 36, //Right Price Label
OBJ_ARROW_BUY = 37, //Buy Sign
OBJ_ARROW_SELL = 38, //Sell Sign
OBJ_ARROW = 22, //Arrow
OBJ_TEXT = 21, //Text
OBJ_LABEL = 23, //Label
OBJ_BUTTON = 25, //Button
OBJ_BITMAP = 26, //Bitmap
OBJ_BITMAP_LABEL = 24, //Bitmap Label
OBJ_EDIT = 27, //Edit
OBJ_EVENT = 42, //The "Event" object corresponding to an event in the economic calendar
OBJ_RECTANGLE_LABEL = 28 //The "Rectangle label" object for creating and designing the custom graphical interface.
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi
{
public enum EnumObjectPropertyDouble
{
OBJPROP_PRICE = 20, // Price coordinate
OBJPROP_LEVELVALUE = 204, // Level value
OBJPROP_SCALE = 12, // Scale (properties of Gann objects, Fibonacci Arcs and Ellipse)
OBJPROP_ANGLE = 13, // Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE
OBJPROP_DEVIATION = 16, // Deviation for the Standard Deviation Channel
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace MtApi
{
public enum EnumObjectPropertyInteger
{
OBJPROP_COLOR = 6,
OBJPROP_STYLE = 7,
OBJPROP_WIDTH = 8,
OBJPROP_BACK = 9,
OBJPROP_ZORDER = 207,
OBJPROP_HIDDEN = 208,
OBJPROP_SELECTED = 17,
OBJPROP_READONLY = 1028,
OBJPROP_TYPE = 18,
OBJPROP_TIME = 19,
OBJPROP_SELECTABLE = 1000,
OBJPROP_CREATETIME = 998,
OBJPROP_LEVELS = 200,
OBJPROP_LEVELCOLOR = 201,
OBJPROP_LEVELSTYLE = 202,
OBJPROP_LEVELWIDTH = 203,
OBJPROP_ALIGN = 1036,
OBJPROP_FONTSIZE = 100,
OBJPROP_RAY_RIGHT = 1004,
OBJPROP_ELLIPSE = 11,
OBJPROP_ARROWCODE = 14,
OBJPROP_TIMEFRAMES = 15,
OBJPROP_ANCHOR = 1011,
OBJPROP_XDISTANCE = 102,
OBJPROP_YDISTANCE = 103,
OBJPROP_STATE = 1018,
OBJPROP_XSIZE = 1019,
OBJPROP_YSIZE = 1020,
OBJPROP_XOFFSET = 1033,
OBJPROP_YOFFSET = 1034,
OBJPROP_BGCOLOR = 1025,
OBJPROP_CORNER = 101,
OBJPROP_BORDER_TYPE = 1029,
OBJPROP_BORDER_COLOR = 1035
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace MtApi
{
public enum EnumObjectPropertyString
{
OBJPROP_NAME = 1037,
OBJPROP_TEXT = 999,
OBJPROP_TOOLTIP = 206,
OBJPROP_LEVELTEXT = 205,
OBJPROP_FONT = 1001,
OBJPROP_BMPFILE = 1017,
OBJPROP_SYMBOL = 1021
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace MtApi
{
public enum EnumSeriesInfoInteger
{
SERIES_BARS_COUNT = 0,
SERIES_FIRSTDATE = 1,
SERIES_LASTBAR_DATE = 5,
SERIES_SERVER_FIRSTDATE = 2
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/marketinfoconstants#enum_symbol_info_double
public enum EnumSymbolInfoDouble
{
SYMBOL_BID = 1, // Bid - best sell offer
SYMBOL_BIDHIGH = 2, // Not supported
SYMBOL_BIDLOW = 3, // Not supported
SYMBOL_ASK = 4, // Ask - best buy offer
SYMBOL_ASKHIGH = 5, // Not supported
SYMBOL_ASKLOW = 6, // Not supported
SYMBOL_LAST = 7, // Not supported
SYMBOL_LASTHIGH = 8, // Not supported
SYMBOL_LASTLOW = 9, // Not supported
SYMBOL_POINT = 16, // Symbol point value
SYMBOL_TRADE_TICK_VALUE = 26, // Value of SYMBOL_TRADE_TICK_VALUE_PROFIT
SYMBOL_TRADE_TICK_VALUE_PROFIT = 53, // Not supported
SYMBOL_TRADE_TICK_VALUE_LOSS = 54, // Not supported
SYMBOL_TRADE_TICK_SIZE = 27, // Minimal price change
SYMBOL_TRADE_CONTRACT_SIZE = 28, // Trade contract size
SYMBOL_VOLUME_MIN = 34, // Minimal volume for a deal
SYMBOL_VOLUME_MAX = 35, // Maximal volume for a deal
SYMBOL_VOLUME_STEP = 36, // Minimal volume change step for deal execution
SYMBOL_VOLUME_LIMIT = 55, // Not supported
SYMBOL_SWAP_LONG = 38, // Buy order swap value
SYMBOL_SWAP_SHORT = 39, // Sell order swap value
SYMBOL_MARGIN_INITIAL = 42, // Initial margin means the amount in the margin currency required for opening an order with the volume of one lot. It is used for checking a client's assets when he or she enters the market.
SYMBOL_MARGIN_MAINTENANCE = 43, // The maintenance margin. If it is set, it sets the margin amount in the margin currency of the symbol, charged from one lot. It is used for checking a client's assets when his/her account state changes. If the maintenance margin is equal to 0, the initial margin is used.
SYMBOL_MARGIN_LONG = 44, // Not supported
SYMBOL_MARGIN_SHORT = 45, // Not supported
SYMBOL_MARGIN_LIMIT = 46, // Not supported
SYMBOL_MARGIN_STOP = 47, // Not supported
SYMBOL_MARGIN_STOPLIMIT = 48, // Not supported
SYMBOL_SESSION_VOLUME = 57, // Not supported
SYMBOL_SESSION_TURNOVER = 58, // Not supported
SYMBOL_SESSION_INTEREST = 59, // Not supported
SYMBOL_SESSION_BUY_ORDERS_VOLUME = 61, // Not supported
SYMBOL_SESSION_SELL_ORDERS_VOLUME = 63, // Not supported
SYMBOL_SESSION_OPEN = 64, // Not supported
SYMBOL_SESSION_CLOSE = 65, // Not supported
SYMBOL_SESSION_AW = 66, // Not supported
SYMBOL_SESSION_PRICE_SETTLEMENT = 67, // Not supported
SYMBOL_SESSION_PRICE_LIMIT_MIN = 68, // Not supported
SYMBOL_SESSION_PRICE_LIMIT_MAX = 69, // Not supported
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_double
public enum EnumTerminalInfoDouble
{
TERMINAL_COMMUNITY_BALANCE = 25 // Balance in MQL5.community
}
}
+27
View File
@@ -0,0 +1,27 @@
namespace MtApi
{
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_integer
public enum EnumTerminalInfoInteger
{
TERMINAL_BUILD = 5, // The client terminal build number
TERMINAL_COMMUNITY_ACCOUNT = 23, // The flag indicates the presence of MQL5.community authorization data in the terminal
TERMINAL_COMMUNITY_CONNECTION = 24, // Connection to MQL5.community
TERMINAL_CONNECTED = 6, // Connection to a trade server
TERMINAL_DLLS_ALLOWED = 7, // Permission to use DLL
TERMINAL_TRADE_ALLOWED = 8, // Permission to trade
TERMINAL_EMAIL_ENABLED = 9, // Permission to send e-mails using SMTP-server and login, specified in the terminal settings
TERMINAL_FTP_ENABLED = 10, // Permission to send reports using FTP-server and login, specified in the terminal settings
TERMINAL_NOTIFICATIONS_ENABLED = 26, // Permission to send notifications to smartphone
TERMINAL_MAXBARS = 11, // The maximal bars count on the chart
TERMINAL_MQID = 22, // The flag indicates the presence of MetaQuotes ID data to send Push notifications
TERMINAL_CODEPAGE = 12, // Number of the code page of the language installed in the client terminal
TERMINAL_CPU_CORES = 21, // The number of CPU cores in the system
TERMINAL_DISK_SPACE = 20, // Free disk space for the MQL4\Files folder of the terminal, Mb
TERMINAL_MEMORY_PHYSICAL = 14, // Physical memory in the system, Mb
TERMINAL_MEMORY_TOTAL = 15, // Memory available to the process of the terminal , Mb
TERMINAL_MEMORY_AVAILABLE = 16, // Free memory of the terminal process, Mb
TERMINAL_MEMORY_USED = 17, // Memory used by the terminal , Mb
TERMINAL_SCREEN_DPI = 27, // The resolution of information display on the screen is measured as number of Dots in a line per Inch (DPI). Knowing the parameter value, you can set the size of graphical objects so that they look the same on monitors with different resolution characteristics.
TERMINAL_PING_LAST = 28 // The last known value of a ping to a trade server in microseconds. One second comprises of one million microseconds
}
}
-42
View File
@@ -1,42 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MtApi
{
static class ExtensionMethods
{
#region Event Methods
public static Task FireEventAsync(this MtApiQuoteHandler evenHandler, object sender, string symbol, double bid, double ask)
{
return Task.Factory.StartNew(() =>
{
evenHandler?.Invoke(sender, symbol, bid, ask);
});
}
public static Task FireEventAsync(this EventHandler eventHandler, object sender)
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, EventArgs.Empty);
});
}
public static Task FireEventAsync<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, e);
});
}
#endregion
public static MtQuote Convert(this MTApiService.MtQuote quote)
{
return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null;
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace MtApi
{
[Flags]
public enum FlagFontStyle
{
//Flags for specifying font style
FONT_ITALIC = -2147483648,
FONT_UNDERLINE = 1073741824,
FONT_STRIKEOUT = 536870912,
//Flags for specifying font width
FW_DONTCARE = 0,
FW_THIN = 1,
FW_EXTRALIGHT = 2,
FW_ULTRALIGHT = 3,
FW_LIGHT = 4,
FW_NORMAL = 5,
FW_REGULAR = 6,
FW_MEDIUM = 7,
FW_SEMIBOLD = 8,
FW_DEMIBOLD = 9,
FW_BOLD = 10,
FW_EXTRABOLD = 11,
FW_ULTRABOLD = 12,
FW_HEAVY = 13,
FW_BLACK = 14
}
}
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public enum MarketInfoModeType
{
+3 -8
View File
@@ -4,7 +4,7 @@ namespace MtApi.Monitors
public class TimeframeTradeMonitor : TradeMonitor
{
#region Fields
private volatile bool _isStarted = false;
private volatile bool _isStarted;
#endregion
#region ctor
@@ -23,13 +23,8 @@ namespace MtApi.Monitors
// Returns:
// true if PositionMonitor should check orders
// otherwise, false.
public override bool IsStarted
{
get
{
return _isStarted;
}
}
public override bool IsStarted => _isStarted;
#endregion
#region Protected Methods
+6 -15
View File
@@ -13,7 +13,7 @@ namespace MtApi.Monitors
#endregion
#region ctor
public TradeMonitor(MtApiClient apiClient)
protected TradeMonitor(MtApiClient apiClient)
{
if (apiClient == null)
throw new ArgumentNullException(nameof(apiClient));
@@ -73,13 +73,7 @@ namespace MtApi.Monitors
protected abstract void OnMtConnected();
protected abstract void OnMtDisconnected();
public bool IsMtConnected
{
get
{
return _apiClient.ConnectionState == MtConnectionState.Connected;
}
}
public bool IsMtConnected => _apiClient.ConnectionState == MtConnectionState.Connected;
protected void Check()
{
@@ -113,12 +107,12 @@ namespace MtApi.Monitors
prevOrders = _prevOrders;
}
if (_prevOrders != null) //skip checking on first load orders
if (prevOrders != null) //skip checking on first load orders
{
//check open orders
foreach (var order in tradesOrders)
{
if (_prevOrders.Find(a => a.Ticket == order.Ticket) == null)
if (prevOrders.Find(a => a.Ticket == order.Ticket) == null)
{
openedOrders.Add(order);
}
@@ -126,7 +120,7 @@ namespace MtApi.Monitors
//check closed orders
var closeOrdersTemp = new List<MtOrder>();
foreach (var order in _prevOrders)
foreach (var order in prevOrders)
{
if (tradesOrders.Find(a => a.Ticket == order.Ticket) == null)
{
@@ -180,10 +174,7 @@ namespace MtApi.Monitors
_prevOrders = null;
}
Task.Factory.StartNew(() =>
{
Check();
});
Task.Factory.StartNew(Check);
}
#endregion
}
+1 -6
View File
@@ -5,12 +5,7 @@ namespace MtApi
public class MqlRates
{
public int MtTime { get; set; }
public DateTime Time
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtTime); }
}
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
public double Open { get; set; }
public double High { get; set; }
public double Low { get; set; }
+14
View File
@@ -0,0 +1,14 @@
using System;
namespace MtApi
{
public class MqlTick
{
public int MtTime { get; set; }
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
public double Bid { get; set; }
public double Ask { get; set; }
public double Last { get; set; }
public ulong Volume { get; set; }
}
}
+17 -1
View File
@@ -59,10 +59,20 @@
</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="ExtensionMethods.cs" />
<Compile Include="EnumTerminalInfoDouble.cs" />
<Compile Include="EnumTerminalInfoInteger.cs" />
<Compile Include="FlagFontStyle.cs" />
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
<Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" />
<Compile Include="MtConnectionEventArgs.cs" />
<Compile Include="MtConnectionException.cs" />
<Compile Include="MtConnectionState.cs" />
@@ -92,16 +102,22 @@
<Compile Include="Requests\OrderDeleteRequest.cs" />
<Compile Include="Requests\OrderModifyRequest.cs" />
<Compile Include="Requests\OrderSendRequest.cs" />
<Compile Include="Requests\SeriesInfoIntegerRequest.cs" />
<Compile Include="Requests\SessionRequest.cs" />
<Compile Include="Requests\RequestBase.cs" />
<Compile Include="Requests\RequestType.cs" />
<Compile Include="Requests\SymbolInfoDoubleRequest.cs" />
<Compile Include="Requests\SymbolInfoTickRequest.cs" />
<Compile Include="Responses\CopyRatesResponse.cs" />
<Compile Include="Responses\GetOrderResponse.cs" />
<Compile Include="Responses\GetOrdersResponse.cs" />
<Compile Include="Responses\ICustomResponse.cs" />
<Compile Include="Responses\OrderSendResponse.cs" />
<Compile Include="Responses\SeriesInfoIntegerResponse.cs" />
<Compile Include="Responses\SessionResponse.cs" />
<Compile Include="Responses\ResponseBase.cs" />
<Compile Include="Responses\SymbolInfoDoubleResponse.cs" />
<Compile Include="Responses\SymbolInfoTickResponse.cs" />
<Compile Include="SeriesIdentifier.cs" />
<Compile Include="TimeBarArgs.cs" />
<Compile Include="Monitors\TimeframeTradeMonitor.cs" />
+941 -200
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -13,9 +13,9 @@ namespace MtApi
return Color.FromArgb((byte)(color), (byte)(color >> 8), (byte)(color >> 16));
}
public static int ConvertToMtColor(Color color)
public static int ConvertToMtColor(Color? color)
{
return color == Color.Empty ? 0xffffff : (Color.FromArgb(color.B, color.G, color.R).ToArgb() & 0xffffff);
return color == null || color == Color.Empty ? 0xffffff : (Color.FromArgb(color.Value.B, color.Value.G, color.Value.R).ToArgb() & 0xffffff);
}
}
}
+3 -3
View File
@@ -13,13 +13,13 @@ namespace MtApi
return new DateTime(tmpTime.Ticks + (time * 0x989680L));
}
public static int ConvertToMtTime(DateTime time)
public static int ConvertToMtTime(DateTime? time)
{
int result = 0;
if (time != DateTime.MinValue)
if (time != null && time != DateTime.MinValue)
{
DateTime tmpTime = new DateTime(1970, 1, 1);
result = (int)((time.Ticks - tmpTime.Ticks) / 0x989680L);
result = (int)((time.Value.Ticks - tmpTime.Ticks) / 0x989680L);
}
return result;
}
+44 -18
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
enum MtCommandType
{
@@ -58,9 +53,15 @@ namespace MtApi
IsVisualMode = 37,
UninitializeReason = 38,
ErrorDescription = 39,
TerminalCompany = 68,
TerminalName = 69,
TerminalPath = 70,
TerminalInfoString = 153,
TerminalInfoInteger = 204,
TerminalInfoDouble = 205,
//Account Information
AccountBalance = 40,
AccountBalance = 40,
AccountCredit = 41,
AccountCompany = 42,
AccountCurrency = 43,
@@ -91,11 +92,6 @@ namespace MtApi
SendMail = 66,
Sleep = 67,
//Client Terminal
TerminalCompany = 68,
TerminalName = 69,
TerminalPath = 70,
//Date and Time
Day = 71,
DayOfWeek = 72,
@@ -139,8 +135,8 @@ namespace MtApi
iBullsPower = 106,
iCCI = 107,
iCCIOnArray = 108,
iCustom = 109,
iCustom_d = 10109,
//iCustom = 109,
//iCustom_d = 10109,
iDeMarker = 110,
iEnvelopes = 111,
iEnvelopesOnArray = 112,
@@ -188,8 +184,6 @@ namespace MtApi
//
RefreshRates = 150,
//
TerminalInfoString = 153,
SymbolInfoString = 154,
//Requests
MtRequest = 155,
@@ -197,10 +191,42 @@ namespace MtApi
//Backtesting
BacktestingReady = 156,
//Symbols
//Market Info
SymbolInfoString = 154,
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 -4
View File
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
public class MtConnectionEventArgs: EventArgs
{
public MtConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; }
public string ConnectionMessage { get; private set; }
public MtConnectionEventArgs(MtConnectionState status, string message)
{
Regular → Executable
+85 -84
View File
@@ -1,5 +1,6 @@
namespace MtApi
{
// https://docs.mql4.com/constants/errorswarnings/errorcodes
public enum MtErrorCode
{
MtApiCustomError = -1, // Error occurred in MtApi.
@@ -10,91 +11,91 @@
ServerBusy = 4, // Trade server is busy.
OldVersion = 5, // Old version of the client terminal.
NoConnection = 6, // No connection with trade server.
NotEnoughRights = 7, // Not enough rights.
TooFrequentRequests = 8, // Too frequent requests.
MalfunctionalTrade = 9, // Malfunctional trade operation.
NotEnoughRights = 7, // Not enough rights.
TooFrequentRequests = 8, // Too frequent requests.
MalfunctionalTrade = 9, // Malfunctional trade operation.
AccountDisabled = 64, // Account disabled.
InvalidAccount = 65, // Invalid account.
TradeTimeout = 128, // Trade timeout.
InvalidPrice = 129, // Invalid price.
InvalidStops = 130, // Invalid stops.
InvalidTradeVolume = 131, // Invalid trade volume.
MarketClosed = 132, // Market is closed.
TradeDisabled = 133, // Trade is disabled.
NotEnoughMoney = 134, // Not enough money.
PriceChanged = 135, // Price changed.
OffQuotes = 136, // Off quotes.
BrokerBusy = 137, // Broker is busy.
Requote = 138, // Requote.
OrderLocked = 139, // Order is locked.
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
TooManyRequests = 141, // Too many requests.
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
TradeContextBusy = 146, // Trade context is busy.
TradeExpirationDenied = 147, // Expirations are denied by broker.
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
InvalidAccount = 65, // Invalid account.
TradeTimeout = 128, // Trade timeout.
InvalidPrice = 129, // Invalid price.
InvalidStops = 130, // Invalid stops.
InvalidTradeVolume = 131, // Invalid trade volume.
MarketClosed = 132, // Market is closed.
TradeDisabled = 133, // Trade is disabled.
NotEnoughMoney = 134, // Not enough money.
PriceChanged = 135, // Price changed.
OffQuotes = 136, // Off quotes.
BrokerBusy = 137, // Broker is busy.
Requote = 138, // Requote.
OrderLocked = 139, // Order is locked.
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
TooManyRequests = 141, // Too many requests.
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
TradeContextBusy = 146, // Trade context is busy.
TradeExpirationDenied = 147, // Expirations are denied by broker.
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
NoMqlerror = 4000, // No error.
WrongFunctionPointer = 4001, // Wrong function pointer.
ArrayIndexOutOfRange = 4002, // Array index is out of range.
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
RecursiveStackOverflow = 4004, // Recursive stack overflow.
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
NoMemoryForParameterString = 4006, // No memory for parameter string.
NoMemoryForTempString = 4007, // No memory for temp string.
NotInitializedString = 4008, // Not initialized string.
NotInitializedArraystring = 4009, // Not initialized string in an array.
NoMemoryForArraystring = 4010, // No memory for an array string.
TooLongString = 4011, // Too long string.
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
ZeroDivide = 4013, // Zero divide.
UnknownCommand = 4014, // Unknown command.
WrongJump = 4015, // Wrong jump.
NotInitializedArray = 4016, // Not initialized array.
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
CannotLoadLibrary = 4018, // Cannot load library.
CannotCallFunction = 4019, // Cannot call function.
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
SystemBusy = 4022, // System is busy.
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
StringFunctionInternalError = 4052, // String function internal error.
SomeArrayError = 4053, // Some array error.
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
CustomIndicatorError = 4055, // Custom indicator error.
IncompatibleArrays = 4056, // Arrays are incompatible.
GlobalVariablesProcessingError = 4057, // Global variables processing error.
GlobalVariableNotFound = 4058, // Global variable not found.
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
FunctionNotConfirmed = 4060, // Function is not confirmed.
SendMailError = 4061, // Mail sending error.
StringParameterExpected = 4062, // String parameter expected.
IntegerParameterExpected = 4063, // Integer parameter expected.
DoubleParameterExpected = 4064, // Double parameter expected.
ArrayAsParameterExpected = 4065, // Array as parameter expected.
HistoryWillUpdated = 4066, // Requested history data in updating state.
TradeError = 4067, // Some error in trade operation execution.
EndOfFile = 4099, // End of a file.
SomeFileError = 4100, // Some file error.
WrongFileName = 4101, // Wrong file name.
TooManyOpenedFiles = 4102, // Too many opened files.
CannotOpenFile = 4103, // Cannot open file.
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
NoOrderSelected = 4105, // No order selected.
UnknownSymbol = 4106, // Unknown symbol.
InvalidPriceParam = 4107, // Invalid price.
InvalidTicket = 4108, // Invalid ticket.
TradeNotAllowed = 4109, // Trade is not allowed.
LongsNotAllowed = 4110, // Longs are not allowed.
ShortsNotAllowed = 4111, // Shorts are not allowed.
ObjectAlreadyExists = 4200, // Object already exists.
UnknownObjectProperty = 4201, // Unknown object property.
ObjectDoesNotExist = 4202, // Object does not exist.
UnknownObjectType = 4203, // Unknown object type.
NoObjectName = 4204, // No object name.
ObjectCoordinatesError = 4205, // Object coordinates error.
NoSpecifiedSubwindow = 4206, // No specified subwindow.
SomeObjectError = 4207 // Some error in object operation.
NoMqlerror = 4000, // No error.
WrongFunctionPointer = 4001, // Wrong function pointer.
ArrayIndexOutOfRange = 4002, // Array index is out of range.
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
RecursiveStackOverflow = 4004, // Recursive stack overflow.
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
NoMemoryForParameterString = 4006, // No memory for parameter string.
NoMemoryForTempString = 4007, // No memory for temp string.
NotInitializedString = 4008, // Not initialized string.
NotInitializedArraystring = 4009, // Not initialized string in an array.
NoMemoryForArraystring = 4010, // No memory for an array string.
TooLongString = 4011, // Too long string.
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
ZeroDivide = 4013, // Zero divide.
UnknownCommand = 4014, // Unknown command.
WrongJump = 4015, // Wrong jump.
NotInitializedArray = 4016, // Not initialized array.
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
CannotLoadLibrary = 4018, // Cannot load library.
CannotCallFunction = 4019, // Cannot call function.
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
SystemBusy = 4022, // System is busy.
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
StringFunctionInternalError = 4052, // String function internal error.
SomeArrayError = 4053, // Some array error.
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
CustomIndicatorError = 4055, // Custom indicator error.
IncompatibleArrays = 4056, // Arrays are incompatible.
GlobalVariablesProcessingError = 4057, // Global variables processing error.
GlobalVariableNotFound = 4058, // Global variable not found.
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
FunctionNotConfirmed = 4060, // Function is not confirmed.
SendMailError = 4061, // Mail sending error.
StringParameterExpected = 4062, // String parameter expected.
IntegerParameterExpected = 4063, // Integer parameter expected.
DoubleParameterExpected = 4064, // Double parameter expected.
ArrayAsParameterExpected = 4065, // Array as parameter expected.
HistoryWillUpdated = 4066, // Requested history data in updating state.
TradeError = 4067, // Some error in trade operation execution.
EndOfFile = 4099, // End of a file.
SomeFileError = 4100, // Some file error.
WrongFileName = 4101, // Wrong file name.
TooManyOpenedFiles = 4102, // Too many opened files.
CannotOpenFile = 4103, // Cannot open file.
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
NoOrderSelected = 4105, // No order selected.
UnknownSymbol = 4106, // Unknown symbol.
InvalidPriceParam = 4107, // Invalid price.
InvalidTicket = 4108, // Invalid ticket.
TradeNotAllowed = 4109, // Trade is not allowed.
LongsNotAllowed = 4110, // Longs are not allowed.
ShortsNotAllowed = 4111, // Shorts are not allowed.
ObjectAlreadyExists = 4200, // Object already exists.
UnknownObjectProperty = 4201, // Unknown object property.
ObjectDoesNotExist = 4202, // Object does not exist.
UnknownObjectType = 4203, // Unknown object type.
NoObjectName = 4204, // No object name.
ObjectCoordinatesError = 4205, // Object coordinates error.
NoSpecifiedSubwindow = 4206, // No specified subwindow.
SomeObjectError = 4207 // Some error in object operation.
}
}
+10 -6
View File
@@ -1,15 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public class MtQuote
{
public string Instrument { get; private set; }
public double Bid { get; private set; }
public double Ask { get; private set; }
public int ExpertHandle { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
@@ -17,5 +13,13 @@ namespace MtApi
Bid = bid;
Ask = ask;
}
internal MtQuote(MTApiService.MtQuote quote)
{
Instrument = quote.Instrument;
Bid = quote.Bid;
Ask = quote.Ask;
ExpertHandle = quote.ExpertHandle;
}
}
}
-3
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
+23 -29
View File
@@ -1,29 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{
public class MtSession
{
public string Symbol { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public uint Index { get; set; }
public int MtFromTime { get; set; }
public DateTime From
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtFromTime); }
}
public int MtToTime { get; set; }
public DateTime To
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtToTime); }
}
public bool HasData { get; set; }
public SessionType Type { get; set; }
}
public enum SessionType { Quote, Trade }
}
using System;
namespace MtApi
{
public class MtSession
{
public string Symbol { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public uint Index { get; set; }
public int MtFromTime { get; set; }
public DateTime From => MtApiTimeConverter.ConvertFromMtTime(MtFromTime);
public int MtToTime { get; set; }
public DateTime To => MtApiTimeConverter.ConvertFromMtTime(MtToTime);
public bool HasData { get; set; }
public SessionType Type { get; set; }
}
public enum SessionType
{
Quote,
Trade
}
}
Executable → Regular
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.31.0")]
[assembly: AssemblyFileVersion("1.0.31.0")]
[assembly: AssemblyVersion("1.0.33.0")]
[assembly: AssemblyFileVersion("1.0.33.0")]
+9 -27
View File
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Requests
namespace MtApi.Requests
{
public abstract class CopyRatesRequestBase : RequestBase
internal abstract class CopyRatesRequestBase : RequestBase
{
public enum CopyRatesTypeEnum
{
@@ -15,10 +9,7 @@ namespace MtApi.Requests
CopyRates_3 = 3,
}
public override RequestType RequestType
{
get { return RequestType.CopyRates; }
}
public override RequestType RequestType => RequestType.CopyRates;
public abstract CopyRatesTypeEnum CopyRatesType { get; }
@@ -26,34 +17,25 @@ namespace MtApi.Requests
public ENUM_TIMEFRAMES Timeframe { get; set; }
}
public class CopyRates1Request : CopyRatesRequestBase
internal class CopyRates1Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_1; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_1;
public int StartPos { get; set; }
public int Count { get; set; }
}
public class CopyRates2Request : CopyRatesRequestBase
internal class CopyRates2Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_2; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_2;
public int StartTime { get; set; }
public int Count { get; set; }
}
public class CopyRates3Request : CopyRatesRequestBase
internal class CopyRates3Request : CopyRatesRequestBase
{
public override CopyRatesTypeEnum CopyRatesType
{
get { return CopyRatesTypeEnum.CopyRates_3; }
}
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_3;
public int StartTime { get; set; }
public int StopTime { get; set; }
+2 -5
View File
@@ -1,14 +1,11 @@
namespace MtApi.Requests
{
public class GetOrderRequest: RequestBase
internal class GetOrderRequest: RequestBase
{
public int Index { get; set; }
public int Select { get; set; }
public int Pool { get; set; }
public override RequestType RequestType
{
get { return RequestType.GetOrder; }
}
public override RequestType RequestType => RequestType.GetOrder;
}
}
+2 -5
View File
@@ -1,12 +1,9 @@
namespace MtApi.Requests
{
public class GetOrdersRequest: RequestBase
internal class GetOrdersRequest: RequestBase
{
public int Pool { get; set; }
public override RequestType RequestType
{
get { return RequestType.GetOrders; }
}
public override RequestType RequestType => RequestType.GetOrders;
}
}
Regular → Executable
+3 -8
View File
@@ -1,10 +1,8 @@
using System;
using System.Collections;
using System.Collections;
namespace MtApi.Requests
{
public class ICustomRequest : RequestBase
internal class ICustomRequest : RequestBase
{
public enum ParametersType
{
@@ -22,9 +20,6 @@ namespace MtApi.Requests
public ArrayList Params { get; set; }
public ParametersType ParamsType { get; set; }
public override RequestType RequestType
{
get { return RequestType.iCustom; }
}
public override RequestType RequestType => RequestType.iCustom;
}
}
+2 -5
View File
@@ -1,15 +1,12 @@
namespace MtApi.Requests
{
public class OrderCloseByRequest: RequestBase
internal class OrderCloseByRequest: RequestBase
{
public int Ticket { get; set; }
public int Opposite { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderCloseBy; }
}
public override RequestType RequestType => RequestType.OrderCloseBy;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderCloseRequest: RequestBase
internal class OrderCloseRequest: RequestBase
{
public int Ticket { get; set; }
@@ -9,9 +9,6 @@
public int? Slippage { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderClose; }
}
public override RequestType RequestType => RequestType.OrderClose;
}
}
+2 -5
View File
@@ -1,14 +1,11 @@
namespace MtApi.Requests
{
public class OrderDeleteRequest: RequestBase
internal class OrderDeleteRequest: RequestBase
{
public int Ticket { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderDelete; }
}
public override RequestType RequestType => RequestType.OrderDelete;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderModifyRequest: RequestBase
internal class OrderModifyRequest: RequestBase
{
public int Ticket { get; set; }
public double Price { get; set; }
@@ -10,9 +10,6 @@
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderModify; }
}
public override RequestType RequestType => RequestType.OrderModify;
}
}
+2 -5
View File
@@ -1,6 +1,6 @@
namespace MtApi.Requests
{
public class OrderSendRequest: RequestBase
internal class OrderSendRequest: RequestBase
{
public string Symbol { get; set; }
public int Cmd { get; set; }
@@ -15,9 +15,6 @@
public int? Expiration { get; set; }
public int? ArrowColor { get; set; }
public override RequestType RequestType
{
get { return RequestType.OrderSend; }
}
public override RequestType RequestType => RequestType.OrderSend;
}
}
+6 -8
View File
@@ -1,9 +1,7 @@
using Newtonsoft.Json;
namespace MtApi.Requests
{
public abstract class RequestBase
namespace MtApi.Requests
{
internal abstract class RequestBase
{
public abstract RequestType RequestType { get; }
}
}
public abstract RequestType RequestType { get; }
}
}
+15 -12
View File
@@ -1,17 +1,20 @@
namespace MtApi.Requests
{
public enum RequestType
internal enum RequestType
{
Unknown = 0,
GetOrder = 1,
GetOrders = 2,
OrderSend = 3,
OrderClose = 4,
OrderCloseBy = 5,
OrderDelete = 6,
OrderModify = 7,
iCustom = 8,
CopyRates = 9,
Session = 10,
Unknown = 0,
GetOrder = 1,
GetOrders = 2,
OrderSend = 3,
OrderClose = 4,
OrderCloseBy = 5,
OrderDelete = 6,
OrderModify = 7,
iCustom = 8,
CopyRates = 9,
Session = 10,
SeriesInfoInteger = 11,
SymbolInfoDouble = 12,
SymbolInfoTick = 13
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi.Requests
{
internal class SeriesInfoIntegerRequest: RequestBase
{
public override RequestType RequestType => RequestType.SeriesInfoInteger;
public string SymbolName { get; set; }
public int Timeframe { get; set; }
public int PropId { get; set; }
}
}
+2 -5
View File
@@ -2,16 +2,13 @@
namespace MtApi.Requests
{
public class SessionRequest : RequestBase
internal class SessionRequest : RequestBase
{
public string Symbol { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public int SessionIndex { get; set; }
public SessionType SessionType { get; set; }
public override RequestType RequestType
{
get { return RequestType.Session; }
}
public override RequestType RequestType => RequestType.Session;
}
}
+12
View File
@@ -0,0 +1,12 @@
using System;
namespace MtApi.Requests
{
internal class SymbolInfoDoubleRequest : RequestBase
{
public override RequestType RequestType => RequestType.SymbolInfoDouble;
public string SymbolName { get; set; }
public int PropId { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi.Requests
{
internal class SymbolInfoTickRequest: RequestBase
{
public override RequestType RequestType => RequestType.SymbolInfoTick;
public string Symbol { get; set; }
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MtApi.Responses
{
public class CopyRatesResponse: ResponseBase
internal class CopyRatesResponse: ResponseBase
{
public List<MqlRates> Rates { get; set; }
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class GetOrderResponse: ResponseBase
internal class GetOrderResponse: ResponseBase
{
public MtOrder Order { get; set; }
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MtApi.Responses
{
public class GetOrdersResponse: ResponseBase
internal class GetOrdersResponse: ResponseBase
{
public List<MtOrder> Orders { get; set; }
}
+2 -8
View File
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Responses
namespace MtApi.Responses
{
public class ICustomResponse: ResponseBase
internal class ICustomResponse: ResponseBase
{
public double Value { get; set; }
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class OrderSendResponse: ResponseBase
internal class OrderSendResponse: ResponseBase
{
public int Ticket { get; set; }
}
Regular → Executable
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class ResponseBase
internal class ResponseBase
{
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SeriesInfoIntegerResponse: ResponseBase
{
public long Value { get; set; }
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MtApi.Responses
{
public class SessionResponse : ResponseBase
internal class SessionResponse : ResponseBase
{
public MtSession Session { get; set; }
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SymbolInfoDoubleResponse: ResponseBase
{
public double Value { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi.Responses
{
internal class SymbolInfoTickResponse: ResponseBase
{
public MqlTick Tick { get; set; }
}
}
-4
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
public enum TradeOperation
{
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi5
{
public enum CopyTicksFlag
{
Info = 1, // ticks with Bid and/or Ask changes
Trade = 2, // ticks with changes in Last and Volume
All = -1 // all ticks
}
}
+188
View File
@@ -0,0 +1,188 @@
namespace MtApi5
{
//Error codes from https://www.mql5.com/en/docs/constants/errorswarnings/errorcodes
public enum ErrorCode
{
ErrCustom = -1, // Error occurred in MtApi5.
ErrSuccess = 0, // The operation completed successfully
ErrInternalError = 4001, // Unexpected internal error
ErrWrongInternalParameter = 4002, // Wrong parameter in the inner call of the client terminal function
ErrInvalidParameter = 4003, // Wrong parameter when calling the system function
ErrNotEnoughMemory = 4004, // Not enough memory to perform the system function
ErrStructWithobjectsOrclass = 4005, // The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes
ErrInvalidArray = 4006, // Array of a wrong type, wrong size, or a damaged object of a dynamic array
ErrArrayResizeError = 4007, // Not enough memory for the relocation of an array, or an attempt to change the size of a static array
ErrStringResizeError = 4008, // Not enough memory for the relocation of string
ErrNotinitializedString = 4009, // Not initialized string
ErrInvalidDatetime = 4010, // Invalid date and/or time
ErrArrayBadSize = 4011, // Requested array size exceeds 2 GB
ErrInvalidPointer = 4012, // Wrong pointer
ErrInvalidPointerType = 4013, // Wrong type of pointer
ErrFunctionNotAllowed = 4014, // Function is not allowed for call
ErrResourceNameDuplicated = 4015, // The names of the dynamic and the static resource match
ErrResourceNotFound = 4016, // Resource with this name has not been found in EX5
ErrResourceUnsuppotedType = 4017, // Unsupported resource type or its size exceeds 16 Mb
ErrResourceNameIsTooLong = 4018, // The resource name exceeds 63 characters
ErrChartWrongId = 4101, // Wrong chart ID
ErrChartNoReply = 4102, // Chart does not respond
ErrChartNotFound = 4103, // Chart not found
ErrChartNoExpert = 4104, // No Expert Advisor in the chart that could handle the event
ErrChartCannotOpen = 4105, // Chart opening error
ErrChartCannotChange = 4106, // Failed to change chart symbol and period
ErrChartWrongParameter = 4107, // Error value of the parameter for the function of working with charts
ErrChartCannotCreateTimer = 4108, // Failed to create timer
ErrChartWrongProperty = 4109, // Wrong chart property ID
ErrChartScreenshotFailed = 4110, // Error creating screenshots
ErrChartNavigateFailed = 4111, // Error navigating through chart
ErrChartTemplateFailed = 4112, // Error applying template
ErrChartWindowNotFound = 4113, // Subwindow containing the indicator was not found
ErrChartIndicatorCannotAdd = 4114, // Error adding an indicator to chart
ErrChartIndicatorCannotDel = 4115, // Error deleting an indicator from the chart
ErrChartIndicatorNotFound = 4116, // Indicator not found on the specified chart
ErrObjectError = 4201, // Error working with a graphical object
ErrObjectNotFound = 4202, // Graphical object was not found
ErrObjectWrongProperty = 4203, // Wrong ID of a graphical object property
ErrObjectGetdateFailed = 4204, // Unable to get date corresponding to the value
ErrObjectGetvalueFailed = 4205, // Unable to get value corresponding to the date
ErrMarketUnknownSymbol = 4301, // Unknown symbol
ErrMarketNotSelected = 4302, // Symbol is not selected in MarketWatch
ErrMarketWrongProperty = 4303, // Wrong identifier of a symbol property
ErrMarketLasttimeUnknown = 4304, // Time of the last tick is not known (no ticks)
ErrMarketSelectError = 4305, // Error adding or deleting a symbol in MarketWatch
ErrHistoryNotFound = 4401, // Requested history not found
ErrHistoryWrongProperty = 4402, // Wrong ID of the history property
ErrGlobalvariableNotFound = 4501, // Global variable of the client terminal is not found
ErrGlobalvariableExists = 4502, // Global variable of the client terminal with the same name already exists
ErrMailSendFailed = 4510, // Email sending failed
ErrPlaySoundFailed = 4511, // Sound playing failed
ErrMql5WrongProperty = 4512, // Wrong identifier of the program property
ErrTerminalWrongProperty = 4513, // Wrong identifier of the terminal property
ErrFtpSendFailed = 4514, // File sending via ftp failed
ErrNotificationSendFailed = 4515, // Failed to send a notification
ErrNotificationWrongParameter = 4516, // Invalid parameter for sending a notification — an empty string or NULL has been passed to the SendNotification() function
ErrNotificationWrongSettings = 4517, // Wrong settings of notifications in the terminal (ID is not specified or permission is not set)
ErrNotificationTooFrequent = 4518, // Too frequent sending of notifications
ErrFtpNoserver = 4519, // FTP server is not specified
ErrFtpNologin = 4520, // FTP login is not specified
ErrFtpFileError = 4521, // File not found in the MQL5\Files directory to send on FTP server
ErrFtpConnectFailed = 4522, // FTP connection failed
ErrFtpChangedir = 4523, // FTP path not found on server
ErrFtpClosed = 4524, // FTP connection closed
ErrBuffersNoMemory = 4601, // Not enough memory for the distribution of indicator buffers
ErrBuffersWrongIndex = 4602, // Wrong indicator buffer index
ErrCustomWrongProperty = 4603, // Wrong ID of the custom indicator property
ErrAccountWrongProperty = 4701, // Wrong account property ID
ErrTradeWrongProperty = 4751, // Wrong trade property ID
ErrTradeDisabled = 4752, // Trading by Expert Advisors prohibited
ErrTradePositionNotFound = 4753, // Position not found
ErrTradeOrderNotFound = 4754, // Order not found
ErrTradeDealNotFound = 4755, // Deal not found
ErrTradeSendFailed = 4756, // Trade request sending failed
ErrIndicatorUnknownSymbol = 4801, // Unknown symbol
ErrIndicatorCannotCreate = 4802, // Indicator cannot be created
ErrIndicatorNoMemory = 4803, // Not enough memory to add the indicator
ErrIndicatorCannotApply = 4804, // The indicator cannot be applied to another indicator
ErrIndicatorCannotAdd = 4805, // Error applying an indicator to chart
ErrIndicatorDataNotFound = 4806, // Requested data not found
ErrIndicatorWrongHandle = 4807, // Wrong indicator handle
ErrIndicatorWrongParameters = 4808, // Wrong number of parameters when creating an indicator
ErrIndicatorParametersMissing = 4809, // No parameters when creating an indicator
ErrIndicatorCustomName = 4810, // The first parameter in the array must be the name of the custom indicator
ErrIndicatorParameterType = 4811, // Invalid parameter type in the array when creating an indicator
ErrIndicatorWrongIndex = 4812, // Wrong index of the requested indicator buffer
ErrBooksCannotAdd = 4901, // Depth Of Market can not be added
ErrBooksCannotDelete = 4902, // Depth Of Market can not be removed
ErrBooksCannotGet = 4903, // The data from Depth Of Market can not be obtained
ErrBooksCannotSubscribe = 4904, // Error in subscribing to receive new data from Depth Of Market
ErrTooManyFiles = 5001, // More than 64 files cannot be opened at the same time
ErrWrongFilename = 5002, // Invalid file name
ErrTooLongFilename = 5003, // Too long file name
ErrCannotOpenFile = 5004, // File opening error
ErrFileCachebufferError = 5005, // Not enough memory for cache to read
ErrCannotDeleteFile = 5006, // File deleting error
ErrInvalidFilehandle = 5007, // A file with this handle was closed, or was not opening at all
ErrWrongFilehandle = 5008, // Wrong file handle
ErrFileNottowrite = 5009, // The file must be opened for writing
ErrFileNottoread = 5010, // The file must be opened for reading
ErrFileNotbin = 5011, // The file must be opened as a binary one
ErrFileNottxt = 5012, // The file must be opened as a text
ErrFileNottxtorcsv = 5013, // The file must be opened as a text or CSV
ErrFileNotcsv = 5014, // The file must be opened as CSV
ErrFileReaderror = 5015, // File reading error
ErrFileBinstringsize = 5016, // String size must be specified, because the file is opened as binary
ErrIncompatibleFile = 5017, // A text file must be for string arrays, for other arrays - binary
ErrFileIsDirectory = 5018, // This is not a file, this is a directory
ErrFileNotExist = 5019, // File does not exist
ErrFileCannotRewrite = 5020, // File can not be rewritten
ErrWrongDirectoryname = 5021, // Wrong directory name
ErrDirectoryNotExist = 5022, // Directory does not exist
ErrFileIsnotDirectory = 5023, // This is a file, not a directory
ErrCannotDeleteDirectory = 5024, // The directory cannot be removed
ErrCannotCleanDirectory = 5025, // Failed to clear the directory (probably one or more files are blocked and removal operation failed)
ErrFileWriteerror = 5026, // Failed to write a resource to a file
ErrFileEndoffile = 5027, // Unable to read the next piece of data from a CSV file (FileReadString, FileReadNumber, FileReadDatetime, FileReadBool), since the end of file is reached
ErrNoStringDate = 5030, // No date in the string
ErrWrongStringDate = 5031, // Wrong date in the string
ErrWrongStringTime = 5032, // Wrong time in the string
ErrStringTimeError = 5033, // Error converting string to date
ErrStringOutOfMemory = 5034, // Not enough memory for the string
ErrStringSmallLen = 5035, // The string length is less than expected
ErrStringTooBignumber = 5036, // Too large number, more than ULONG_MAX
ErrWrongFormatstring = 5037, // Invalid format string
ErrTooManyFormatters = 5038, // Amount of format specifiers more than the parameters
ErrTooManyParameters = 5039, // Amount of parameters more than the format specifiers
ErrWrongStringParameter = 5040, // Damaged parameter of string type
ErrStringposOutofrange = 5041, // Position outside the string
ErrStringZeroadded = 5042, // 0 added to the string end, a useless operation
ErrStringUnknowntype = 5043, // Unknown data type when converting to a string
ErrWrongStringObject = 5044, // Damaged string object
ErrIncompatibleArrays = 5050, // Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only
ErrSmallAsseriesArray = 5051, // The receiving array is declared as AS_SERIES, and it is of insufficient size
ErrSmallArray = 5052, // Too small array, the starting position is outside the array
ErrZerosizeArray = 5053, // An array of zero length
ErrNumberArraysOnly = 5054, // Must be a numeric array
ErrOnedimArraysOnly = 5055, // Must be a one-dimensional array
ErrSeriesArray = 5056, // Timeseries cannot be used
ErrDoubleArrayOnly = 5057, // Must be an array of type double
ErrFloatArrayOnly = 5058, // Must be an array of type float
ErrLongArrayOnly = 5059, // Must be an array of type long
ErrIntArrayOnly = 5060, // Must be an array of type int
ErrShortArrayOnly = 5061, // Must be an array of type short
ErrCharArrayOnly = 5062, // Must be an array of type char
ErrOpenclNotSupported = 5100, // OpenCL functions are not supported on this computer
ErrOpenclInternal = 5101, // Internal error occurred when running OpenCL
ErrOpenclInvalidHandle = 5102, // Invalid OpenCL handle
ErrOpenclContextCreate = 5103, // Error creating the OpenCL context
ErrOpenclQueueCreate = 5104, // Failed to create a run queue in OpenCL
ErrOpenclProgramCreate = 5105, // Error occurred when compiling an OpenCL program
ErrOpenclTooLongKernelName = 5106, // Too long kernel name (OpenCL kernel)
ErrOpenclKernelCreate = 5107, // Error creating an OpenCL kernel
ErrOpenclSetKernelParameter = 5108, // Error occurred when setting parameters for the OpenCL kernel
ErrOpenclExecute = 5109, // OpenCL program runtime error
ErrOpenclWrongBufferSize = 5110, // Invalid size of the OpenCL buffer
ErrOpenclWrongBufferOffset = 5111, // Invalid offset in the OpenCL buffer
ErrOpenclBufferCreate = 5112, // Failed to create an OpenCL buffer
ErrWebrequestInvalidAddress = 5200, // Invalid URL
ErrWebrequestConnectFailed = 5201, // Failed to connect to specified URL
ErrWebrequestTimeout = 5202, // Timeout exceeded
ErrWebrequestRequestFailed = 5203, // HTTP request failed
ErrUserErrorFirst = 65536 // User defined errors start with this code
}
}
+15
View File
@@ -0,0 +1,15 @@
using System;
namespace MtApi5
{
public class ExecutionException: Exception
{
public ExecutionException(ErrorCode errorCode, string message)
:base(message)
{
ErrorCode = errorCode;
}
public ErrorCode ErrorCode { get; private set; }
}
}
-21
View File
@@ -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
}
}
+13 -9
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
@@ -9,17 +6,24 @@ namespace MtApi5
{
public MqlTick(DateTime time, double bid, double ask, double last, ulong volume)
{
this.time = time;
MtTime = Mt5TimeConverter.ConvertToMtTime(time);
this.bid = bid;
this.ask = ask;
this.last = last;
this.volume = volume;
}
public DateTime time { get; private set; } // Time of the last prices update
public double bid { get; private set; } // Current Bid price
public double ask { get; private set; } // Current Ask price
public double last { get; private set; } // Price of the last deal (Last)
public ulong volume { get; private set; } // Volume for the current Last price
public MqlTick()
{
}
public long MtTime { get; set; } // Time of the last prices update
public double bid { get; set; } // Current Bid price
public double ask { get; set; } // Current Ask price
public double last { get; set; } // Price of the last deal (Last)
public ulong volume { get; set; } // Volume for the current Last price
public DateTime time => Mt5TimeConverter.ConvertFromMtTime(MtTime);
}
}
+4 -1
View File
@@ -110,6 +110,9 @@ namespace MtApi5
BacktestingReady = 66,
IsTesting = 67,
Print = 68
Print = 68,
//Requests
MtRequest = 155,
}
}
+1 -4
View File
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5
{
public class Mt5ConnectionEventArgs: EventArgs
{
public Mt5ConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; }
public string ConnectionMessage { get; private set; }
public Mt5ConnectionEventArgs(Mt5ConnectionState status, string message)
{
+15 -1
View File
@@ -32,6 +32,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
@@ -43,6 +47,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CopyTicksFlag.cs" />
<Compile Include="MqlBookInfo.cs" />
<Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" />
@@ -51,15 +56,21 @@
<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" />
<Compile Include="MtApi5Client.cs" />
<Compile Include="Mt5CommandType.cs" />
<Compile Include="MtConverters.cs" />
<Compile Include="ErrorCode.cs" />
<Compile Include="ExecutionException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Mt5Quote.cs" />
<Compile Include="Requests\CopyTicksRequest.cs" />
<Compile Include="Requests\RequestBase.cs" />
<Compile Include="Requests\RequestType.cs" />
<Compile Include="Responses\CopyTicksResponse.cs" />
<Compile Include="Responses\ResponseBase.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
@@ -67,6 +78,9 @@
<Name>MTApiService</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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.
+212 -99
View File
@@ -4,6 +4,10 @@ using System.Linq;
using MTApiService;
using System.Collections;
using System.ServiceModel;
using MtApi5.Requests;
using MtApi5.Responses;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace MtApi5
{
@@ -28,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>
@@ -53,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>
@@ -70,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>
@@ -79,8 +69,7 @@ namespace MtApi5
///</summary>
public void BeginDisconnect()
{
Action disconnectAction = Disconnect;
disconnectAction.BeginInvoke(null, null);
Task.Factory.StartNew(() => Disconnect(false));
}
///<summary>
@@ -88,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());
}
@@ -1200,6 +1186,24 @@ namespace MtApi5
return spreadArray?.Length ?? 0;
}
///<summary>
///The function receives ticks in the MqlTick format into ticks_array. In this case, ticks are indexed from the past to the present, i.e. the 0 indexed tick is the oldest one in the array. For tick analysis, check the flags field, which shows what exactly has changed in the tick.
///</summary>
///<param name="symbolName">Symbol name.</param>
///<param name="flags">The flag that determines the type of received ticks.</param>
///<param name="from">The date from which you want to request ticks. In milliseconds since 1970.01.01. If from=0, the last count ticks will be returned.</param>
///<param name="count">The number of ticks that you want to receive. If the 'from' and 'count' parameters are not specified, all available recent ticks (but not more than 2000) will be written to result.</param>
///<see href="https://www.mql5.com/en/docs/series/copyticks"/>
public List<MqlTick> CopyTicks(string symbolName, CopyTicksFlag flags = CopyTicksFlag.All, ulong from = 0, uint count = 0)
{
var response = SendRequest<CopyTicksResponse>(new CopyTicksRequest
{
SymbolName = symbolName, Flags = (int)flags, From = from, Count = count
});
return response.Ticks;
}
#endregion
#region Market Info
@@ -1302,7 +1306,7 @@ namespace MtApi5
tick = null;
if (retVal != null)
{
tick = new MqlTick(Mt5TimeConverter.ConvertFromMtTime(retVal.time), retVal.bid, retVal.ask, retVal.last, retVal.volume);
tick = new MqlTick { MtTime = retVal.time, ask = retVal.ask, bid = retVal.bid, last = retVal.last, volume = retVal.volume };
}
return tick != null;
@@ -1411,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
@@ -1422,97 +1456,180 @@ 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 void mClient_QuoteUpdated(MtQuote quote)
private T SendRequest<T>(RequestBase request) where T : ResponseBase, new()
{
if (request == null)
return default(T);
var serializer = JsonConvert.SerializeObject(request, Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var commandParameters = new ArrayList { serializer };
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);
if (response.ErrorCode != 0)
{
throw new ExecutionException((ErrorCode)response.ErrorCode, response.ErrorMessage);
}
return response;
}
private void _client_QuoteUpdated(MtQuote quote)
{
if (quote != null)
{
@@ -1520,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()
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.10.0")]
[assembly: AssemblyFileVersion("1.0.10.0")]
[assembly: AssemblyVersion("1.0.11.1")]
[assembly: AssemblyFileVersion("1.0.11.1")]
+12
View File
@@ -0,0 +1,12 @@
namespace MtApi5.Requests
{
internal class CopyTicksRequest: RequestBase
{
public override RequestType RequestType => RequestType.CopyTicks;
public string SymbolName { get; set; }
public int Flags { get; set; }
public ulong From { get; set; }
public uint Count { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi5.Requests
{
internal abstract class RequestBase
{
public abstract RequestType RequestType { get; }
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace MtApi5.Requests
{
internal enum RequestType
{
Unknown = 0,
CopyTicks = 1
}
}
+9
View File
@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace MtApi5.Responses
{
internal class CopyTicksResponse: ResponseBase
{
public List<MqlTick> Ticks { get; set; }
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace MtApi5.Responses
{
internal class ResponseBase
{
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
}
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net40" />
</packages>
+42
View File
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<?if $(var.Platform) = x64 ?>
<?define MsiSourceFileName="MtApi5Installer_x64.msi"?>
<?define VcRedistFileName="vc_redist.x64.exe"?>
<?else ?>
<?define MsiSourceFileName="MtApi5Installer_x86.msi"?>
<?define VcRedistFileName="vc_redist.x86.exe"?>
<?endif ?>
<?define ProductName="!(bind.packageName.MtApi5Msi)" ?>
<?define ProductVersion="!(bind.packageVersion.MtApi5Msi)" ?>
<?define Manufacturer="!(bind.packageManufacturer.MtApi5Msi)" ?>
<Bundle Name="$(var.ProductName) Bootstrapper"
Version="$(var.ProductVersion)"
Manufacturer="$(var.Manufacturer)"
UpgradeCode="1497e285-c228-490b-9638-565e118548fb">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="..\LICENSE.rtf"/>
</BootstrapperApplicationRef>
<Chain>
<ExePackage SourceFile="..\vcredist\$(var.VcRedistFileName)"
Name="Redist\$(var.VcRedistFileName)"
Cache="no"
Compressed="yes"
InstallCommand="/install /quiet /norestart">
<!-- Ignore "Newer version installed" error -->
<ExitCode Value="1638" Behavior="success"/>
</ExePackage>
<MsiPackage Id="MtApi5Msi"
SourceFile="..\build\installers\$(var.Configuration)\$(var.MsiSourceFileName)"
Visible="yes"
DisplayInternalUI="yes" />
</Chain>
</Bundle>
</Wix>
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>1497e285-c228-490b-9638-565e118548fb</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>MtApi5_Setup_$(Platform)</OutputName>
<OutputType>Bundle</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DefineConstants>Debug</DefineConstants>
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Bundle.wxs" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixBalExtension">
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
<Name>WixBalExtension</Name>
</WixExtension>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+3 -3
View File
@@ -6,7 +6,7 @@
<ProductVersion>3.6</ProductVersion>
<ProjectGuid>{a9ed070f-ab4d-4380-9dde-5d931ac71333}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>MtApi5Installer</OutputName>
<OutputName>MtApi5Installer_$(Platform)</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
@@ -22,11 +22,11 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DefineConstants>Debug</DefineConstants>
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
<OutputPath>..\build\installers\$(Configuration)</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
+14 -7
View File
@@ -1,30 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductName="MtApi5" ?>
<?if $(var.Platform) = x64 ?>
<?define ProductName="MtApi5_x64" ?>
<?define ProductPathNative="..\build\products\$(var.Configuration)\x64\"?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define PlatformSystemFolder = "System64Folder" ?>
<?else ?>
<?define ProductName="MtApi5" ?>
<?define ProductPathNative="..\build\products\$(var.Configuration)\"?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?define PlatformSystemFolder = "SystemFolder" ?>
<?endif ?>
<?define ProductVersion="1.0.10" ?>
<?define ProductVersion=!(bind.FileVersion.MtApi5.dll) ?>
<?define Manufacturer="DW"?>
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
<Product Id="*"
<Product Id="*"
Name="$(var.ProductName) $(var.ProductVersion)"
Language="1033"
Version="$(var.ProductVersion)"
Manufacturer="$(var.Manufacturer)"
UpgradeCode="d72d346e-e6f7-4c23-85c6-1c42b3175599">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<WixVariable Id="WixUILicenseRtf" Value="..\LICENSE.rtf" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="MtApi5" Title="$(var.ProductName)" Level="1">
@@ -37,7 +39,7 @@
<Property Id="WIXUI_INSTALLDIR">INSTALLFOLDER</Property>
<UIRef Id="WixUI_Mondo" />
</Product>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
@@ -78,6 +80,11 @@
</RegistryKey>
</Component>
<Component Id="NewtonsoftJsondll" Directory="INSTALLFOLDER">
<File Id="Newtonsoft.Json.dll" Name="Newtonsoft.Json.dll" KeyPath="yes"
src="$(var.ProductPath)Newtonsoft.Json.dll"/>
</Component>
<Component Id="MTApiServiceDll" Directory="INSTALLFOLDER">
<File Id="GAC_MTApiService.dll" Name="MTApiService.dll" KeyPath="yes"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<?if $(var.Platform) = x64 ?>
<?define VcRedistFileName="vc_redist.x64.exe"?>
<?else ?>
<?define VcRedistFileName="vc_redist.x86.exe"?>
<?endif ?>
<?define MsiSourceFileName="MtApiInstaller.msi"?>
<?define ProductName="!(bind.packageName.MtApiMsi)" ?>
<?define ProductVersion="!(bind.packageVersion.MtApiMsi)" ?>
<?define Manufacturer="!(bind.packageManufacturer.MtApiMsi)" ?>
<Bundle Name="$(var.ProductName) Bootstrapper"
Version="$(var.ProductVersion)"
Manufacturer="$(var.Manufacturer)"
UpgradeCode="8e63046b-56e5-4623-8808-558ad72a8f2b">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="..\LICENSE.rtf"/>
</BootstrapperApplicationRef>
<Chain>
<ExePackage SourceFile="..\vcredist\$(var.VcRedistFileName)"
Name="Redist\$(var.VcRedistFileName)"
Cache="no"
Compressed="yes"
InstallCommand="/install /quiet /norestart">
<!-- Ignore "Newer version installed" error -->
<ExitCode Value="1638" Behavior="success"/>
</ExePackage>
<MsiPackage Id="MtApiMsi"
SourceFile="..\build\installers\$(var.Configuration)\$(var.MsiSourceFileName)"
Visible="yes"
DisplayInternalUI="yes" />
</Chain>
</Bundle>
</Wix>

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