using Newtonsoft.Json; using MtClient; using MtApi5.MtProtocol; using MtApi5.MtProtocol.ICustomRequest; using System.Data; namespace MtApi5 { public class MtApi5Client { #region MT Constants public const int SYMBOL_EXPIRATION_GTC = 1; public const int SYMBOL_EXPIRATION_DAY = 2; public const int SYMBOL_EXPIRATION_SPECIFIED = 4; public const int SYMBOL_EXPIRATION_SPECIFIED_DAY = 8; public const int SYMBOL_FILLING_ALL_OR_NONE = 1; public const int SYMBOL_CANCEL_REMAIND = 1; public const int SYMBOL_RETURN_REMAIND = 1; #endregion public delegate void QuoteHandler(object sender, string symbol, double bid, double ask); #region Private Fields private MtRpcClient? _client; private readonly object _locker = new(); private Mt5ConnectionState _connectionState = Mt5ConnectionState.Disconnected; private int _executorHandle; private readonly Dictionary> _mtEventHandlers = []; private HashSet _experts = []; private Dictionary _quotes = []; private volatile int _command_timeout = 30000; // 30 seconds #endregion #region Public Methods private IMtLogger Log { get; } // Time in milliseconds to wait for a response from MetaTrader for a command. Default is 30 seconds. public int CommandTimeout { get => _command_timeout; set { if (value <= 0) throw new ArgumentException("Command timeout must be greater than zero."); _command_timeout = value; } } public MtApi5Client(IMtLogger? log = null) { _mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent; _mtEventHandlers[Mt5EventTypes.OnTick] = ReceivedOnTickEvent; _mtEventHandlers[Mt5EventTypes.OnTradeTransaction] = ReceivedOnTradeTransactionEvent; _mtEventHandlers[Mt5EventTypes.OnLastTimeBar] = ReceivedOnLastTimeBarEvent; _mtEventHandlers[Mt5EventTypes.OnLockTicks] = ReceivedOnLockTicksEvent; Log = log ?? new StubMtLogger(); } /// ///Connect with MetaTrader API. Async method. /// ///Address of MetaTrader host (ex. 192.168.1.2, localhost) ///Port of host connection (default 8222) public void BeginConnect(string host, int port) { Log.Info($"BeginConnect: host = {host}, port = {port}"); Task.Factory.StartNew(async () => { try { await Connect(host, port); } catch (Exception) { } }); } /// ///Connect with MetaTrader API. Async method. /// ///Port of host connection (default 8222) public void BeginConnect(int port) { BeginConnect("localhost", port); } /// ///Connect with MetaTrader API. /// ///Address of MetaTrader host (ex. 192.168.1.2, localhost) ///Port of host connection (default 8222) /// /// Thrown when host is null or empty. /// public async Task Connect(string host, int port) { if (string.IsNullOrEmpty(host)) throw new ArgumentNullException(nameof(host)); lock (_locker) { if (_connectionState == Mt5ConnectionState.Connected || _connectionState == Mt5ConnectionState.Connecting) return; _connectionState = Mt5ConnectionState.Connecting; } ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, $"Connecting to {host}:{port}")); var client = new MtRpcClient(host, port, new RpcClientLogger(Log)); client.ExpertAdded += Client_ExpertAdded; client.ExpertRemoved += Client_ExpertRemoved; client.MtEventReceived += Client_MtEventReceived; client.ConnectionFailed += Client_OnConnectionFailed; client.Disconnected += Client_Disconnected; try { await client.Connect(); Log.Info($"Connected to {host}:{port}"); var experts = client.RequestExpertsList(); if (experts == null || experts.Count == 0) { var errorMessage = "Failed to load expert list"; Log.Error(errorMessage); client.Disconnect(); ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, errorMessage)); throw new Exception($"Connection to {host}:{port} failed. Error: {errorMessage}"); } var quotes = LoadQuotes(client, experts); lock (_locker) { _client = client; _experts = experts; _quotes = quotes; if (_executorHandle == 0) _executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0; _connectionState = Mt5ConnectionState.Connected; } if (IsTesting()) BacktestingReady(); ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, $"Connected to {host}:{port}")); QuoteList?.Invoke(this, new(quotes.Values.ToList())); } catch (Exception e) { Log.Error($"Connect: Failed connection to {host}:{port}. Error: {e.Message}"); lock (_locker) { _connectionState = Mt5ConnectionState.Failed; } ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, e.Message)); throw new Exception($"Connection to {host}:{port} failed. Error: {e.Message}"); } } private Dictionary LoadQuotes(MtRpcClient client, HashSet experts) { Dictionary quotes = []; foreach (var handle in experts) { var quote = GetQuote(client, handle); if (quote != null) quotes[handle] = quote; } return quotes; } /// ///Disconnect from MetaTrader API. Async method. /// public void BeginDisconnect() { Log.Info("BeginDisconnect called."); Task.Factory.StartNew(() => Disconnect(false)); } /// ///Disconnect from MetaTrader API. /// public void Disconnect() { Log.Info("Disconnect called."); Disconnect(false); } /// ///Load quotes connected into MetaTrader API /// public IEnumerable GetQuotes() { MtRpcClient? client; HashSet experts; lock (_locker) { client = _client; experts = new HashSet(_experts); } if (client == null) { Log.Warn("GetQuotes: No connection"); throw new Exception("No connection"); } var quotes = LoadQuotes(client, experts); return quotes.Values.ToList(); } /// ///Load symbols /// public List? GetSymbols(bool selected) { Dictionary cmdParams = new() { { "Selected", selected } }; return SendCommand>(ExecutorHandle, Mt5CommandType.GetSymbols, cmdParams); } /// ///Checks if the Expert Advisor runs in the testing mode.. /// public bool IsTesting() { return SendCommand(ExecutorHandle, Mt5CommandType.IsTesting); } #region Trading functions /// ///Sends trade requests to a server /// ///Reference to a object of MqlTradeRequest type describing the trade activity of the client. ///Reference to a object of MqlTradeResult type describing the result of trade operation in case of a successful completion (if true is returned). /// /// In case of a successful basic check of structures (index checking) returns true. /// However, this is not a sign of successful execution of a trade operation. /// For a more detailed description of the function execution result, analyze the fields of result structure. /// public bool OrderSend(MqlTradeRequest request, out MqlTradeResult? result) { Log.Debug($"OrderSend: request = {request}"); if (request == null) { Log.Warn("OrderSend: request is not defined!"); result = null; return false; } Dictionary commandParameters = new() { { "TradeRequest", request } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.OrderSend, commandParameters); result = response?.Result; return response != null && response.RetVal; } /// ///Function is used for conducting asynchronous trade operations without waiting for the trade server's response to a sent request. /// ///Reference to a object of MqlTradeRequest type describing the trade activity of the client. ///Reference to a object of MqlTradeResult type describing the result of trade operation in case of a successful completion (if true is returned). /// /// Returns true if the request is sent to a trade server. In case the request is not sent, it returns false. /// In case the request is sent, in the result variable the response code contains TRADE_RETCODE_PLACED value (code 10008) – "order placed". /// Successful execution means only the fact of sending, but does not give any guarantee that the request has reached the trade server and has been accepted for processing. /// When processing the received request, a trade server sends a reply to a client terminal notifying of change in the current state of positions, /// orders and deals, which leads to the generation of the Trade event. /// public bool OrderSendAsync(MqlTradeRequest request, out MqlTradeResult? result) { Log.Debug($"OrderSend: request = {request}"); if (request == null) { Log.Warn("OrderSend: request is not defined!"); result = null; return false; } Dictionary commandParameters = new() { { "TradeRequest", request } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.OrderSendAsync, commandParameters); result = response?.Result; return response != null && response.RetVal; } /// ///The function calculates the margin required for the specified order type, on the current account ///, in the current market environment not taking into account current pending orders and open positions ///. It allows the evaluation of margin for the trade operation planned. The value is returned in the account currency. /// ///The order type, can be one of the values of the ENUM_ORDER_TYPE enumeration. ///Symbol name. ///Volume of the trade operation. ///Open price. ///The variable, to which the value of the required margin will be written in case the function is successfully executed ///. The calculation is performed as if there were no pending orders and open positions on the current account ///. The margin value depends on many factors, and can differ in different market environments. /// /// The function returns true in case of success; otherwise it returns false. /// public bool OrderCalcMargin(ENUM_ORDER_TYPE action, string symbol, double volume, double price, out double margin) { Dictionary cmdParams = new() { { "Action", (int)action }, { "Symbol", symbol }, { "Volume", volume }, { "Price", price } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.OrderCalcMargin, cmdParams); margin = response != null ? response.Result : double.NaN; return response != null && response.RetVal; } /// ///The function calculates the profit for the current account, ///in the current market conditions, based on the parameters passed. ///The function is used for pre-evaluation of the result of a trade operation. ///The value is returned in the account currency. /// ///Type of the order, can be one of the two values of the ENUM_ORDER_TYPE enumeration: ORDER_TYPE_BUY or ORDER_TYPE_SELL. ///Symbol name. ///Volume of the trade operation. ///Open price. ///Close price. ///The variable, to which the calculated value of the profit will be written in case the function is successfully executed. ///The estimated profit value depends on many factors, and can differ in different market environments. /// /// The function returns true in case of success; otherwise it returns false. If an invalid order type is specified, the function will return false. /// public bool OrderCalcProfit(ENUM_ORDER_TYPE action, string symbol, double volume, double priceOpen, double priceClose, out double profit) { Dictionary cmdParams = new() { { "Action", (int)action }, { "Symbol", symbol ?? string.Empty }, { "Volume", volume }, { "PriceOpen", priceOpen }, { "PriceClose", priceClose} }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.OrderCalcProfit, cmdParams); profit = response != null ? response.Result : double.NaN; return response != null && response.RetVal; } /// ///The OrderCheck() function checks if there are enough money to execute a required trade operation. ///The check results are placed to the fields of the MqlTradeCheckResult structure. /// ///Reference to a object of MqlTradeRequest type describing the trade activity of the client. /// Reference to the object of the MqlTradeCheckResult type, to which the check result will be placed. /// /// If funds are not enough for the operation, or parameters are filled out incorrectly, the function returns false. /// In case of a successful basic check of structures (check of pointers), it returns true. /// However, this is not an indication that the requested trade operation is sure to be successfully executed. /// For a more detailed description of the function execution result, analyze the fields of the result structure. /// public bool OrderCheck(MqlTradeRequest request, out MqlTradeCheckResult? result) { Log.Debug($"OrderCheck: request = {request}"); if (request == null) { Log.Warn("OrderCheck: request is not defined!"); result = null; return false; } Dictionary commandParameters = new() { { "TradeRequest", request } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.OrderCheck, commandParameters); result = response?.Result; return response != null && response.RetVal; } /// ///Returns the number of open positions. /// public int PositionsTotal() { return SendCommand(ExecutorHandle, Mt5CommandType.PositionsTotal); } /// ///Returns the symbol corresponding to the open position and automatically selects the position for further working with it using functions PositionGetDouble, PositionGetInteger, PositionGetString. /// ///Number of the position in the list of open positions. public string? PositionGetSymbol(int index) { Dictionary commandParameters = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionGetSymbol, commandParameters); } /// ///Chooses an open position for further working with it. Returns true if the function is successfully completed. Returns false in case of failure. /// ///Name of the financial security. public bool PositionSelect(string symbol) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionSelect, cmdParams); } /// ///Selects an open position to work with based on the ticket number specified in the position. If successful, returns true. Returns false if the function failed. /// ///Position ticket. public bool PositionSelectByTicket(ulong ticket) { Dictionary cmdParams = new() { { "Ticket", ticket } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionSelectByTicket, cmdParams); } /// ///The function returns the requested property of an open position, pre-selected using PositionGetSymbol or PositionSelect. /// ///Identifier of a position property. public double PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionGetDouble, cmdParams); } /// ///The function returns the requested property of an open position, pre-selected using PositionGetSymbol or PositionSelect. /// ///Identifier of a position property. public long PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionGetInteger, cmdParams); } /// ///The function returns the requested property of an open position, pre-selected using PositionGetSymbol or PositionSelect. /// ///Identifier of a position property. public string? PositionGetString(ENUM_POSITION_PROPERTY_STRING propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionGetString, cmdParams); } /// ///The function returns the ticket of a position with the specified index in the list of open positions and automatically selects the position to work with using functions PositionGetDouble, PositionGetInteger, PositionGetString. /// ///Identifier of a position property. public ulong PositionGetTicket(int index) { Dictionary cmdParams = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionGetTicket, cmdParams); } /// ///Returns the number of current orders. /// public int OrdersTotal() { return SendCommand(ExecutorHandle, Mt5CommandType.OrdersTotal); } /// ///Returns the number of current orders. /// ///Number of an order in the list of current orders. public ulong OrderGetTicket(int index) { Dictionary cmdParams = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.OrderGetTicket, cmdParams); } /// ///Selects an order to work with. Returns true if the function has been successfully completed. /// ///Order ticket. public bool OrderSelect(ulong ticket) { Dictionary cmdParams = new() { { "Ticket", ticket } }; return SendCommand(ExecutorHandle, Mt5CommandType.OrderSelect, cmdParams); } /// ///Returns the requested property of an order, pre-selected using OrderGetTicket or OrderSelect. /// /// Identifier of the order property. public double OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.OrderGetDouble, cmdParams); } /// ///Returns the requested property of an order, pre-selected using OrderGetTicket or OrderSelect. /// /// Identifier of the order property. public long OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.OrderGetInteger, cmdParams); } /// ///Returns the requested property of an order, pre-selected using OrderGetTicket or OrderSelect. /// /// Identifier of the order property. public string? OrderGetString(ENUM_ORDER_PROPERTY_STRING propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.OrderGetString, cmdParams); } /// ///Retrieves the history of deals and orders for the specified period of server time. /// ///Start date of the request. ///End date of the request. public bool HistorySelect(DateTime fromDate, DateTime toDate) { Dictionary cmdParams = new() { { "FromDate", Mt5TimeConverter.ConvertToMtTime(fromDate) }, { "ToDate", Mt5TimeConverter.ConvertToMtTime(toDate) } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistorySelect, cmdParams); } /// ///Retrieves the history of deals and orders having the specified position identifier. /// ///Position identifier that is set to every executed order and every deal. public bool HistorySelectByPosition(long positionId) { Dictionary cmdParams = new() { { "PositionId", positionId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistorySelectByPosition, cmdParams); } /// ///Selects an order from the history for further calling it through appropriate functions. /// ///Order ticket. public bool HistoryOrderSelect(ulong ticket) { Dictionary cmdParams = new() { { "Ticket", ticket } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrderSelect, cmdParams); } /// ///Returns the number of orders in the history. /// public int HistoryOrdersTotal() { return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrdersTotal); } /// ///Return the ticket of a corresponding order in the history. /// ///Number of the order in the list of orders. public ulong HistoryOrderGetTicket(int index) { Dictionary cmdParams = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrderGetTicket, cmdParams); } /// ///Returns the requested order property. /// ///Order ticket. ///Identifier of the order property. public double HistoryOrderGetDouble(ulong ticketNumber, ENUM_ORDER_PROPERTY_DOUBLE propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrderGetDouble, cmdParams); } /// ///Returns the requested property of an order. /// ///Order ticket. ///Identifier of the order property. public long HistoryOrderGetInteger(ulong ticketNumber, ENUM_ORDER_PROPERTY_INTEGER propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrderGetInteger, cmdParams); } /// ///Returns the requested property of an order. /// ///Order ticket. ///Identifier of the order property. public string? HistoryOrderGetString(ulong ticketNumber, ENUM_ORDER_PROPERTY_STRING propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryOrderGetString, cmdParams); } /// ///Selects a deal in the history for further calling it through appropriate functions. /// ///Deal ticket. public bool HistoryDealSelect(ulong ticket) { Dictionary cmdParams = new() { { "Ticket", ticket } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealSelect, cmdParams); } /// ///Returns the number of deal in history. /// public int HistoryDealsTotal() { return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealsTotal); } /// ///The function selects a deal for further processing and returns the deal ticket in history. /// ///Number of a deal in the list of deals. public ulong HistoryDealGetTicket(int index) { Dictionary cmdParams = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealGetTicket, cmdParams); } /// ///Returns the requested property of a deal. /// ///Deal ticket. /// Identifier of a deal property. public double HistoryDealGetDouble(ulong ticketNumber, ENUM_DEAL_PROPERTY_DOUBLE propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealGetDouble, cmdParams); } /// ///Returns the requested property of a deal. /// ///Deal ticket. /// Identifier of a deal property. public long HistoryDealGetInteger(ulong ticketNumber, ENUM_DEAL_PROPERTY_INTEGER propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealGetInteger, cmdParams); } /// ///Returns the requested property of a deal. /// ///Deal ticket. /// Identifier of a deal property. public string? HistoryDealGetString(ulong ticketNumber, ENUM_DEAL_PROPERTY_STRING propertyId) { Dictionary cmdParams = new() { { "TicketNumber", ticketNumber }, { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.HistoryDealGetString, cmdParams); } /// ///Close all open positions. /// [Obsolete("OrderCloseAll is deprecated, please use PositionCloseAll instead.")] public bool OrderCloseAll() { return SendCommand(ExecutorHandle, Mt5CommandType.OrderCloseAll); } /// ///Close all open positions. Returns count of closed positions. /// public int PositionCloseAll() { return SendCommand(ExecutorHandle, Mt5CommandType.PositionCloseAll); } /// ///Closes a position with the specified ticket. /// ///Ticket of the closed position. ///Maximal deviation from the current price (in points). public bool PositionClose(ulong ticket, ulong deviation = ulong.MaxValue) { return PositionClose(ticket, deviation, out MqlTradeResult? result); } /// /// Modifies existing position /// /// >Ticket of the position /// Stop loss /// Take profit /// public bool PositionModify(ulong ticket, double sl, double tp) { Dictionary cmdParams = new() { { "Ticket", ticket }, { "Sl", sl }, { "Tp", tp } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionModify, cmdParams); } /// ///Closes a position with the specified ticket. /// ///Ticket of the closed position. ///Maximal deviation from the current price (in points). /// output result public bool PositionClose(ulong ticket, ulong deviation, out MqlTradeResult? result) { Dictionary cmdParams = new() { { "Ticket", ticket }, { "Deviation", deviation } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.PositionClose, cmdParams); result = response?.Result; return response != null && response.RetVal; } /// ///Closes a position with the specified ticket. /// ///Ticket of the closed position. /// output result public bool PositionClose(ulong ticket, out MqlTradeResult? result) { return PositionClose(ticket, ulong.MaxValue, out result); } /// /// Opens a position with the specified parameters. /// /// symbol /// order type to open position /// position volume /// execution price /// Stop Loss price /// Take Profit price /// comment /// true - successful check of the basic structures, otherwise - false. public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment = "") { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "OrderType", (int)orderType }, { "Volume", volume }, { "Price", price }, { "Sl", sl }, { "Tp", tp }, { "Comment", comment ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionOpen, cmdParams); } /// /// Opens a position with the specified parameters. /// /// symbol /// order type to open position /// position volume /// execution price /// Stop Loss price /// Take Profit price /// comment /// output result /// true - successful check of the basic structures, otherwise - false. public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string? comment, out MqlTradeResult? result) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty}, { "OrderType", (int)orderType }, { "Volume", volume }, { "Price", price }, { "Sl", sl }, { "Tp", tp } }; if (comment != null) cmdParams["Comment"] = comment; var response = SendCommand>(ExecutorHandle, Mt5CommandType.PositionOpen2, cmdParams); result = response?.Result; return response != null && response.RetVal; } /// /// Opens a position with the specified parameters. /// /// symbol /// order type to open position /// position volume /// execution price /// Stop Loss price /// Take Profit price /// output result /// true - successful check of the basic structures, otherwise - false. public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, out MqlTradeResult? result) { return PositionOpen(symbol, orderType, volume, price, sl, tp, "", out result); } /// /// Partially closes a position on a specified symbol in case of a "hedging" accounting. /// /// Name of a trading instrument, on which a position is closed partially. /// Volume, by which a position should be decreased. If the value exceeds the volume of a partially closed position, it is closed in full. No position in the opposite direction is opened. /// The maximum deviation from the current price (in points). /// true if the basic check of structures is successful, otherwise false. public bool PositionClosePartial(string symbol, double volume, ulong deviation = ulong.MaxValue) { Dictionary cmdParams = new() { { "Symbol", symbol }, { "Volume", volume }, { "Deviation", deviation} }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionClosePartial_bySymbol, cmdParams); } /// /// Partially closes a position on a specified symbol in case of a "hedging" accounting. /// /// Closed position ticket. /// Volume, by which a position should be decreased. If the value exceeds the volume of a partially closed position, it is closed in full. No position in the opposite direction is opened. /// The maximum deviation from the current price (in points). /// true if the basic check of structures is successful, otherwise false. public bool PositionClosePartial(ulong ticket, double volume, ulong deviation = ulong.MaxValue) { Dictionary cmdParams = new() { { "Ticket", ticket }, { "Volume", volume }, { "Deviation", deviation} }; return SendCommand(ExecutorHandle, Mt5CommandType.PositionClosePartial_byTicket, cmdParams); } /// /// Opens a long position with specified parameters with current market Ask price /// /// output result /// Requested position volume. /// Position symbol. If it is not specified, the current symbol will be used. /// Execution price. /// Stop Loss price. /// Take Profit price. /// Comment. /// true - successful check of the structures, otherwise - false. public bool Buy(out MqlTradeResult? result, double volume, string? symbol = null, double price = 0.0, double sl = 0.0, double tp = 0.0, string? comment = null) { Dictionary cmdParams = new() { { "Volume", volume }, { "Price", price }, { "Sl", sl }, { "Tp", tp } }; if (symbol != null) cmdParams["Symbol"] = symbol; if (comment != null) cmdParams["Comment"] = comment; var response = SendCommand>(ExecutorHandle, Mt5CommandType.Buy, cmdParams); result = response?.Result; return response != null && response.RetVal; } /// /// Opens a short position with specified parameters with current market Bid price /// /// output result /// Requested position volume. /// Position symbol. If it is not specified, the current symbol will be used. /// Execution price. /// Stop Loss price. /// Take Profit price. /// Comment. /// true - successful check of the structures, otherwise - false. public bool Sell(out MqlTradeResult? result, double volume, string? symbol = null, double price = 0.0, double sl = 0.0, double tp = 0.0, string? comment = null) { Dictionary cmdParams = new() { { "Volume", volume }, { "Price", price }, { "Sl", sl }, { "Tp", tp } }; if (symbol != null) cmdParams["Symbol"] = symbol; if (comment != null) cmdParams["Comment"] = comment; var response = SendCommand>(ExecutorHandle, Mt5CommandType.Sell, cmdParams); result = response?.Result; return response != null && response.RetVal; } #endregion #region Account Information functions /// ///Returns the value of the corresponding account property. /// ///Identifier of the property. public double AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE propertyId) { Dictionary cmdParams = new() { { "PropertyId", propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.AccountInfoDouble, cmdParams); } /// ///Returns the value of the corresponding account property. /// ///Identifier of the property. public long AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER propertyId) { Dictionary cmdParams = new() { { "PropertyId", propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.AccountInfoInteger, cmdParams); } /// ///Returns the value of the corresponding account property. /// ///Identifier of the property. public string? AccountInfoString(ENUM_ACCOUNT_INFO_STRING propertyId) { Dictionary cmdParams = new() { { "PropertyId", propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.AccountInfoString, cmdParams); } #endregion #region Timeseries and Indicators Access /// ///Returns information about the state of historical data. /// ///Symbol name. /// Period. ///Identifier of the requested property, value of the ENUM_SERIES_INFO_INTEGER enumeration. public long SeriesInfoInteger(string symbolName, ENUM_TIMEFRAMES timeframe, ENUM_SERIES_INFO_INTEGER propId) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.SeriesInfoInteger, cmdParams); } /// ///Returns the number of bars count in the history for a specified symbol and period. /// ///Symbol name. /// Period. public int Bars(string symbolName, ENUM_TIMEFRAMES timeframe) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe } }; return SendCommand(ExecutorHandle, Mt5CommandType.Bars, cmdParams); } /// ///Returns the number of bars count in the history for a specified symbol and period. /// ///Symbol name. ///Period. ///Bar time corresponding to the first element. ///Bar time corresponding to the last element. public int Bars(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime)} }; return SendCommand(ExecutorHandle, Mt5CommandType.Bars2, cmdParams); } /// ///Returns the number of calculated data for the specified indicator. /// ///The indicator handle, returned by the corresponding indicator function. public int BarsCalculated(int indicatorHandle) { Dictionary cmdParams = new() { { "IndicatorHandle", indicatorHandle } }; return SendCommand(ExecutorHandle, Mt5CommandType.BarsCalculated, cmdParams); } /// ///Gets data of a specified buffer of a certain indicator in the necessary quantity. /// ///The indicator handle, returned by the corresponding indicator function. ///The indicator buffer number. ///The position of the first element to copy. ///Data count to copy. ///Array of double type. public int CopyBuffer(int indicatorHandle, int bufferNum, int startPos, int count, out double[] buffer) { Dictionary cmdParams = new() { { "IndicatorHandle", indicatorHandle }, { "BufferNum", bufferNum }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyBuffer, cmdParams); buffer = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///Gets data of a specified buffer of a certain indicator in the necessary quantity. /// ///The indicator handle, returned by the corresponding indicator function. ///The indicator buffer number. ///Bar time, corresponding to the first element. ///Data count to copy. ///Array of double type. public int CopyBuffer(int indicatorHandle, int bufferNum, DateTime startTime, int count, out double[] buffer) { Dictionary cmdParams = new() { { "IndicatorHandle", indicatorHandle }, { "BufferNum", bufferNum }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyBuffer1, cmdParams); buffer = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///Gets data of a specified buffer of a certain indicator in the necessary quantity. /// ///The indicator handle, returned by the corresponding indicator function. ///The indicator buffer number. ///Bar time, corresponding to the first element. ///Bar time, corresponding to the last element. ///Array of double type. public int CopyBuffer(int indicatorHandle, int bufferNum, DateTime startTime, DateTime stopTime, out double[] buffer) { Dictionary cmdParams = new() { { "IndicatorHandle", indicatorHandle }, { "BufferNum", bufferNum }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyBuffer2, cmdParams); buffer = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///Gets history data of MqlRates structure of a specified symbol-period in specified quantity into the ratesArray array. The elements ordering of the copied data is from present to the past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of MqlRates type. public int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out MqlRates[]? ratesArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRates, cmdParams); ratesArray = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///Gets history data of MqlRates structure of a specified symbol-period in specified quantity into the ratesArray array. The elements ordering of the copied data is from present to the past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of MqlRates type. public int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out MqlRates[]? ratesArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRates1, cmdParams); ratesArray = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///Gets history data of MqlRates structure of a specified symbol-period in specified quantity into the ratesArray array. The elements ordering of the copied data is from present to the past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Bar time, corresponding to the last element to copy. ///Array of MqlRates type. public int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out MqlRates[]? ratesArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRates2, cmdParams); ratesArray = response?.ToArray() ?? []; return response?.Count ?? 0; } /// ///The function gets to time_array history data of bar opening time for the specified symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of DatetTme type. public int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out DateTime[]? timeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTime, cmdParams); if (response != null) { timeArray = new DateTime[response.Count]; for (var i = 0; i < response.Count; i++) timeArray[i] = Mt5TimeConverter.ConvertFromMtTime(response[i]); } else timeArray = []; return response?.Count ?? 0; } /// ///The function gets to time_array history data of bar opening time for the specified symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of DatetTme type. public int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out DateTime[]? timeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTime1, cmdParams); if (response != null) { timeArray = new DateTime[response.Count]; for (var i = 0; i < response.Count; i++) timeArray[i] = Mt5TimeConverter.ConvertFromMtTime(response[i]); } else timeArray = []; return response?.Count ?? 0; } /// ///The function gets to time_array history data of bar opening time for the specified symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Bar time corresponding to the last element to copy. ///Array of DatetTme type. public int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out DateTime[]? timeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTime2, cmdParams); if (response != null) { timeArray = new DateTime[response.Count]; for (var i = 0; i < response.Count; i++) timeArray[i] = Mt5TimeConverter.ConvertFromMtTime(response[i]); } else timeArray = []; return response?.Count ?? 0; } /// ///The function gets into open_array the history data of bar open prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] openArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyOpen, cmdParams); openArray = response != null ? response.ToArray() : []; return openArray?.Length ?? 0; } /// ///The function gets into open_array the history data of bar open prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] openArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyOpen1, cmdParams); openArray = response != null ? response.ToArray() : []; return openArray?.Length ?? 0; } /// ///The function gets into open_array the history data of bar open prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of double type. public int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] openArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyOpen2, cmdParams); openArray = response != null ? response.ToArray() : []; return openArray?.Length ?? 0; } /// ///The function gets into high_array the history data of highest bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] highArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyHigh, cmdParams); highArray = response != null ? response.ToArray() : []; return highArray?.Length ?? 0; } /// ///The function gets into high_array the history data of highest bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] highArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyHigh1, cmdParams); highArray = response != null ? response.ToArray() : []; return highArray?.Length ?? 0; } /// ///The function gets into high_array the history data of highest bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of double type. public int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] highArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyHigh2, cmdParams); highArray = response != null ? response.ToArray() : []; return highArray?.Length ?? 0; } /// ///The function gets into low_array the history data of minimal bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] lowArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyLow, cmdParams); lowArray = response != null ? response.ToArray() : []; return lowArray?.Length ?? 0; } /// ///The function gets into low_array the history data of minimal bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] lowArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyLow1, cmdParams); lowArray = response != null ? response.ToArray() : []; return lowArray?.Length ?? 0; } /// ///The function gets into low_array the history data of minimal bar prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of double type. public int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] lowArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyLow2, cmdParams); lowArray = response != null ? response.ToArray() : []; return lowArray?.Length ?? 0; } /// ///The function gets into close_array the history data of bar close prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] closeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyClose, cmdParams); closeArray = response != null ? response.ToArray() : []; return closeArray?.Length ?? 0; } /// ///The function gets into close_array the history data of bar close prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of double type. public int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] closeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyClose1, cmdParams); closeArray = response != null ? response.ToArray() : []; return closeArray?.Length ?? 0; } /// ///The function gets into close_array the history data of bar close prices for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of double type. public int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] closeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyClose2, cmdParams); closeArray = response != null ? response.ToArray() : []; return closeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of tick volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of long type. public int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTickVolume, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of tick volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of long type. public int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTickVolume1, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of tick volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of long type. public int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTickVolume2, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of trade volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of long type. public int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRealVolume, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of trade volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of long type. public int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRealVolume1, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into volume_array the history data of trade volumes for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of long type. public int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out long[] volumeArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyRealVolume2, cmdParams); volumeArray = response != null ? response.ToArray() : []; return volumeArray?.Length ?? 0; } /// ///The function gets into spread_array the history data of spread values for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start position for the first element to copy. ///Data count to copy. ///Array of long type. public int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out int[] spreadArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartPos", startPos }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopySpread, cmdParams); spreadArray = response != null ? response.ToArray() : []; return spreadArray?.Length ?? 0; } /// ///The function gets into spread_array the history data of spread values for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///Data count to copy. ///Array of long type. public int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out int[] spreadArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopySpread1, cmdParams); spreadArray = response != null ? response.ToArray() : []; return spreadArray?.Length ?? 0; } /// ///The function gets into spread_array the history data of spread values for the selected symbol-period pair in the specified quantity. It should be noted that elements ordering is from present to past, i.e., starting position of 0 means the current bar. /// ///Symbol name. ///Period. ///The start time for the first element to copy. ///The start time for the last element to copy. ///Array of long type. public int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out int[] spreadArray) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Timeframe", (int)timeframe }, { "StartTime", Mt5TimeConverter.ConvertToMtTime(startTime) }, { "StopTime", Mt5TimeConverter.ConvertToMtTime(stopTime) } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopySpread2, cmdParams); spreadArray = response != null ? response.ToArray() : []; return spreadArray?.Length ?? 0; } /// ///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. /// ///Symbol name. ///The flag that determines the type of received ticks. ///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. ///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. /// public List? CopyTicks(string symbolName, CopyTicksFlag flags = CopyTicksFlag.All, ulong from = 0, uint count = 0) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Flags", flags }, { "From", from }, { "Count", count } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.CopyTicks, cmdParams); List? ticks = response?.Select(t => new MqlTick(t)).ToList(); return ticks; } /// ///The function returns the handle of a specified technical indicator created based on the array of parameters of MqlParam type. /// ///Name of a symbol, on data of which the indicator is calculated. NULL means the current symbol. ///The value of the timeframe can be one of values of the ENUM_TIMEFRAMES enumeration, 0 means the current timeframe. ///Indicator type, can be one of values of the ENUM_INDICATOR enumeration. ///An array of MqlParam type, whose elements contain the type and value of each input parameter of a technical indicator. public int IndicatorCreate(string? symbol, ENUM_TIMEFRAMES period, ENUM_INDICATOR indicatorType, List? parameters = null) { Dictionary cmdParams = new() { { "Period", (int)period }, { "IndicatorType", (int)indicatorType } }; if (symbol != null) cmdParams["Symbol"] = symbol; if (parameters != null) cmdParams["Parameters"] = parameters; return SendCommand(ExecutorHandle, Mt5CommandType.IndicatorCreate, cmdParams); } public bool IndicatorRelease(int indicatorHandle) { Dictionary cmdParams = new() { { "IndicatorHandle", indicatorHandle } }; return SendCommand(ExecutorHandle, Mt5CommandType.IndicatorRelease, cmdParams); } #endregion #region Market Info /// ///Returns the number of available (selected in Market Watch or all) symbols. /// ///Request mode. Can be true or false. public int SymbolsTotal(bool selected) { Dictionary cmdParams = new() { { "Selected", selected } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolsTotal, cmdParams); } /// ///Returns the name of a symbol. /// ///Order number of a symbol. ///Request mode. If the value is true, the symbol is taken from the list of symbols selected in MarketWatch. If the value is false, the symbol is taken from the general list. public string? SymbolName(int pos, bool selected) { Dictionary cmdParams = new() { { "Pos", pos }, { "Selected", selected } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolName, cmdParams); } /// ///Selects a symbol in the Market Watch window or removes a symbol from the window. /// ///Symbol name. ///Switch. If the value is false, a symbol should be removed from MarketWatch, otherwise a symbol should be selected in this window. A symbol can't be removed if the symbol chart is open, or there are open positions for this symbol. public bool SymbolSelect(string symbolName, bool selected) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "Selected", selected } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolSelect, cmdParams); } /// ///The function checks whether data of a selected symbol in the terminal are synchronized with data on the trade server. /// ///Symbol name. public bool SymbolIsSynchronized(string symbolName) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolIsSynchronized, cmdParams); } /// ///Returns the corresponding property of a specified symbol. /// ///Symbol name. ///Identifier of a symbol property. public double SymbolInfoDouble(string symbolName, ENUM_SYMBOL_INFO_DOUBLE propId) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolInfoDouble, cmdParams); } /// ///Returns the corresponding property of a specified symbol. /// ///Symbol name. ///Identifier of a symbol property. public long SymbolInfoInteger(string symbolName, ENUM_SYMBOL_INFO_INTEGER propId) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.SymbolInfoInteger, cmdParams); } /// ///Returns the corresponding property of a specified symbol. /// ///Symbol name. ///Identifier of a symbol property. public string? SymbolInfoString(string symbolName, ENUM_SYMBOL_INFO_STRING propId) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "PropId", (int)propId } }; var response = SendCommand(ExecutorHandle, Mt5CommandType.SymbolInfoString, cmdParams); return response; } /// ///Returns the corresponding property of a specified symbol. /// ///Symbol name. ///Identifier of a symbol property. ///Variable of the string type receiving the value of the requested property. public bool SymbolInfoString(string symbolName, ENUM_SYMBOL_INFO_STRING propId, out string? value) { Dictionary cmdParams = new() { { "Symbol", symbolName ?? string.Empty }, { "PropId", (int)propId } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.SymbolInfoString2, cmdParams); value = response?.Result; return response?.RetVal ?? false; } /// ///The function returns current prices of a specified symbol in a variable of the MqlTick type. ///The function returns true if successful, otherwise returns false. /// ///Symbol name. /// Link to the structure of the MqlTick type, to which the current prices and time of the last price update will be placed. public bool SymbolInfoTick(string symbol, out MqlTick? tick) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.SymbolInfoTick, cmdParams); tick = response != null && response.Result != null ? new MqlTick(response.Result) : null; return response?.RetVal ?? false; } /// ///The function returns current prices of a specified symbol in a variable of the MqlTick type. /// ///Symbol name. public MqlTick? SymbolInfoTick(string symbol) { if (SymbolInfoTick(symbol, out MqlTick? tick)) return tick; return null; } /// ///Allows receiving time of beginning and end of the specified quoting sessions for a specified symbol and weekday. /// ///Symbol name. ///Day of the week ///Ordinal number of a session, whose beginning and end time we want to receive. Indexing of sessions starts with 0. ///Session beginning time in seconds from 00 hours 00 minutes, in the returned value date should be ignored. ///Session end time in seconds from 00 hours 00 minutes, in the returned value date should be ignored. public bool SymbolInfoSessionQuote(string name, ENUM_DAY_OF_WEEK dayOfWeek, uint sessionIndex, out DateTime from, out DateTime to) { Dictionary cmdParams = new() { { "Symbol", name ?? string.Empty }, { "DayOfWeek", dayOfWeek }, { "SessionIndex", sessionIndex } }; var response = SendCommand>>(ExecutorHandle, Mt5CommandType.SymbolInfoSessionQuote, cmdParams); if (response != null && response.Result != null && response.Result.TryGetValue("From", out int mtFrom) && response.Result.TryGetValue("To", out int mtTo)) { from = Mt5TimeConverter.ConvertFromMtTime(mtFrom); to = Mt5TimeConverter.ConvertFromMtTime(mtTo); return response.RetVal; } from = DateTime.MinValue; to = DateTime.MinValue; return false; } /// ///Allows receiving time of beginning and end of the specified trading sessions for a specified symbol and weekday. /// ///Symbol name. ///Day of the week ///Ordinal number of a session, whose beginning and end time we want to receive. Indexing of sessions starts with 0. ///Session beginning time in seconds from 00 hours 00 minutes, in the returned value date should be ignored. ///Session end time in seconds from 00 hours 00 minutes, in the returned value date should be ignored. public bool SymbolInfoSessionTrade(string name, ENUM_DAY_OF_WEEK dayOfWeek, uint sessionIndex, out DateTime from, out DateTime to) { Dictionary cmdParams = new() { { "Symbol", name ?? string.Empty }, { "DayOfWeek", dayOfWeek }, { "SessionIndex", sessionIndex } }; var response = SendCommand>>(ExecutorHandle, Mt5CommandType.SymbolInfoSessionTrade, cmdParams); if (response != null && response.Result != null && response.Result.TryGetValue("From", out int mtFrom) && response.Result.TryGetValue("To", out int mtTo)) { from = Mt5TimeConverter.ConvertFromMtTime(mtFrom); to = Mt5TimeConverter.ConvertFromMtTime(mtTo); return response.RetVal; } from = DateTime.MinValue; to = DateTime.MinValue; return false; } /// ///Provides opening of Depth of Market for a selected symbol, and subscribes for receiving notifications of the DOM changes. /// ///Symbol name. public bool MarketBookAdd(string symbol) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.MarketBookAdd, cmdParams); } /// ///Provides closing of Depth of Market for a selected symbol, and cancels the subscription for receiving notifications of the DOM changes. /// ///Symbol name. public bool MarketBookRelease(string symbol) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.MarketBookRelease, cmdParams); } /// ///Returns a structure array MqlBookInfo containing records of the Depth of Market of a specified symbol. /// ///Symbol name. ///Reference to an array of Depth of Market records. public bool MarketBookGet(string symbol, out MqlBookInfo[]? book) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty } }; var response = SendCommand>(ExecutorHandle, Mt5CommandType.MarketBookGet, cmdParams); book = response?.ToArray(); return response != null; } #endregion #region Chart Operations /// ///Returns the ID of the current chart. /// /// /// Value of long type. /// public long ChartId() { return ChartId(ExecutorHandle); } /// ///Returns the ID of the chart. /// ///Handle of expert linked to the chart. /// /// Value of long type. /// public long ChartId(int expertHandle) { return SendCommand(ExecutorHandle, Mt5CommandType.ChartId, expertHandle); } /// ///This function calls a forced redrawing of a specified chart. /// ///Chart ID. 0 means the current chart. public void ChartRedraw(long chartId = 0) { Dictionary cmdParams = new() { { "ChartId", chartId } }; SendCommand(ExecutorHandle, Mt5CommandType.ChartRedraw, cmdParams); } /// ///Applies a specific template from a specified file to the chart. /// ///Chart ID. ///The name of the file containing the template. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartApplyTemplate(long chartId, string filename) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "TemplateFileName", filename ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartApplyTemplate, cmdParams); } /// ///Saves current chart settings in a template with a specified name. /// ///Chart ID. ///The filename to save the template. The ".tpl" extension will be added to the filename automatically; there is no need to specify it. The template is saved in data_folder\templates\ and can be used for manual application in the terminal. If a template with the same filename already exists, the contents of this file will be overwritten. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartSaveTemplate(long chartId, string filename) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "TemplateFileName", filename ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSaveTemplate, cmdParams); } /// ///The function returns the number of a subwindow where an indicator is drawn. /// ///Chart ID. ///Short name of the indicator. /// ///Subwindow number in case of success. In case of failure the function returns -1. /// public int ChartWindowFind(long chartId, string indicatorShortname) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "IndicatorShortname", indicatorShortname ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartWindowFind, cmdParams); } /// ///The function returns the number of a subwindow where an indicator is drawn. /// ///Chart ID. ///The number of the chart subwindow. 0 means the main chart window. ///The time value on the chart, for which the value in pixels along the X axis will be received. ///The price value on the chart, for which the value in pixels along the Y axis will be received. ///The variable, into which the conversion of time to X will be received. The origin is in the upper left corner of the main chart window. ///The variable, into which the conversion of price to Y will be received. The origin is in the upper left corner of the main chart window. /// ///Subwindow number in case of success. In case of failure the function returns -1. /// public bool ChartTimePriceToXY(long chartId, int subWindow, DateTime? time, double price, out int x, out int y) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "Time", Mt5TimeConverter.ConvertToMtTime(time) }, { "Price", price } }; var response = SendCommand>>(ExecutorHandle, Mt5CommandType.ChartTimePriceToXY, cmdParams); if (response != null && response.Result != null && response.Result.TryGetValue("X", out x) && response.Result.TryGetValue("Y", out y)) return response.RetVal; x = 0; y = 0; return false; } /// ///The function returns the number of a subwindow where an indicator is drawn. /// ///Chart ID. ///The variable, into which the conversion of time to X will be received. The origin is in the upper left corner of the main chart window. ///The variable, into which the conversion of price to Y will be received. The origin is in the upper left corner of the main chart window. ///The number of the chart subwindow. 0 means the main chart window. ///The time value on the chart, for which the value in pixels along the X axis will be received. ///The price value on the chart, for which the value in pixels along the Y axis will be received. /// ///Subwindow number in case of success. In case of failure the function returns -1. /// public bool ChartXYToTimePrice(long chartId, int x, int y, out int subWindow, out DateTime? time, out double price) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "X", x }, { "Y", y } }; var response = SendCommand>>(ExecutorHandle, Mt5CommandType.ChartXYToTimePrice, cmdParams); if (response != null && response.Result != null && response.Result.TryGetValue("SubWindow", out object? mtSubWindow) && response.Result.TryGetValue("Time", out object? mtTime) && response.Result.TryGetValue("Price", out object? mtPrice)) { subWindow = Convert.ToInt32(mtSubWindow); time = Mt5TimeConverter.ConvertFromMtTime(Convert.ToInt32(mtTime)); price = Convert.ToDouble(mtPrice); return response.RetVal; } subWindow = 0; time = null; price = double.NaN; return false; } /// ///Opens a new chart with the specified symbol and period. /// ///Chart symbol. NULL means the symbol of the current chart (the Expert Advisor is attached to). /// Chart period (timeframe). Can be one of the ENUM_TIMEFRAMES values. 0 means the current chart period. /// ///If successful, it returns the opened chart ID. Otherwise returns 0. /// public long ChartOpen(string symbol, ENUM_TIMEFRAMES period) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Timeframe", (int)period } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartOpen, cmdParams); } /// ///Returns the ID of the first chart of the client terminal. /// public long ChartFirst() { return SendCommand(ExecutorHandle, Mt5CommandType.ChartFirst); } /// ///Returns the chart ID of the chart next to the specified one. /// ///Chart ID. 0 does not mean the current chart. 0 means "return the first chart ID". /// ///Chart ID. If this is the end of the chart list, it returns -1. /// public long ChartNext(long chartId) { Dictionary cmdParams = new() { { "ChartId", chartId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartNext, cmdParams); } /// ///Closes the specified chart. /// ///Chart ID. 0 means the current chart. /// ///If successful, returns true, otherwise false. /// public bool ChartClose(long chartId = 0) { Dictionary cmdParams = new() { { "ChartId", chartId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartClose, cmdParams); } /// ///Returns the symbol name for the specified chart. /// ///Chart ID. 0 means the current chart. /// ///If chart does not exist, the result will be an empty string. /// public string? ChartSymbol(long chartId) { Dictionary cmdParams = new() { { "ChartId", chartId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSymbol, cmdParams); } /// ///Returns the timeframe period of specified chart. /// ///Chart ID. 0 means the current chart. /// ///The function returns one of the ENUM_TIMEFRAMES values. If chart does not exist, it returns 0. /// public ENUM_TIMEFRAMES ChartPeriod(long chartId) { Dictionary cmdParams = new() { { "ChartId", chartId } }; return (ENUM_TIMEFRAMES)SendCommand(ExecutorHandle, Mt5CommandType.ChartPeriod, cmdParams); } /// ///Sets a value for a corresponding property of the specified chart. Chart property should be of a double type. /// ///Chart ID. 0 means the current chart. ///Chart property ID. Can be one of the ENUM_CHART_PROPERTY_DOUBLE values (except the read-only properties). ///Property value. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartSetDouble(long chartId, ENUM_CHART_PROPERTY_DOUBLE propId, double value) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId }, { "Value", value } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSetDouble, cmdParams); } /// ///Sets a value for a corresponding property of the specified chart. Chart property must be datetime, int, color, bool or char. /// ///Chart ID. 0 means the current chart. ///Chart property ID. It can be one of the ENUM_CHART_PROPERTY_INTEGER value (except the read-only properties). ///Property value. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartSetInteger(long chartId, ENUM_CHART_PROPERTY_INTEGER propId, long value) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId }, { "Value", value } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSetInteger, cmdParams); } /// ///Sets a value for a corresponding property of the specified chart. Chart property must be of the string type. /// ///Chart ID. 0 means the current chart. ///Chart property ID. Its value can be one of the ENUM_CHART_PROPERTY_STRING values (except the read-only properties). ///Property value string. String length cannot exceed 2045 characters (extra characters will be truncated). /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartSetString(long chartId, ENUM_CHART_PROPERTY_STRING propId, string value) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId }, { "Value", value } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSetString, cmdParams); } /// ///Returns the value of a corresponding property of the specified chart. Chart property must be of double type. /// ///Chart ID. 0 means the current chart. ///Chart property ID. This value can be one of the ENUM_CHART_PROPERTY_DOUBLE values. ///Number of the chart subwindow. For the first case, the default value is 0 (main chart window). The most of the properties do not require a subwindow number. /// ///The value of double type. /// public double ChartGetDouble(long chartId, ENUM_CHART_PROPERTY_DOUBLE propId, int subWindow = 0) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId }, { "SubWindow", subWindow } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartGetDouble, cmdParams); } /// ///Returns the value of a corresponding property of the specified chart. Chart property must be of datetime, int or bool type. /// ///Chart ID. 0 means the current chart. ///Chart property ID. This value can be one of the ENUM_CHART_PROPERTY_INTEGER values. ///Number of the chart subwindow. For the first case, the default value is 0 (main chart window). The most of the properties do not require a subwindow number. /// ///The value of long type. /// public long ChartGetInteger(long chartId, ENUM_CHART_PROPERTY_INTEGER propId, int subWindow = 0) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId }, { "SubWindow", subWindow } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartGetInteger, cmdParams); } /// ///Returns the value of a corresponding property of the specified chart. Chart property must be of string type. /// ///Chart ID. 0 means the current chart. ///Chart property ID. This value can be one of the ENUM_CHART_PROPERTY_STRING values. /// ///The value of string type. /// public string? ChartGetString(long chartId, ENUM_CHART_PROPERTY_STRING propId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartGetString, cmdParams); } /// ///Performs shift of the specified chart by the specified number of bars relative to the specified position in the chart. /// ///Chart ID. 0 means the current chart. ///Chart position to perform a shift. Can be one of the ENUM_CHART_POSITION values. ///Number of bars to shift the chart. Positive value means the right shift (to the end of chart), negative value means the left shift (to the beginning of chart). The zero shift can be used to navigate to the beginning or end of chart. /// ///Returns true if successful, otherwise returns false. /// public bool ChartNavigate(long chartId, ENUM_CHART_POSITION position, int shift = 0) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Position", (int)position }, { "Shift", shift } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartNavigate, cmdParams); } /// ///Adds an indicator with the specified handle into a specified chart window. Indicator and chart should be generated on the same symbol and time frame. /// ///Chart ID. 0 means the current chart. ///Number of the chart subwindow. 0 denotes the main chart subwindow. ///The handle of the indicator. /// ///The function returns true in case of success, otherwise it returns false. /// public bool ChartIndicatorAdd(long chartId, int subWindow, int indicatorHandle) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "IndicatorHandle", indicatorHandle } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartIndicatorAdd, cmdParams); } /// ///Removes an indicator with a specified name from the specified chart window. /// ///Chart ID. 0 means the current chart. ///Number of the chart subwindow. 0 denotes the main chart subwindow. ///The short name of the indicator which is set in the INDICATOR_SHORTNAME property with the IndicatorSetString() function. To get the short name of an indicator use the ChartIndicatorName() function. /// ///Returns true in case of successful deletion of the indicator. /// public bool ChartIndicatorDelete(long chartId, int subWindow, string indicatorShortname) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "IndicatorShortname", indicatorShortname ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartIndicatorDelete, cmdParams); } /// ///Returns the handle of the indicator with the specified short name in the specified chart window. /// ///Chart ID. 0 means the current chart. ///Number of the chart subwindow. 0 denotes the main chart subwindow. ///The short name of the indicator which is set in the INDICATOR_SHORTNAME property with the IndicatorSetString() function. To get the short name of an indicator use the ChartIndicatorName() function. /// ///Returns an indicator handle if successful, otherwise returns INVALID_HANDLE. /// public int ChartIndicatorGet(long chartId, int subWindow, string indicatorShortname) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "IndicatorShortname", indicatorShortname ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartIndicatorGet, cmdParams); } /// ///Returns the short name of the indicator by the number in the indicators list on the specified chart window. /// ///Chart ID. 0 means the current chart. ///Number of the chart subwindow. 0 denotes the main chart subwindow. ///the index of the indicator in the list of indicators. The numeration of indicators start with zero, i.e. the first indicator in the list has the 0 index. To obtain the number of indicators in the list use the ChartIndicatorsTotal() function. /// ///The short name of the indicator which is set in the INDICATOR_SHORTNAME property with the IndicatorSetString() function. /// public string? ChartIndicatorName(long chartId, int subWindow, int index) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartIndicatorName, cmdParams); } /// ///Returns the number of all indicators applied to the specified chart window. /// ///Chart ID. 0 means the current chart. ///Number of the chart subwindow. 0 denotes the main chart subwindow. /// ///The number of indicators in the specified chart window. /// public int ChartIndicatorsTotal(long chartId, int subWindow) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartIndicatorsTotal, cmdParams); } /// ///Returns the number (index) of the chart subwindow the Expert Advisor or script has been dropped to. 0 means the main chart window. /// public int ChartWindowOnDropped() { return SendCommand(ExecutorHandle, Mt5CommandType.ChartWindowOnDropped); } /// ///Returns the price coordinate corresponding to the chart point the Expert Advisor or script has been dropped to. /// public double ChartPriceOnDropped() { return SendCommand(ExecutorHandle, Mt5CommandType.ChartPriceOnDropped); } /// ///Returns the time coordinate corresponding to the chart point the Expert Advisor or script has been dropped to. /// public DateTime ChartTimeOnDropped() { var res = SendCommand(ExecutorHandle, Mt5CommandType.ChartTimeOnDropped); return Mt5TimeConverter.ConvertFromMtTime(res); } /// ///Returns the X coordinate of the chart point the Expert Advisor or script has been dropped to. /// public int ChartXOnDropped() { return SendCommand(ExecutorHandle, Mt5CommandType.ChartXOnDropped); } /// ///Returns the Y coordinateof the chart point the Expert Advisor or script has been dropped to. /// public int ChartYOnDropped() { return SendCommand(ExecutorHandle, Mt5CommandType.ChartYOnDropped); } /// ///Changes the symbol and period of the specified chart. The function is asynchronous, i.e. it sends the command and does not wait for its execution completion. /// ///Chart ID. 0 means the current chart. ///Chart symbol. NULL value means the current chart symbol (Expert Advisor is attached to) ///Chart period (timeframe). Can be one of the ENUM_TIMEFRAMES values. 0 means the current chart period. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartSetSymbolPeriod(long chartId, string symbol, ENUM_TIMEFRAMES period) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Symbol", symbol ?? string.Empty }, { "Period", (int)period } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartSetSymbolPeriod, cmdParams); } /// ///Saves current chart screen shot as a GIF, PNG or BMP file depending on specified extension. /// ///Chart ID. 0 means the current chart. ///Screenshot file name. Cannot exceed 63 characters. Screenshot files are placed in the \Files directory. ///Screenshot width in pixels. ///Screenshot height in pixels. ///Output mode of a narrow screenshot. /// ///Returns true if the command has been added to chart queue, otherwise false. /// public bool ChartScreenShot(long chartId, string filename, int width, int height, ENUM_ALIGN_MODE alignMode = ENUM_ALIGN_MODE.ALIGN_RIGHT) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Filename", filename ?? string.Empty }, { "Width", width }, { "Height", height }, { "AlignMode", (int)alignMode } }; return SendCommand(ExecutorHandle, Mt5CommandType.ChartScreenShot, cmdParams); } #endregion #region Commands of Terminal /// ///Returns the value of a corresponding property of the mql5 program environment. /// ///Identifier of a property. Can be one of the values of the ENUM_TERMINAL_INFO_STRING enumeration. /// ///Value of string type. /// public string? TerminalInfoString(ENUM_TERMINAL_INFO_STRING propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.TerminalInfoString, cmdParams); } /// ///Returns the value of a corresponding property of the mql5 program environment. /// ///Identifier of a property. Can be one of the values of the ENUM_TERMINAL_INFO_INTEGER enumeration. /// ///Value of int type. /// public int TerminalInfoInteger(ENUM_TERMINAL_INFO_INTEGER propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.TerminalInfoInteger, cmdParams); } /// ///Returns the value of a corresponding property of the mql5 program environment. /// ///Identifier of a property. Can be one of the values of the ENUM_TERMINAL_INFO_DOUBLE enumeration. /// ///Value of double type. /// public double TerminalInfoDouble(ENUM_TERMINAL_INFO_DOUBLE propertyId) { Dictionary cmdParams = new() { { "PropertyId", (int)propertyId } }; return SendCommand(ExecutorHandle, Mt5CommandType.TerminalInfoDouble, cmdParams); } #endregion #region Common Functions /// ///It enters a message in the Expert Advisor /// ///Message public bool Print(string message) { Dictionary cmdParams = new() { { "PrintMsg", message ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.Print, cmdParams); } /// ///Displays a message in a separate window. /// ///Message public void Alert(string message) { Dictionary cmdParams = new() { { "Message", message ?? string.Empty } }; SendCommand(ExecutorHandle, Mt5CommandType.Alert, cmdParams); } /// ///Gives program operation completion command when testing. /// public void TesterStop() { SendCommand(ExecutorHandle, Mt5CommandType.TesterStop); } #endregion // Common Functions #region Object Functions /// ///The function creates an object with the specified name, type, and the initial coordinates in the specified chart subwindow. /// ///Chart identifier. 0 means the current chart. ///Name of the object. The name must be unique within a chart, including its subwindows. ///Object type. The value can be one of the values of the ENUM_OBJECT enumeration. ///Number of the chart subwindow. 0 means the main chart window. The specified subwindow must exist, otherwise the function returns false. ///The time coordinate of the first anchor. ///The price coordinate of the first anchor point. ///List of further anchor points (tuple of time and price). public bool ObjectCreate(long chartId, string name, ENUM_OBJECT type, int nwin, DateTime time, double price, List>? listOfCoordinates = null) { //Count the additional coordinates int iAdditionalCoordinates = (listOfCoordinates != null) ? listOfCoordinates.Count : 0; if(iAdditionalCoordinates > 29) throw new ArgumentOutOfRangeException(nameof(listOfCoordinates), "The maximum amount of coordinates in 30."); Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "Type", (int)type }, { "Nwin", nwin } }; List times = []; List prices = []; if (iAdditionalCoordinates > 0 && listOfCoordinates != null) { foreach (var coordinateTuple in listOfCoordinates) { times.Add(Mt5TimeConverter.ConvertToMtTime(coordinateTuple.Item1)); prices.Add(coordinateTuple.Item2); } } cmdParams["Times"] = times; cmdParams["Prices"] = prices; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectCreate, cmdParams); } /// ///The function returns the name of the corresponding object in the specified chart, in the specified subwindow, of the specified type. /// ///Chart identifier. 0 means the current chart. ///Ordinal number of the object according to the specified filter by the number and type of the subwindow. ///umber of the chart subwindow. 0 means the main chart window, -1 means all the subwindows of the chart, including the main window. ///Type of the object. The value can be one of the values of the ENUM_OBJECT enumeration. -1 means all types. public string? ObjectName(long chartId, int pos, int subWindow = -1, int type = -1) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Pos", pos }, { "SubWindow", subWindow }, { "Type", type } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectName, cmdParams); } /// ///The function removes the object with the specified name from the specified chart. /// ///Chart identifier. 0 means the current chart. ///Name of object to be deleted. public bool ObjectDelete(long chartId, string name) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectDelete, cmdParams); } /// ///The function removes the object with the specified name from the specified chart. /// ///Chart identifier. 0 means the current chart. ///Number of the chart subwindow. 0 means the main chart window, -1 means all the subwindows of the chart, including the main window. ///Type of the object. The value can be one of the values of the ENUM_OBJECT enumeration. -1 means all types. public int ObjectsDeleteAll(long chartId, int subWindow = -1, int type = -1) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "Type", type } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectsDeleteAll, cmdParams); } /// ///The function searches for an object with the specified name in the chart with the specified ID. /// ///Chart identifier. 0 means the current chart. ///The name of the searched object. public int ObjectFind(long chartId, string name) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectFind, cmdParams); } /// ///The function returns the time value for the specified price value of the specified object. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///Price value. ///Line identifier. public DateTime ObjectGetTimeByValue(long chartId, string name, double value, int lineId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "Value", value }, { "LineId", lineId } }; var res = SendCommand(ExecutorHandle, Mt5CommandType.ObjectGetTimeByValue, cmdParams); return Mt5TimeConverter.ConvertFromMtTime(res); } /// ///The function returns the price value for the specified time value of the specified object. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///Time value. ///Line identifier. public double ObjectGetValueByTime(long chartId, string name, DateTime time, int lineId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "Time", Mt5TimeConverter.ConvertToMtTime(time) }, { "LineId", lineId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectGetValueByTime, cmdParams); } /// ///The function changes coordinates of the specified anchor point of the object. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///Index of the anchor point. The number of anchor points depends on the type of object. ///Time coordinate of the selected anchor point. ///Price coordinate of the selected anchor point. public bool ObjectMove(long chartId, string name, int pointIndex, DateTime time, double price) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PointIndex", pointIndex }, { "Time", Mt5TimeConverter.ConvertToMtTime(time) }, { "Price", price } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectMove, cmdParams); } /// ///The function returns the number of objects in the specified chart, specified subwindow, of the specified type. /// ///Chart identifier. 0 means the current chart. ///Number of the chart subwindow. 0 means the main chart window, -1 means all the subwindows of the chart, including the main window. ///Type of the object. The value can be one of the values of the ENUM_OBJECT enumeration. -1 means all types. public int ObjectsTotal(long chartId, int subWindow = -1, int type = -1) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "SubWindow", subWindow }, { "Type", type } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectsTotal, cmdParams); } /// ///The function sets the value of the corresponding object property. The object property must be of the double type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_DOUBLE enumeration. ///The value of the property. public bool ObjectSetDouble(long chartId, string name, ENUM_OBJECT_PROPERTY_DOUBLE propId, double propValue) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId }, { "PropValue", propValue} }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectSetDouble, cmdParams); } /// ///The function sets the value of the corresponding object property. The object property must be of the datetime, int, color, bool or char type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_INTEGER enumeration. ///The value of the property. public bool ObjectSetInteger(long chartId, string name, ENUM_OBJECT_PROPERTY_INTEGER propId, long propValue) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId }, { "PropValue", propValue} }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectSetInteger, cmdParams); } /// ///The function sets the value of the corresponding object property. The object property must be of the string type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_STRING enumeration. ///The value of the property. public bool ObjectSetString(long chartId, string name, ENUM_OBJECT_PROPERTY_STRING propId, string propValue) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId }, { "PropValue", propValue} }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectSetString, cmdParams); } /// ///The function returns the value of the corresponding object property. The object property must be of the double type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_DOUBLE enumeration. public double ObjectGetDouble(long chartId, string name, ENUM_OBJECT_PROPERTY_DOUBLE propId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectGetDouble, cmdParams); } /// ///he function returns the value of the corresponding object property. The object property must be of the datetime, int, color, bool or char type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_INTEGER enumeration. public long ObjectGetInteger(long chartId, string name, ENUM_OBJECT_PROPERTY_INTEGER propId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectGetInteger, cmdParams); } /// ///The function returns the value of the corresponding object property. The object property must be of the string type. /// ///Chart identifier. 0 means the current chart. ///Name of the object. ///ID of the object property. The value can be one of the values of the ENUM_OBJECT_PROPERTY_STRING enumeration. public string? ObjectGetString(long chartId, string name, ENUM_OBJECT_PROPERTY_STRING propId) { Dictionary cmdParams = new() { { "ChartId", chartId }, { "Name", name ?? string.Empty }, { "PropId", (int)propId } }; return SendCommand(ExecutorHandle, Mt5CommandType.ObjectGetString, cmdParams); } #endregion //Object Functions #region Technical Indicators /// ///The function creates Accelerator Oscillator in a global cache of the client terminal and returns its handle. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. public int iAC(string symbol, ENUM_TIMEFRAMES period) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period } }; return SendCommand(ExecutorHandle, Mt5CommandType.iAC, cmdParams); } /// ///The function returns the handle of the Accumulation/Distribution indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The volume used. Can be any of ENUM_APPLIED_VOLUME values. public int iAD(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AppliedVolume", appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iAD, cmdParams); } /// ///The function returns the handle of the Average Directional Movement Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period to calculate the index. public int iADX(string symbol, ENUM_TIMEFRAMES period, int adxPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AdxPeriod", adxPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iADX, cmdParams); } /// ///The function returns the handle of Average Directional Movement Index by Welles Wilder. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period to calculate the index. public int iADXWilder(string symbol, ENUM_TIMEFRAMES period, int adxPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AdxPeriod", adxPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iADXWilder, cmdParams); } /// ///The function returns the handle of the Alligator indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the blue line (Alligator's Jaw). ///The shift of the blue line relative to the price chart. ///Averaging period for the red line (Alligator's Teeth). ///The shift of the red line relative to the price chart. ///Averaging period for the green line (Alligator's lips). ///The shift of the green line relative to the price chart. ///The method of averaging. Can be any of the ENUM_MA_METHOD values. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iAlligator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "JawPeriod", jawPeriod }, { "JawShift", jawShift }, { "TeethPeriod", teethPeriod }, { "TeethShift", teethShift }, { "LipsPeriod", lipsPeriod }, { "LipsShift", lipsShift }, { "MaMethod", maMethod}, { "AppliedPrice", appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iAlligator, cmdParams); } /// ///The function returns the handle of the Adaptive Moving Average indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The calculation period, on which the efficiency coefficient is calculated. ///Fast period for the smoothing coefficient calculation for a rapid market. ///Slow period for the smoothing coefficient calculation in the absence of trend. ///Shift of the indicator relative to the price chart. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iAMA(string symbol, ENUM_TIMEFRAMES period, int amaPeriod, int fastMaPeriod, int slowMaPeriod, int amaShift, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AmaPeriod", amaPeriod }, { "FastMaPeriod", fastMaPeriod }, { "SlowMaPeriod", slowMaPeriod }, { "AmaShift", amaShift }, { "AppliedPrice", appliedPrice} }; return SendCommand(ExecutorHandle, Mt5CommandType.iAMA, cmdParams); } /// ///The function returns the handle of the Awesome Oscillator indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. public int iAO(string symbol, ENUM_TIMEFRAMES period) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period } }; return SendCommand(ExecutorHandle, Mt5CommandType.iAO, cmdParams); } /// ///The function returns the handle of the Average True Range indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The value of the averaging period for the indicator calculation. public int iATR(string symbol, ENUM_TIMEFRAMES period, int maPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iATR, cmdParams); } /// ///The function returns the handle of the Bears Power indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The value of the averaging period for the indicator calculation. public int iBearsPower(string symbol, ENUM_TIMEFRAMES period, int maPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iBearsPower, cmdParams); } /// ///The function returns the handle of the Bollinger Bands® indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The averaging period of the main line of the indicator. ///The shift the indicator relative to the price chart. ///Deviation from the main line. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iBands(string symbol, ENUM_TIMEFRAMES period, int bandsPeriod, int bandsShift, double deviation, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "BandsPeriod", bandsPeriod }, { "BandsShift", bandsShift }, { "Deviation", deviation}, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iBands, cmdParams); } /// ///The function returns the handle of the Bulls Power indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The averaging period for the indicator calculation. public int iBullsPower(string symbol, ENUM_TIMEFRAMES period, int maPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iBullsPower, cmdParams); } /// ///The function returns the handle of the Commodity Channel Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The averaging period for the indicator calculation. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iCCI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "AppliedPrice", appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iCCI, cmdParams); } /// ///The function returns the handle of the Bulls Power indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Fast averaging period for calculations. ///Slow averaging period for calculations. ///Smoothing type. Can be one of the averaging constants of ENUM_MA_METHOD. ///The volume used. Can be one of the constants of ENUM_APPLIED_VOLUME. public int iChaikin(string symbol, ENUM_TIMEFRAMES period, int fastMaPeriod, int slowMaPeriod, ENUM_MA_METHOD maMethod, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "FastMaPeriod", fastMaPeriod }, { "SlowMaPeriod", slowMaPeriod}, { "MaMethod", (int)maMethod }, { "AppliedVolume", (int)appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iChaikin, cmdParams); } /// ///The function returns the handle of the Bulls Power indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for calculations. ///Shift of the indicator relative to the price chart. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iDEMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift}, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iDEMA, cmdParams); } /// ///The function returns the handle of the DeMarker indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for calculations. public int iDeMarker(string symbol, ENUM_TIMEFRAMES period, int maPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iDeMarker, cmdParams); } /// ///The function returns the handle of the Envelopes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the main line. ///The shift of the indicator relative to the price chart. ///Smoothing type. Can be one of the values of ENUM_MA_METHOD. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. ///The deviation from the main line (in percents). public int iEnvelopes(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice, double deviation) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift }, { "MaMethod", (int)maMethod }, { "AppliedPrice", (int)appliedPrice }, { "Deviation", deviation } }; return SendCommand(ExecutorHandle, Mt5CommandType.iEnvelopes, cmdParams); } /// ///The function returns the handle of the Force Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the indicator calculations. ///Smoothing type. Can be one of the values of ENUM_MA_METHOD. ///The volume used. Can be one of the values of ENUM_APPLIED_VOLUME. public int iForce(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_MA_METHOD maMethod, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaMethod", (int)maMethod }, { "AppliedVolume", (int)appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iForce, cmdParams); } /// ///The function returns the handle of the Fractals indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. public int iFractals(string symbol, ENUM_TIMEFRAMES period) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period } }; return SendCommand(ExecutorHandle, Mt5CommandType.iFractals, cmdParams); } /// ///The function returns the handle of the Fractal Adaptive Moving Average indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period (bars count) for the indicator calculations. ///Shift of the indicator in the price chart. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iFrAMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iFrAMA, cmdParams); } /// ///The function returns the handle of the Gator indicator. The Oscillator shows the difference between the blue and red lines of Alligator (upper histogram) and difference between red and green lines (lower histogram). /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the blue line (Alligator's Jaw). ///The shift of the blue line relative to the price chart. It isn't directly connected with the visual shift of the indicator histogram. ///Averaging period for the red line (Alligator's Teeth). ///The shift of the red line relative to the price chart. It isn't directly connected with the visual shift of the indicator histogram. ///Averaging period for the green line (Alligator's lips). ///The shift of the green line relative to the price charts. It isn't directly connected with the visual shift of the indicator histogram. ///Smoothing type. Can be one of the values of ENUM_MA_METHOD. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iGator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "JawPeriod", jawPeriod }, { "JawShift", jawShift }, { "TeethPeriod", teethPeriod }, { "TeethShift", teethShift }, { "LipsPeriod", lipsPeriod }, { "LipsShift", lipsShift }, { "MaMethod", maMethod }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iGator, cmdParams); } /// ///The function returns the handle of the Ichimoku Kinko Hyo indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for Tenkan Sen. ///Averaging period for Kijun Sen. ///Averaging period for Senkou Span B. public int iIchimoku(string symbol, ENUM_TIMEFRAMES period, int tenkanSen, int kijunSen, int senkouSpanB) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "TenkanSen", tenkanSen }, { "KijunSen", kijunSen }, { "SenkouSpanB", senkouSpanB } }; return SendCommand(ExecutorHandle, Mt5CommandType.iIchimoku, cmdParams); } /// ///The function returns the handle of the Market Facilitation Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The volume used. Can be one of the constants of ENUM_APPLIED_VOLUME. public int iBWMFI(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AppliedVolume", (int)appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iBWMFI, cmdParams); } /// ///The function returns the handle of the Momentum indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for the calculation of the price change. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iMomentum(string symbol, ENUM_TIMEFRAMES period, int momPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MomPeriod", momPeriod }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iMomentum, cmdParams); } /// ///The function returns the handle of the Money Flow Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for the calculation. ///The volume used. Can be any of the ENUM_APPLIED_VOLUME values. public int iMFI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "AppliedVolume", (int)appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iMFI, cmdParams); } /// ///The function returns the handle of the Moving Average indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the calculation of the moving average. ///Shift of the indicator relative to the price chart. ///Smoothing type. Can be one of the ENUM_MA_METHOD values. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift }, { "MaMethod", (int)maMethod }, { "AppliedPrice", (int)appliedPrice} }; return SendCommand(ExecutorHandle, Mt5CommandType.iMA, cmdParams); } /// ///The function returns the handle of the Moving Average of Oscillator indicator. The OsMA oscillator shows the difference between values of MACD and its signal line. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period for Fast Moving Average calculation. ///Period for Slow Moving Average calculation. ///Averaging period for signal line calculation. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iOsMA(string symbol, ENUM_TIMEFRAMES period, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "FastEmaPeriod", fastEmaPeriod }, { "SlowEmaPeriod", slowEmaPeriod }, { "SignalPeriod", signalPeriod }, { "AppliedPrice", (int)appliedPrice} }; return SendCommand(ExecutorHandle, Mt5CommandType.iOsMA, cmdParams); } /// ///The function returns the handle of the Moving Averages Convergence/Divergence indicator. In systems where OsMA is called MACD Histogram, this indicator is shown as two lines. In the client terminal the Moving Averages Convergence/Divergence looks like a histogram. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period for Fast Moving Average calculation. ///Period for Slow Moving Average calculation. ///Averaging period for signal line calculation. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iMACD(string symbol, ENUM_TIMEFRAMES period, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "FastEmaPeriod", fastEmaPeriod }, { "SlowEmaPeriod", slowEmaPeriod }, { "SignalPeriod", signalPeriod }, { "AppliedPrice", (int)appliedPrice} }; return SendCommand(ExecutorHandle, Mt5CommandType.iMACD, cmdParams); } /// ///The function returns the handle of the On Balance Volume indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The volume used. Can be any of the ENUM_APPLIED_VOLUME values. public int iOBV(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AppliedVolume", (int)appliedVolume} }; return SendCommand(ExecutorHandle, Mt5CommandType.iOBV, cmdParams); } /// ///The function returns the handle of the Parabolic Stop and Reverse system indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The step of price increment, usually 0.02. ///The maximum step, usually 0.2. public int iSAR(string symbol, ENUM_TIMEFRAMES period, double step, double maximum) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "Step", (int)step}, { "Maximum", maximum } }; return SendCommand(ExecutorHandle, Mt5CommandType.iSAR, cmdParams); } /// ///The function returns the handle of the Relative Strength Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the RSI calculation. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iRSI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iRSI, cmdParams); } /// ///The function returns the handle of the Relative Vigor Index indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the RVI calculation. public int iRVI(string symbol, ENUM_TIMEFRAMES period, int maPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iRVI, cmdParams); } /// ///The function returns the handle of the Standard Deviation indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period for the RVI calculation. ///Shift of the indicator relative to the price chart. ///Type of averaging. Can be any of the ENUM_MA_METHOD values. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iStdDev(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift }, { "MaMethod", (int)maMethod }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iStdDev, cmdParams); } /// ///The function returns the handle of the Stochastic Oscillator indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for the %K line calculation. ///Averaging period (bars count) for the %D line calculation. ///Slowing value. ///Type of averaging. Can be any of the ENUM_MA_METHOD values. ///Parameter of price selection for calculations. Can be one of the ENUM_STO_PRICE values. public int iStochastic(string symbol, ENUM_TIMEFRAMES period, int Kperiod, int Dperiod, int slowing, ENUM_MA_METHOD maMethod, ENUM_STO_PRICE priceField) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "Kperiod", Kperiod }, { "Dperiod", Dperiod }, { "Slowing", slowing }, { "MaMethod", (int)maMethod }, { "PriceField", (int)priceField } }; return SendCommand(ExecutorHandle, Mt5CommandType.iStochastic, cmdParams); } /// ///The function returns the handle of the Triple Exponential Moving Average indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for calculation. ///Shift of indicator relative to the price chart. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iTEMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "MaShift", maShift }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iTEMA, cmdParams); } /// ///The function returns the handle of the Triple Exponential Moving Averages Oscillator indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Averaging period (bars count) for calculation. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iTriX(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "MaPeriod", maPeriod }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iTriX, cmdParams); } /// ///The function returns the handle of the Larry Williams' Percent Range indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period (bars count) for the indicator calculation. public int iWPR(string symbol, ENUM_TIMEFRAMES period, int calcPeriod) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "CalcPeriod", calcPeriod } }; return SendCommand(ExecutorHandle, Mt5CommandType.iWPR, cmdParams); } /// ///The function returns the handle of the Variable Index Dynamic Average indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///Period (bars count) for the Chande Momentum Oscillator calculation. ///EMA period (bars count) for smoothing factor calculation. ///Shift of the indicator relative to the price chart. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. public int iVIDyA(string symbol, ENUM_TIMEFRAMES period, int cmoPeriod, int emaPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "CmoPeriod", cmoPeriod }, { "EmaPeriod", emaPeriod }, { "MaShift", maShift }, { "AppliedPrice", (int)appliedPrice } }; return SendCommand(ExecutorHandle, Mt5CommandType.iVIDyA, cmdParams); } /// ///The function returns the handle of the Volumes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The volume used. Can be any of the ENUM_APPLIED_VOLUME values. public int iVolumes(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Period", (int)period }, { "AppliedVolume", (int)appliedVolume } }; return SendCommand(ExecutorHandle, Mt5CommandType.iVolumes, cmdParams); } /// ///The function returns the handle of the Volumes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The name of the custom indicator, with path relative to the root directory of indicators (MQL5/Indicators/). If an indicator is located in a subdirectory, for example, in MQL5/Indicators/Examples, its name must be specified like: "Examples\\indicator_name" (it is necessary to use a double slash instead of the single slash as a separator). ///input-parameters of a custom indicator. If there is no parameters specified, then default values will be used. public int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, double[] parameters) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Timeframe", (int)period }, { "Name", name ?? string.Empty}, { "Params", parameters }, { "ParamsType", ParametersType.Double} }; return SendCommand(ExecutorHandle, Mt5CommandType.iCustom, cmdParams); } /// ///The function returns the handle of the Volumes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The name of the custom indicator, with path relative to the root directory of indicators (MQL5/Indicators/). If an indicator is located in a subdirectory, for example, in MQL5/Indicators/Examples, its name must be specified like: "Examples\\indicator_name" (it is necessary to use a double slash instead of the single slash as a separator). ///input-parameters of a custom indicator. If there is no parameters specified, then default values will be used. public int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, int[] parameters) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Timeframe", (int)period }, { "Name", name ?? string.Empty }, { "Params", parameters }, { "ParamsType", ParametersType.Int } }; return SendCommand(ExecutorHandle, Mt5CommandType.iCustom, cmdParams); } /// ///The function returns the handle of the Volumes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The name of the custom indicator, with path relative to the root directory of indicators (MQL5/Indicators/). If an indicator is located in a subdirectory, for example, in MQL5/Indicators/Examples, its name must be specified like: "Examples\\indicator_name" (it is necessary to use a double slash instead of the single slash as a separator). ///input-parameters of a custom indicator. If there is no parameters specified, then default values will be used. public int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, string[] parameters) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Timeframe", (int)period }, { "Name", name ?? string.Empty }, { "Params", parameters }, { "ParamsType", ParametersType.String } }; return SendCommand(ExecutorHandle, Mt5CommandType.iCustom, cmdParams); } /// ///The function returns the handle of the Volumes indicator. /// ///The symbol name of the security, the data of which should be used to calculate the indicator. ///The value of the period can be one of the ENUM_TIMEFRAMES enumeration values, 0 means the current timeframe. ///The name of the custom indicator, with path relative to the root directory of indicators (MQL5/Indicators/). If an indicator is located in a subdirectory, for example, in MQL5/Indicators/Examples, its name must be specified like: "Examples\\indicator_name" (it is necessary to use a double slash instead of the single slash as a separator). ///input-parameters of a custom indicator. If there is no parameters specified, then default values will be used. public int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, bool[] parameters) { Dictionary cmdParams = new() { { "Symbol", symbol ?? string.Empty }, { "Timeframe", (int)period }, { "Name", name ?? string.Empty }, { "Params", parameters }, { "ParamsType", ParametersType.Boolean } }; return SendCommand(ExecutorHandle, Mt5CommandType.iCustom, cmdParams); } #endregion //Technical Indicators #region Date and Time /// ///Returns the last known server time, time of the last quote receipt for one of the symbols selected in the "Market Watch" window. /// public DateTime TimeCurrent() { var response = SendCommand(ExecutorHandle, Mt5CommandType.TimeCurrent); return Mt5TimeConverter.ConvertFromMtTime(response); } /// ///Returns the calculated current time of the trade server. Unlike TimeCurrent(), the calculation of the time value is performed in the client terminal and depends on the time settings on your computer. /// public DateTime TimeTradeServer() { var response = SendCommand(ExecutorHandle, Mt5CommandType.TimeTradeServer); return Mt5TimeConverter.ConvertFromMtTime(response); } /// ///Returns the local time of a computer, where the client terminal is running. /// public DateTime TimeLocal() { var response = SendCommand(ExecutorHandle, Mt5CommandType.TimeLocal); return Mt5TimeConverter.ConvertFromMtTime(response); } /// ///Returns the GMT, which is calculated taking into account the DST switch by the local time on the computer where the client terminal is running. /// public DateTime TimeGMT() { var response = SendCommand(ExecutorHandle, Mt5CommandType.TimeGMT); return Mt5TimeConverter.ConvertFromMtTime(response); } #endregion //Date and Time #region Checkup /// ///Returns the value of the last error that occurred during the execution of an mql5 program. /// public int GetLastError() { return SendCommand(ExecutorHandle, Mt5CommandType.GetLastError); } /// ///Sets the value of the predefined variable _LastError into zero. /// public void ResetLastError() { SendCommand(ExecutorHandle, Mt5CommandType.ResetLastError); } #endregion #region Global Variables /// ///Checks the existence of a global variable with the specified name. /// ///Global variable name. public bool GlobalVariableCheck(string name) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableCheck, cmdParams); } /// ///Returns the time when the global variable was last accessed. /// ///Name of the global variable. public DateTime GlobalVariableTime(string name) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty } }; var res = SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableTime, cmdParams); return Mt5TimeConverter.ConvertFromMtTime(res); } /// ///Deletes a global variable from the client terminal. /// ///Name of the global variable. public bool GlobalVariableDel(string name) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableDel, cmdParams); } /// ///Returns the value of an existing global variable of the client terminal. /// ///Global variable name. public double GlobalVariableGet(string name) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableGet, cmdParams); } /// ///Returns the name of a global variable by its ordinal number. /// ///Sequence number in the list of global variables. It should be greater than or equal to 0 and less than GlobalVariablesTotal(). public string? GlobalVariableName(int index) { Dictionary cmdParams = new() { { "Index", index } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableName, cmdParams); } /// ///Sets a new value for a global variable. If the variable does not exist, the system creates a new global variable. /// ///Global variable name. ///The new numerical value. public DateTime GlobalVariableSet(string name, double value) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty }, { "Value", value } }; var res = SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableSet, cmdParams); return Mt5TimeConverter.ConvertFromMtTime(res); } /// ///Forcibly saves contents of all global variables to a disk. /// public void GlobalVariablesFlush() { SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariablesFlush); } /// ///The function attempts to create a temporary global variable. If the variable doesn't exist, the system creates a new temporary global variable. /// ///The name of a temporary global variable. public bool GlobalVariableTemp(string name) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableTemp, cmdParams); } /// ///Sets the new value of the existing global variable if the current value equals to the third parameter check_value. If there is no global variable, the function will generate an error ERR_GLOBALVARIABLE_NOT_FOUND (4501) and return false. /// ///The name of a global variable. ///New value. ///The value to check the current value of the global variable. public bool GlobalVariableSetOnCondition(string name, double value, double checkValue) { Dictionary cmdParams = new() { { "Name", name ?? string.Empty }, { "Value", value }, { "CheckValue", checkValue } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariableSetOnCondition, cmdParams); } /// ///Deletes global variables of the client terminal. /// ///Name prefix global variables to remove. If you specify a prefix NULL or empty string, then all variables that meet the data criterion will be deleted. ///Date to select global variables by the time of their last modification. The function removes global variables, which were changed before this date. If the parameter is zero, then all variables that meet the first criterion (prefix) are deleted. public int GlobalVariablesDeleteAll(string prefixName = "", DateTime? limitData = null) { Dictionary cmdParams = new() { { "PrefixName", prefixName ?? string.Empty }, { "LimitData", Mt5TimeConverter.ConvertToMtTime(limitData) } }; return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariablesDeleteAll, cmdParams); } /// ///Returns the total number of global variables of the client terminal. /// public int GlobalVariablesTotal() { return SendCommand(ExecutorHandle, Mt5CommandType.GlobalVariablesTotal); } #endregion #region Backtesting functions /// ///The function unlock ticks in backtesting mode. /// public void UnlockTicks() { SendCommand(ExecutorHandle, Mt5CommandType.UnlockTicks); } #endregion #endregion // Public Methods #region Properties /// ///Connection status of MetaTrader API. /// public Mt5ConnectionState ConnectionState { get { lock (_locker) { return _connectionState; } } } /// ///Handle of expert used to execute commands /// public int ExecutorHandle { get { lock (_locker) { return _executorHandle; } } set { lock (_locker) { _executorHandle = value; } } } #endregion #region Events public event QuoteHandler? QuoteUpdated; public event EventHandler? QuoteUpdate; public event EventHandler? QuoteAdded; public event EventHandler? QuoteRemoved; public event EventHandler? ConnectionStateChanged; public event EventHandler? OnTradeTransaction; public event EventHandler? OnBookEvent; public event EventHandler? OnLastTimeBar; public event EventHandler? OnLockTicks; public event EventHandler? QuoteList; #endregion #region Private Methods private MtRpcClient? Client { get { lock (_locker) { return _client; } } } private void Client_MtEventReceived(object? sender, MtEventArgs e) { Task.Run(() => _mtEventHandlers[(Mt5EventTypes)e.EventType](e.ExpertHandle, e.Payload)); } private void Client_ExpertAdded(object? sender, MtExpertEventArgs e) { Task.Run(() => ProcessExpertAdded(e.Expert)); } private void Client_ExpertRemoved(object? sender, MtExpertEventArgs e) { Task.Run(() => ProcessExpertRemoved(e.Expert)); } private void ProcessExpertAdded(int handle) { Log.Debug($"ProcessExpertAdded: {handle}"); bool added; lock (_locker) { added = _experts.Add(handle); if (_executorHandle == 0) _executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0; } if (added) { var quote = GetQuote(Client, handle); if (quote != null) { QuoteAdded?.Invoke(this, new Mt5QuoteEventArgs(quote)); } else Log.Warn($"ProcessExpertAdded: failed to get quote for expert {handle}"); } else Log.Warn($"ProcessExpertAdded: expert handle {handle} is already exist"); } private void ProcessExpertRemoved(int handle) { Log.Debug($"ProcessExpertRemoved: {handle}"); Mt5Quote? quote; lock (_locker) { _quotes.TryGetValue(handle, out quote); _quotes.Remove(handle); _experts.Remove(handle); if (_executorHandle == handle) _executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0; } if (quote != null) QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(new Mt5Quote { Instrument = quote.Instrument, ExpertHandle = quote.ExpertHandle })); } private Mt5Quote? GetQuote(MtRpcClient? client, int expertHandle) { Log.Debug($"GetQuote: expertHandle = {expertHandle}"); var q = SendCommand(client, expertHandle, Mt5CommandType.GetQuote); if (q == null || string.IsNullOrEmpty(q.Instrument) || q.Tick == null) return null; Mt5Quote quote = new() { Instrument = q.Instrument, Bid = q.Tick.Bid, Ask = q.Tick.Ask, ExpertHandle = expertHandle, Volume = q.Tick.Volume, Time = Mt5TimeConverter.ConvertFromMtTime(q.Tick.Time), Last = q.Tick.Last }; return quote; } private void Client_OnConnectionFailed(object? sender, EventArgs e) { Log.Info("Received connection failed"); Disconnect(true); } private void Client_Disconnected(object? sender, EventArgs e) { Log.Info("Received normal disconnection"); Disconnect(false); } private void ReceivedOnTradeTransactionEvent(int expertHandle, string payload) { var e = JsonConvert.DeserializeObject(payload); if (e == null) return; OnTradeTransaction?.Invoke(this, new Mt5TradeTransactionEventArgs { ExpertHandle = expertHandle, Trans = e.Trans, Request = e.Request, Result = e.Result }); } private void ReceivedOnBookEvent(int expertHandle, string payload) { var e = JsonConvert.DeserializeObject(payload); if (e == null || string.IsNullOrEmpty(e.Symbol)) return; OnBookEvent?.Invoke(this, new Mt5BookEventArgs { ExpertHandle = expertHandle, Symbol = e.Symbol }); } private void ReceivedOnTickEvent(int expertHandle, string payload) { var e = JsonConvert.DeserializeObject(payload); if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Tick == null) return; QuoteUpdated?.Invoke(this, e.Instrument, e.Tick.Bid, e.Tick.Ask); Mt5Quote quote = new() { Instrument = e.Instrument, Bid = e.Tick.Bid, Ask = e.Tick.Ask, ExpertHandle = expertHandle, Volume = e.Tick.Volume, Time = Mt5TimeConverter.ConvertFromMtTime(e.Tick.Time), Last = e.Tick.Last }; QuoteUpdate?.Invoke(this, new Mt5QuoteEventArgs(quote)); } private void ReceivedOnLastTimeBarEvent(int expertHandle, string payload) { var e = JsonConvert.DeserializeObject(payload); if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Rates == null) return; OnLastTimeBar?.Invoke(this, new Mt5TimeBarArgs(expertHandle, e.Instrument, e.Timeframe, e.Rates)); } private void ReceivedOnLockTicksEvent(int expertHandle, string payload) { var e = JsonConvert.DeserializeObject(payload); if (e == null || string.IsNullOrEmpty(e.Instrument)) return; OnLockTicks?.Invoke(this, new Mt5LockTicksEventArgs(e.Instrument)); } private void Disconnect(bool failed) { var state = failed ? Mt5ConnectionState.Failed : Mt5ConnectionState.Disconnected; var message = failed ? "Connection Failed" : "Disconnected"; MtRpcClient? client; lock (_locker) { if (_connectionState == Mt5ConnectionState.Disconnected || _connectionState == Mt5ConnectionState.Failed) return; _connectionState = state; client = _client; _client = null; _experts.Clear(); _executorHandle = 0; } client?.Disconnect(); Log.Info(message); ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(state, message)); } private T? SendCommand(int expertHandle, Mt5CommandType commandType, object? payload = null) { return SendCommand(Client, expertHandle, commandType, payload); } private T? SendCommand(MtRpcClient? client, int expertHandle, Mt5CommandType commandType, object? payload = null) { if (client == null) { Log.Warn("SendCommand: No connection"); throw new Exception("No connection"); } var payloadJson = payload == null ? string.Empty : JsonConvert.SerializeObject(payload); Log.Debug($"SendCommand: sending '{payloadJson}' ..."); var responseJson = client.SendCommand(expertHandle, (int)commandType, payloadJson, CommandTimeout); Log.Debug($"SendCommand: received response JSON [{responseJson}]"); if (string.IsNullOrEmpty(responseJson)) { Log.Warn("SendCommand: Response JSON from MetaTrader is null or empty"); throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null"); } var response = JsonConvert.DeserializeObject>(responseJson); if (response == null) { Log.Warn("SendCommand: Failed to deserialize response from JSON"); throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null"); } if (response.ErrorCode != 0) { Log.Warn($"SendCommand: ErrorCode = {response.ErrorCode}. {response.ErrorMessage}"); throw new ExecutionException((ErrorCode)response.ErrorCode, response.ErrorMessage); } return (response.Value == null) ? default : response.Value; } private void BacktestingReady() { SendCommand(ExecutorHandle, Mt5CommandType.BacktestingReady); } #endregion } internal class RpcClientLogger(IMtLogger logger) : IRpcLogger { public void Debug(string message) { logger_.Debug(message); } public void Error(string message) { logger_.Debug(message); } public void Info(string message) { logger_.Debug(message); } public void Warn(string message) { logger_.Debug(message); } private readonly IMtLogger logger_ = logger; } internal class StubMtLogger : IMtLogger { public void Debug(object message) { } public void Error(object message) { } public void Fatal(object message) { } public void Info(object message) { } public void Warn(object message) { } } }