using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Linq; using System.Windows.Forms.DataVisualization.Charting; using System.Xml; using TradeIdeas.MiscSupport; using TradeIdeas.TIProData; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI.Charting { [DebuggerDisplay("TiqColumn: {DisplayName} {Id} {ParentId}")] public class TiqColumn { public Series Series { get; set; } /// /// The Chart Area that this indicator should be attached to. /// public ChartArea ChartArea { get; set; } /// /// The Chart Area name for reference when restoring this indicator from a layout. /// public string ChartAreaName { get; set; } /// /// The TIQ code for the indicator /// public string Code { get; set; } /// /// If this indicator uses an anchor time (anchored VWAP, for example) this value should be populated /// public DateTime? AnchorTime { get; set; } /// /// The string used to reference the value when receiving data from the server. /// /// /// The name of the reference. /// public string ReferenceName { get; set; } = ""; /// /// Display name for showing on a label or documentation. Can be a friendly name with spaces, etc. /// /// /// The display name. /// public string DisplayName { get; set; } /// /// Gets or sets the abbreviated display name for use in the status line. /// public string AbbreviatedName { get; set; } /// /// Gets or sets the id for the indicator as specified from the server. /// public int Id { get; set; } public int? ParentId { get; set; } public bool Chartable { get; set; } = true; /// /// Gets or sets a value indicating whether this indicator prefers its own chart pane. /// public bool PrefersOwnPane { get; set; } = true; public IndicatorColorType ColorType { get; set; } = IndicatorColorType.One; /// /// Gets or sets the solid color for the chart series for this indicator. Only used if ColorType == OneColor /// public Color Color { get; set; } = Color.Green; /// /// Gets or sets up color to be displayed when the OHLC candle closes higher than or equal to the open. /// public Color UpColor { get; set; } = Color.Green; /// /// Gets or sets down color to be displayed when the OHLC candle closes lower than the open. /// public Color DownColor { get; set; } = Color.Red; /// /// Gets or sets top color when using gradient coloring for this indicator. /// public Color TopColor { get; set; } = Color.Green; /// /// Gets or sets bottom color when using gradient coloring for this indicator. /// public Color BottomColor { get; set; } = Color.White; /// /// Gets or sets top value when using gradient coloring for this indicator. /// public double TopGradientValue { get; set; } = 100.0; /// /// Gets or sets bottom value when using gradient coloring for this indicator. /// public double BottomGradientValue { get; set; } /// /// Should this indicator use its own scaling (true) or is it ok to use the default scaling of its chart area. /// public bool OwnScale { get; set; } /// /// Gets or sets a value indicating whether to show this indicator's value in the status line. /// public bool ShowInStatusLine { get; set; } = true; /// /// List of parameters available to be changed by the user. /// public List Parameters { get; set; } = new List(); //public List Codes { get; set; } public IndicatorType IndicatorType { get; set; } /// /// The list of associated indicators with this one. For example, a bollinger band has a top and a bottom indicator. /// The top one might be the "main" one and the associated indicator might be the bottom one. The parameters from the /// "primary" indicator will be used for the associated indicators. Parameter objects for the associated indicators /// will be ignored. /// public List ChildIndicators { get; set; } = new List(); public TiqColumn Parent { get; set; } /// /// This id is special - just for the purposes with the new Indicator configuration window (Web-like). As with the /// web version,this unique id helps keep track of indicators while using this new window and avoid weird duplication bugs. Although it's included in a 'DeepCopy()', it's never saved with a layout /// public String HelperId { get; set; } = ""; /// /// The category for the indicator. Can be bar (|) delimited to specify subcategories. (Currently unused in client.) /// public string Category { get; set; } /// /// Gets or sets the format. /// public string Format { get; set; } /// /// Used to determined that an indicator has been updated in the indicator manager config window. /// public bool DoUpdate { get; set; } public void SaveLayout(XmlNode indicatorNode) { indicatorNode.SetProperty("REFERENCE_NAME", ReferenceName); indicatorNode.SetProperty("DISPLAY_NAME", DisplayName); indicatorNode.SetProperty("ABBREVIATED_NAME", AbbreviatedName); indicatorNode.SetProperty("CODE", Code); if (AnchorTime.HasValue) indicatorNode.SetProperty("ANCHOR_TIME", ServerFormats.ToTimeT(AnchorTime.Value)); if (null != ChartArea) indicatorNode.SetProperty("CHART_AREA_NAME", ChartArea.Name); indicatorNode.SetProperty("INDICATOR_TYPE", IndicatorType); indicatorNode.SetProperty("FORMAT", Format); indicatorNode.SetProperty("COLOR_TYPE", ColorType); indicatorNode.SetProperty("COLOR", Color); indicatorNode.SetProperty("UP_COLOR", UpColor); indicatorNode.SetProperty("DOWN_COLOR", DownColor); indicatorNode.SetProperty("TOP_COLOR", TopColor); indicatorNode.SetProperty("BOTTOM_COLOR", BottomColor); indicatorNode.SetProperty("TOP_GRADIENT_VALUE", TopGradientValue); indicatorNode.SetProperty("BOTTOM_GRADIENT_VALUE", BottomGradientValue); indicatorNode.SetProperty("USES_OWN_SCALE", OwnScale); indicatorNode.SetProperty("SHOW_IN_STATUS_LINE", ShowInStatusLine); indicatorNode.SetProperty("CATEGORY", Category); if (ParentId.HasValue) indicatorNode.SetProperty("PARENT_ID", ParentId); indicatorNode.SetProperty("ID", Id); XmlNode parametersNode = indicatorNode.NewNode("PARAMETERS"); foreach (var parameter in Parameters) { XmlNode parameterNode = parametersNode.NewNode("PARAMETER"); parameter.SaveLayout(parameterNode); } } /// /// Restores an indicator from the indicator library response from the server. /// /// The indicator node. /// The index. public void RestoreFromServer(XmlNode indicatorNode, int index) { string propertySuffix = index.ToString(); Id = indicatorNode.Property("id" + propertySuffix, -1); ReferenceName = indicatorNode.Property("reference_name" + propertySuffix); DisplayName = indicatorNode.Property("name" + propertySuffix); AbbreviatedName = indicatorNode.Property("abbreviated_name" + propertySuffix); long anchorTime = indicatorNode.Property("anchor_time" + propertySuffix, 0); if (anchorTime > 0) AnchorTime = ServerFormats.FromTimeT(anchorTime); Code = indicatorNode.Property("formula" + propertySuffix); Category = indicatorNode.Property("category" + propertySuffix); PrefersOwnPane = indicatorNode.Property("requires_own_pane" + propertySuffix, true); ChartAreaName = PrefersOwnPane ? "" : Charts.MAIN_CHARTAREA_NAME; Format = indicatorNode.Property("format" + propertySuffix); Chartable = indicatorNode.Property("chartable" + propertySuffix, true); ColorType = indicatorNode.PropertyEnum("color_type" + propertySuffix, IndicatorColorType.One); IndicatorType = indicatorNode.PropertyEnum("column_type" + propertySuffix, IndicatorType.Line); Color = indicatorNode.Property("one_color" + propertySuffix, Color.Blue); UpColor = indicatorNode.Property("up_color" + propertySuffix, Color.Black); DownColor = indicatorNode.Property("down_color" + propertySuffix, Color.Black); TopColor = indicatorNode.Property("top_color" + propertySuffix, Color.Green); if (TopColor.A == 0) TopColor = Color.Green; BottomColor = indicatorNode.Property("bottom_color" + propertySuffix, Color.White); if (BottomColor.A == 0) BottomColor = Color.White; TopGradientValue = indicatorNode.Property("top_value" + propertySuffix, 100.0); BottomGradientValue = indicatorNode.Property("bottom_value" + propertySuffix, 0.0); int parentId = indicatorNode.Property("parent_id" + propertySuffix, -1); if (parentId > -1) ParentId = parentId; OwnScale = false; } /// /// Creates a new instance of the ChartIndicator. /// public TiqColumn DeepCopy() { var copy = new TiqColumn { ReferenceName = ReferenceName, DisplayName = DisplayName, AbbreviatedName = AbbreviatedName, Code = Code, Format = Format, AnchorTime = AnchorTime, ChartAreaName = ChartAreaName, ColorType = ColorType, IndicatorType = IndicatorType, Color = Color, UpColor = UpColor, DownColor = DownColor, TopColor = TopColor, BottomColor = BottomColor, TopGradientValue = TopGradientValue, BottomGradientValue = BottomGradientValue, OwnScale = OwnScale, ShowInStatusLine = ShowInStatusLine, Category = Category, HelperId = HelperId, ParentId = ParentId, Id = Id, DoUpdate = DoUpdate, Parent = Parent, ChartArea = ChartArea, Chartable = Chartable, PrefersOwnPane = PrefersOwnPane }; foreach (var child in ChildIndicators) { copy.ChildIndicators.Add(child.DeepCopy()); } foreach (var parameter in Parameters) { copy.Parameters.Add(parameter.DeepCopy()); } return copy; } /// /// Restores the indicator from the layout XML. /// /// The indicator node. public void Restore(XmlNode indicatorNode) { ReferenceName = indicatorNode.Property("REFERENCE_NAME"); DisplayName = indicatorNode.Property("DISPLAY_NAME"); AbbreviatedName = indicatorNode.Property("ABBREVIATED_NAME"); Code = indicatorNode.Property("CODE"); ChartAreaName = indicatorNode.Property("CHART_AREA_NAME"); Format = indicatorNode.Property("FORMAT", "2"); long anchorTimeT = (long)indicatorNode.Property("ANCHOR_TIME", 0.0); if (anchorTimeT > 0) AnchorTime = ServerFormats.FromTimeT(anchorTimeT); ColorType = indicatorNode.PropertyEnum("COLOR_TYPE", IndicatorColorType.One); IndicatorType = indicatorNode.PropertyEnum("INDICATOR_TYPE", IndicatorType.Line); Color = indicatorNode.Property("COLOR", Color.Blue); UpColor = indicatorNode.Property("UP_COLOR", Color.Black); DownColor = indicatorNode.Property("DOWN_COLOR", Color.Black); TopColor = indicatorNode.Property("TOP_COLOR", Color.Green); if (TopColor.A == 0) TopColor = Color.Green; BottomColor = indicatorNode.Property("BOTTOM_COLOR", Color.White); if (BottomColor.A == 0) BottomColor = Color.White; TopGradientValue = indicatorNode.Property("TOP_GRADIENT_VALUE", 100.0); BottomGradientValue = indicatorNode.Property("BOTTOM_GRADIENT_VALUE", 0.0); int parentId = indicatorNode.Property("PARENT_ID", -1); if (parentId > 0) ParentId = parentId; OwnScale = indicatorNode.Property("USES_OWN_SCALE", false); ShowInStatusLine = indicatorNode.Property("SHOW_IN_STATUS_LINE", true); Category = indicatorNode.Property("CATEGORY"); Id = indicatorNode.Property("ID", -1); XmlNode parametersNode = indicatorNode.Node("PARAMETERS"); if (null == parametersNode) return; foreach (XmlNode parameterNode in parametersNode.ChildNodes) { var parameter = new IndicatorParameter(); parameter.Restore(parameterNode); Parameters.Add(parameter); } } /// /// Modifies Code to include all values of all current parameters. /// /// public string ResolvedReferenceName() { string toReturn = ReferenceName; foreach (var parameter in GetParameters().ToList()) { toReturn = Resolve(toReturn, parameter); } return toReturn; } /// /// Gets the parameters to use. If this indicator has a Parent, then use the parameters from the parent. /// /// private List GetParameters() { var parameters = Parameters.ToList(); if (null != Parent && Parent.Parameters.Count > 0) parameters = Parent.Parameters; return parameters; } /// /// Modifies Code to include all values of all current parameters. /// /// public string ResolvedCode() { string toReturn = Code; foreach (var parameter in GetParameters().ToList()) { toReturn = Resolve(toReturn, parameter); } return toReturn; } public string ResolvedAbbreviatedName() { string toReturn = AbbreviatedName; foreach (var parameter in GetParameters().ToList()) { toReturn = Resolve(toReturn, parameter); } return toReturn; } private string Resolve(string rawCode, IndicatorParameter parameter) { string reference = "[" + parameter.ReferenceId + "]"; // We need to apply invariant culture to the format so that we can handle different decimal symbols. return rawCode.Replace(reference, parameter.Value.ToString("N" + parameter.Format, CultureInfo.InvariantCulture)); } public GradientInfo GetGradientInfo() { GradientInfo gradientInfo = null; if (ColorType == IndicatorColorType.Gradient) { gradientInfo = new GradientInfo(); gradientInfo.Add(TopGradientValue, TopColor); gradientInfo.Add(BottomGradientValue, BottomColor); } return gradientInfo; } } public enum IndicatorType { Line, Bar, Arrow, Diamond, Bump, Background, StatusOnly } public enum IndicatorColorType { One, UpDown, Gradient } }