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 }
}