From 18ddf3df1c3d0c397348359f0f10f877ca8ecbc6 Mon Sep 17 00:00:00 2001 From: DW Date: Fri, 30 Dec 2016 17:16:48 +0200 Subject: [PATCH] Issue #32: Added c# implementations of most object functions in MtApi client --- MtApi/EnumColorFormat.cs | 9 + MtApi/EnumObjectPropertyDouble.cs | 11 + MtApi/EnumObjectPropertyInteger.cs | 40 ++++ MtApi/EnumObjectPropertyString.cs | 13 + MtApi/FlagFontStyle.cs | 30 +++ MtApi/MtApi.csproj | 5 + MtApi/MtApiClient.cs | 366 ++++++++++++++++++++++++++++- MtApi/MtApiTimeConverter.cs | 6 +- MtApi5/ExtensionMethods.cs | 21 -- MtApi5/MtApi5.csproj | 1 - MtApi5/MtApi5Client.cs | 7 +- 11 files changed, 479 insertions(+), 30 deletions(-) create mode 100644 MtApi/EnumColorFormat.cs create mode 100644 MtApi/EnumObjectPropertyDouble.cs create mode 100644 MtApi/EnumObjectPropertyInteger.cs create mode 100644 MtApi/EnumObjectPropertyString.cs create mode 100644 MtApi/FlagFontStyle.cs delete mode 100755 MtApi5/ExtensionMethods.cs diff --git a/MtApi/EnumColorFormat.cs b/MtApi/EnumColorFormat.cs new file mode 100644 index 00000000..6b6d590b --- /dev/null +++ b/MtApi/EnumColorFormat.cs @@ -0,0 +1,9 @@ +namespace MtApi +{ + enum EnumColorFormat + { + COLOR_FORMAT_XRGB_NOALPHA = 0, //The component of the alpha channel is ignored + COLOR_FORMAT_ARGB_RAW = 1, //Color components are not handled by the terminal (must be correctly set by the user) + COLOR_FORMAT_ARGB_NORMALIZE = 2 //Color components are handled by the terminal + } +} diff --git a/MtApi/EnumObjectPropertyDouble.cs b/MtApi/EnumObjectPropertyDouble.cs new file mode 100644 index 00000000..9bb22d35 --- /dev/null +++ b/MtApi/EnumObjectPropertyDouble.cs @@ -0,0 +1,11 @@ +namespace MtApi +{ + public enum EnumObjectPropertyDouble + { + OBJPROP_PRICE = 20, // Price coordinate + OBJPROP_LEVELVALUE = 204, // Level value + OBJPROP_SCALE = 12, // Scale (properties of Gann objects, Fibonacci Arcs and Ellipse) + OBJPROP_ANGLE = 13, // Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE + OBJPROP_DEVIATION = 16, // Deviation for the Standard Deviation Channel + } +} diff --git a/MtApi/EnumObjectPropertyInteger.cs b/MtApi/EnumObjectPropertyInteger.cs new file mode 100644 index 00000000..5e1f79ca --- /dev/null +++ b/MtApi/EnumObjectPropertyInteger.cs @@ -0,0 +1,40 @@ +namespace MtApi +{ + public enum EnumObjectPropertyInteger + { + OBJPROP_COLOR = 6, + OBJPROP_STYLE = 7, + OBJPROP_WIDTH = 8, + OBJPROP_BACK = 9, + OBJPROP_ZORDER = 207, + OBJPROP_HIDDEN = 208, + OBJPROP_SELECTED = 17, + OBJPROP_READONLY = 1028, + OBJPROP_TYPE = 18, + OBJPROP_TIME = 19, + OBJPROP_SELECTABLE = 1000, + OBJPROP_CREATETIME = 998, + OBJPROP_LEVELS = 200, + OBJPROP_LEVELCOLOR = 201, + OBJPROP_LEVELSTYLE = 202, + OBJPROP_LEVELWIDTH = 203, + OBJPROP_ALIGN = 1036, + OBJPROP_FONTSIZE = 100, + OBJPROP_RAY_RIGHT = 1004, + OBJPROP_ELLIPSE = 11, + OBJPROP_ARROWCODE = 14, + OBJPROP_TIMEFRAMES = 15, + OBJPROP_ANCHOR = 1011, + OBJPROP_XDISTANCE = 102, + OBJPROP_YDISTANCE = 103, + OBJPROP_STATE = 1018, + OBJPROP_XSIZE = 1019, + OBJPROP_YSIZE = 1020, + OBJPROP_XOFFSET = 1033, + OBJPROP_YOFFSET = 1034, + OBJPROP_BGCOLOR = 1025, + OBJPROP_CORNER = 101, + OBJPROP_BORDER_TYPE = 1029, + OBJPROP_BORDER_COLOR = 1035 + } +} diff --git a/MtApi/EnumObjectPropertyString.cs b/MtApi/EnumObjectPropertyString.cs new file mode 100644 index 00000000..2b1cd26f --- /dev/null +++ b/MtApi/EnumObjectPropertyString.cs @@ -0,0 +1,13 @@ +namespace MtApi +{ + public enum EnumObjectPropertyString + { + OBJPROP_NAME = 1037, + OBJPROP_TEXT = 999, + OBJPROP_TOOLTIP = 206, + OBJPROP_LEVELTEXT = 205, + OBJPROP_FONT = 1001, + OBJPROP_BMPFILE = 1017, + OBJPROP_SYMBOL = 1021 + } +} diff --git a/MtApi/FlagFontStyle.cs b/MtApi/FlagFontStyle.cs new file mode 100644 index 00000000..13f857b1 --- /dev/null +++ b/MtApi/FlagFontStyle.cs @@ -0,0 +1,30 @@ +using System; + +namespace MtApi +{ + [Flags] + public enum FlagFontStyle + { + //Flags for specifying font style + FONT_ITALIC = -2147483648, + FONT_UNDERLINE = 1073741824, + FONT_STRIKEOUT = 536870912, + + //Flags for specifying font width + FW_DONTCARE = 0, + FW_THIN = 1, + FW_EXTRALIGHT = 2, + FW_ULTRALIGHT = 3, + FW_LIGHT = 4, + FW_NORMAL = 5, + FW_REGULAR = 6, + FW_MEDIUM = 7, + FW_SEMIBOLD = 8, + FW_DEMIBOLD = 9, + FW_BOLD = 10, + FW_EXTRABOLD = 11, + FW_ULTRABOLD = 12, + FW_HEAVY = 13, + FW_BLACK = 14 + } +} diff --git a/MtApi/MtApi.csproj b/MtApi/MtApi.csproj index de7bfb08..09bf1c52 100755 --- a/MtApi/MtApi.csproj +++ b/MtApi/MtApi.csproj @@ -59,12 +59,17 @@ + + + + + diff --git a/MtApi/MtApiClient.cs b/MtApi/MtApiClient.cs index 15b138fe..d9f086aa 100755 --- a/MtApi/MtApiClient.cs +++ b/MtApi/MtApiClient.cs @@ -97,7 +97,7 @@ namespace MtApi } /// - ///Connection status of MetaTrader API. + ///Handle of expert used to execute commands /// public int ExecutorHandle { @@ -1741,7 +1741,7 @@ namespace MtApi /// ///The function creates an object with the specified name, type, and the initial coordinates in the specified chart subwindow of the specified chart. /// - ///Chart identifier. + ///Chart identifier. 0 means the current chart. ///Name of the object. The name must be unique within a chart, including its subwindows. ///Object type. ///Number of the chart subwindow. 0 means the main chart window. @@ -1762,7 +1762,7 @@ namespace MtApi namedParams.Add(nameof(objectName), objectName); namedParams.Add(nameof(objectType), (int)objectType); namedParams.Add(nameof(subWindow), subWindow); - namedParams.Add(nameof(time1), time1 == null ? 0 : MtApiTimeConverter.ConvertToMtTime(time1.Value)); + namedParams.Add(nameof(time1), MtApiTimeConverter.ConvertToMtTime(time1.Value)); namedParams.Add(nameof(price1), price1); if (time2 != null) @@ -1777,6 +1777,366 @@ namespace MtApi return SendCommand(MtCommandType.ObjectCreate, null, namedParams); } + /// + ///The function returns the name of the corresponding object by its index in the objects list. + /// + ///Object index. This value must be greater or equal to 0 and less than ObjectsTotal(). + /// + ///Name of the object is returned in case of success. + /// + public string ObjectName(int objectIndex) + { + var commandParameters = new ArrayList { objectIndex }; + return SendCommand(MtCommandType.ObjectName, commandParameters); + } + + /// + ///The function removes the object with the specified name at the specified chart. + /// + ///Chart identifier. 0 means the current chart. + ///Name of object to be deleted. + /// + ///Returns true if the removal was successful, otherwise returns false. + /// + public bool ObjectDelete(long chartId, string objectName) + { + var commandParameters = new ArrayList { chartId, objectName }; + return SendCommand(MtCommandType.ObjectDelete, commandParameters); + } + + /// + ///The function removes the object with the specified name at the specified chart. + /// + ///Chart identifier. 0 means the current chart. + ///Number of the chart window. Must be greater or equal to -1 (-1 mean all subwindows, 0 means the main chart window) and less than WindowsTotal(). + ///Type of the object. The value can be one of the values of the EnumObject enumeration. EMPTY (-1) means all types. + /// + ///Returns true if the removal was successful, otherwise returns false. + /// + public int ObjectsDeleteAll(long chartId, int subWindow = EMPTY, int objectType = EMPTY) + { + var commandParameters = new ArrayList { chartId, subWindow, objectType }; + return SendCommand(MtCommandType.ObjectsDeleteAll, commandParameters); + } + + /// + ///The function searches for an object having the specified name. + /// + ///Chart identifier. 0 means the current chart. + ///The name of the object to find. + /// + ///If successful the function returns the number of the subwindow (0 means the main window of the chart), in which the object is found. + /// + public int ObjectFind(long chartId, string objectName) + { + var commandParameters = new ArrayList { chartId, objectName }; + return SendCommand(MtCommandType.ObjectFind, commandParameters); + } + + /// + ///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. + /// + ///The time value for the specified price value of the specified object. + /// + public DateTime ObjectGetTimeByValue(long chartId, string objectName, double value, int lineId = 0) + { + var commandParameters = new ArrayList { chartId, objectName, value, lineId }; + var res = SendCommand(MtCommandType.ObjectGetTimeByValue, commandParameters); + return MtApiTimeConverter.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. + /// + ///The price value for the specified time value of the specified object. + /// + public double ObjectGetValueByTime(long chartId, string objectName, DateTime? time, int lineId = 0) + { + var commandParameters = new ArrayList { chartId, objectName, time, lineId }; + return SendCommand(MtCommandType.ObjectGetValueByTime, commandParameters); + } + + /// + ///The function changes coordinates of the specified anchor point of the object at the specified chart + /// + ///Chart identifier. 0 means the current chart. + ///Name of the object. + ///Index of the anchor point. + ///Time coordinate of the selected anchor point. + ///Price coordinate of the selected anchor point. + /// + ///If successful, returns true, in case of failure returns false. + /// + public bool ObjectMove(long chartId, string objectName, int pointIndex, DateTime? time, double price) + { + var commandParameters = new ArrayList { chartId, objectName, pointIndex, MtApiTimeConverter.ConvertToMtTime(time), price }; + return SendCommand(MtCommandType.ObjectMove, commandParameters); + } + + /// + ///The function changes coordinates of the specified anchor point of the object at 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 EnumObject enumeration. EMPTY(-1) means all types. + /// + ///The number of objects. + /// + public int ObjectsTotal(long chartId, int subWindow = EMPTY, int type = EMPTY) + { + var commandParameters = new ArrayList { chartId, subWindow, type }; + return SendCommand(MtCommandType.ObjectsTotal, commandParameters); + } + + /// + ///The function returns the value of the corresponding object property. + /// + ///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 EnumObjectPropertyDouble enumeration. + ///Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier. + /// + ///Value of the double type. + /// + public double ObjectGetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, int propModifier = 0) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier }; + return SendCommand(MtCommandType.ObjectGetDouble, commandParameters); + } + + /// + ///The 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 EnumObjectPropertyDouble enumeration. + ///Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier. + /// + ///The long value. + /// + public long ObjectGetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, int propModifier = 0) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier }; + return SendCommand(MtCommandType.ObjectGetInteger, commandParameters); + } + + /// + ///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 EnumObjectPropertyString enumeration. + ///Modifier of the specified property. For the first variant, the default modifier value is equal to 0. Most properties do not require a modifier. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero. + /// + ///String value. + /// + public string ObjectGetString(long chartId, string objectName, EnumObjectPropertyString propId, int propModifier = 0) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propModifier }; + return SendCommand(MtCommandType.ObjectGetString, commandParameters); + } + + /// + ///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 EnumObjectPropertyDouble enumeration. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. + /// + public bool ObjectSetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, double propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + return SendCommand(MtCommandType.ObjectSetDouble, commandParameters); + } + + /// + ///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 EnumObjectPropertyDouble enumeration. + ///Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. + /// + public bool ObjectSetDouble(long chartId, string objectName, EnumObjectPropertyDouble propId, int propModifier, double propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + var namedParams = new Dictionary(); + namedParams.Add(nameof(propModifier), propModifier); + return SendCommand(MtCommandType.ObjectSetDouble, commandParameters, namedParams); + } + + /// + ///The function sets the value of the corresponding object property. The object property must be of the int 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 EnumObjectPropertyInteger enumeration. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false. + /// + public bool ObjectSetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, long propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + return SendCommand(MtCommandType.ObjectSetInteger, commandParameters); + } + + /// + ///The function sets the value of the corresponding object property. The object property must be of the int 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 EnumObjectPropertyInteger enumeration. + ///Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false. + /// + public bool ObjectSetInteger(long chartId, string objectName, EnumObjectPropertyInteger propId, int propModifier, long propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + var namedParams = new Dictionary(); + namedParams.Add(nameof(propModifier), propModifier); + return SendCommand(MtCommandType.ObjectSetInteger, commandParameters, namedParams); + } + + /// + ///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 EnumObjectPropertyString enumeration. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false. + /// + public bool ObjectSetString(long chartId, string objectName, EnumObjectPropertyString propId, string propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + return SendCommand(MtCommandType.ObjectSetString, commandParameters); + } + + /// + ///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 EnumObjectPropertyString enumeration. + ///Modifier of the specified property. It denotes the number of the level in Fibonacci tools and in the graphical object Andrew's pitchfork. The numeration of levels starts from zero. + ///The value of the property. + /// + ///The function returns true only if the command to change properties of a graphical object has been sent to a chart successfully. Otherwise it returns false. + /// + public bool ObjectSetString(long chartId, string objectName, EnumObjectPropertyString propId, int propModifier, string propValue) + { + var commandParameters = new ArrayList { chartId, objectName, (int)propId, propValue }; + var namedParams = new Dictionary(); + namedParams.Add(nameof(propModifier), propModifier); + return SendCommand(MtCommandType.ObjectSetString, commandParameters, namedParams); + } + + /// + ///The function sets the font for displaying the text using drawing methods and returns the result of that operation. Arial font with the size -120 (12 pt) is used by default. + /// + ///Font name in the system or the name of the resource containing the font or the path to font file on the disk. + ///The font size that can be set using positive and negative values. In case of positive values, the size of a displayed text does not depend on the operating system's font size settings. In case of negative values, the value is set in tenths of a point and the text size depends on the operating system settings ("standard scale" or "large scale"). See the Note below for more information about the differences between the modes. + ///Combination of flags describing font style. + ///Text's horizontal inclination to X axis, the unit of measurement is 0.1 degrees. It means that orientation=450 stands for inclination equal to 45 degrees. + /// + ///Returns true if the current font is successfully installed, otherwise false. + /// + public bool TextSetFont(string name, int size, FlagFontStyle flags = 0, int orientation = 0) + { + var commandParameters = new ArrayList { name, size, (uint)flags, orientation }; + return SendCommand(MtCommandType.TextSetFont, commandParameters); + } + + /// + ///Returns the object description. + /// + ///Object name. + /// + ///Object description. For objects of OBJ_TEXT and OBJ_LABEL types, the text drawn by these objects will be returned. + /// + public string ObjectDescription(string objectName) + { + var commandParameters = new ArrayList { objectName }; + return SendCommand(MtCommandType.ObjectDescription, commandParameters); + } + + /// + ///Returns the level description of a Fibonacci object. + /// + ///Fibonacci object name. + ///Index of the Fibonacci level (0-31). + /// + ///The level description of a Fibonacci object. + /// + public string ObjectGetFiboDescription(string objectName, int index) + { + var commandParameters = new ArrayList { objectName, index }; + return SendCommand(MtCommandType.ObjectGetFiboDescription, commandParameters); + } + + /// + ///The function calculates and returns bar index (shift related to the current bar) for the given price. + /// + ///Object name. + ///Price value. + /// + ///The function calculates and returns bar index (shift related to the current bar) for the given price. The bar index is calculated by the first and second coordinates using a linear equation. Applied to trendlines and similar objects. + /// + public int ObjectGetShiftByValue(string objectName, double value) + { + var commandParameters = new ArrayList { objectName, value }; + return SendCommand(MtCommandType.ObjectGetShiftByValue, commandParameters); + } + + /// + ///The function calculates and returns the price value for the specified bar (shift related to the current bar). + /// + ///Object name. + ///Bar index. + /// + ///The function calculates and returns the price value for the specified bar (shift related to the current bar). The price value is calculated by the first and second coordinates using a linear equation. Applied to trendlines and similar objects. + /// + public double ObjectGetValueByShift(string objectName, int shift) + { + var commandParameters = new ArrayList { objectName, shift }; + return SendCommand(MtCommandType.ObjectGetValueByShift, commandParameters); + } + + /// + ///Changes the value of the specified object property. + /// + ///Object name. + ///Object property index. It can be any of object properties enumeration values. + ///New value of the given property. + /// + ///If the function succeeds, the returned value will be true, otherwise it returns false. + /// + public bool ObjectSet(string objectName, int index, double value) + { + var commandParameters = new ArrayList { objectName, index, value }; + return SendCommand(MtCommandType.ObjectSet, commandParameters); + } + #endregion #region Private Methods diff --git a/MtApi/MtApiTimeConverter.cs b/MtApi/MtApiTimeConverter.cs index c123c64a..8f35ccb2 100755 --- a/MtApi/MtApiTimeConverter.cs +++ b/MtApi/MtApiTimeConverter.cs @@ -13,13 +13,13 @@ namespace MtApi return new DateTime(tmpTime.Ticks + (time * 0x989680L)); } - public static int ConvertToMtTime(DateTime time) + public static int ConvertToMtTime(DateTime? time) { int result = 0; - if (time != DateTime.MinValue) + if (time != null && time != DateTime.MinValue) { DateTime tmpTime = new DateTime(1970, 1, 1); - result = (int)((time.Ticks - tmpTime.Ticks) / 0x989680L); + result = (int)((time.Value.Ticks - tmpTime.Ticks) / 0x989680L); } return result; } diff --git a/MtApi5/ExtensionMethods.cs b/MtApi5/ExtensionMethods.cs deleted file mode 100755 index d05395b8..00000000 --- a/MtApi5/ExtensionMethods.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace MtApi5 -{ - internal static class ExtensionMethods - { - #region Event Methods - public static void FireEvent(this EventHandler eventHandler, object sender) - { - eventHandler?.Invoke(sender, EventArgs.Empty); - } - - public static void FireEvent(this EventHandler eventHandler, object sender, T e) - where T : EventArgs - { - eventHandler?.Invoke(sender, e); - } - - #endregion - } -} diff --git a/MtApi5/MtApi5.csproj b/MtApi5/MtApi5.csproj index 979b02c6..363db31f 100755 --- a/MtApi5/MtApi5.csproj +++ b/MtApi5/MtApi5.csproj @@ -56,7 +56,6 @@ - diff --git a/MtApi5/MtApi5Client.cs b/MtApi5/MtApi5Client.cs index ba931151..8352c369 100755 --- a/MtApi5/MtApi5Client.cs +++ b/MtApi5/MtApi5Client.cs @@ -1426,6 +1426,9 @@ namespace MtApi5 } } + /// + ///Handle of expert used to execute commands + /// public int ExecutorHandle { get @@ -1646,12 +1649,12 @@ namespace MtApi5 private void _client_QuoteRemoved(MtQuote quote) { - QuoteRemoved.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse())); + QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse())); } private void _client_QuoteAdded(MtQuote quote) { - QuoteAdded.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse())); + QuoteAdded?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse())); } private void OnConnected()