using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using System.Xml; using TradeIdeas.MiscSupport; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI { public partial class CompareCount : Form, ISaveLayout, IDemoMode, ICultureListener, ICompareCountMainControl, IChildable, IContextMenuStrip, ISnapToGrid, ISupportLimitedMode, ICanConfigure, IClearData, IFont, ICanRefreshNow, ISymbolLinkingChannel { private string _fileNameSaved; private readonly IConnectionMaster _connectionMaster; private LayoutManager _layoutManager = LayoutManager.Instance(); private List _phrases; private ISymbolLinkingForOwner _symbolLinking; private static int MAXCOUNT = 720; //At the 5 second interval this is about 1 hour. At 120 seconds interval this is about 1 day. //private const int MAXCOUNT = 720; //At the 5 second interval this is about 1 hour. At 120 seconds interval this is about 1 day. private const string _defaultFileName = "DEFAULT_CompareCount.WTI"; private const double DEMOTIMEDELAY = -20; // 20 minute delay when logged in as DEMO private const double _minYValue = 0.2; private bool _isChild = false; // new variable to set that dock panel is being used - RVH20210329 private bool _dockPanelMode = true; public bool IsChild { get { return _isChild; } set { _isChild = value; } } public Rectangle? ActualSize { get; set; } public TIFormType TIFormType { get { return TIProGUI.TIFormType.CompareCount; } } /// /// This gets called before any other code in the SaveLayout function. Currently this is aimed at the Scottrade addin but anything can set this code. /// public Action
PreSaveLayoutCode { get; set; } /// /// This gets called after SaveBase and it passes the XmlNode that the form is being saved to. This allows extensions to add properties to the layout. Access the layout XmlNode /// from a form using RestoredLayout. /// public Action SaveLayoutCode { get; set; } /// /// This is the xml that was used to restore this form. If this form wasn't layout-restored then this will be null. /// public XmlNode RestoredLayout { get; set; } /// /// Returns the current configuration string used for collaboration. /// /// public string GetConfigString() { // unimplemented for now return ""; } public ContextMenuStrip MyContextMenuStrip { get { return contextMenuStrip1; } } public CompareCount(IConnectionMaster connectionMaster) { _limitedMode = GuiEnvironment.LimitedMode; _connectionMaster = connectionMaster; InitializeComponent(); selectTheFont(); _phrases = GuiEnvironment.XmlConfig.Node("COMPARE_COUNT").Node("PHRASES"); MAXCOUNT = GuiEnvironment.XmlConfig.Node("COMPARE_COUNT").Node("MAXCOUNT").Property("VALUE", MAXCOUNT); saveToCloudToolStripMenuItem.Image = SaveToCloud.WindowIconCache.MenuImage; if (!IsHandleCreated) CreateHandle(); WindowIconCache.SetIcon(this); tickerSymbol1.CompareCountOwner = this; _bullishSeries = new ConfigManager(this, connectionMaster, this); _bearishSeries = new ConfigManager(this, connectionMaster, this); Settings = Settings.DecentSample(); _symbolLinking = new SymbolLinking(this); ChartColorTheme(); //Update window title from legend UpdateWindowTitle(); //Allow scrolling and zooming of the x-axis chart1.ChartAreas[0].CursorX.AutoScroll = true; chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true; chart1.ChartAreas[0].CursorX.IsUserEnabled = true; // Set scrollbar colors chart1.ChartAreas[0].AxisX.ScrollBar.BackColor = Color.White; chart1.ChartAreas[0].AxisX.ScrollBar.ButtonColor = Color.FromArgb(224, 224, 224); chart1.ChartAreas[0].AxisX.ScrollBar.LineColor = Color.Black; chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true; // Set labels chart1.ChartAreas[0].AxisY.Title = "Alerts/Sec"; // Set click event for show points/percent/both/Legend showBothToolStripMenuItem.Click += showPlots_Click; showPointsToolStripMenuItem.Click += showPlots_Click; showPercentToolStripMenuItem.Click += showPlots_Click; showLegendToolStripMenuItem.Click += showPlots_Click; AddExtraMenuItems(GuiEnvironment.GetExtraMenuItems().Where(x => (x.TIFormType == TIFormType.All || x.TIFormType == TIFormType.CompareCount) && !x.IsSymbolSpecific).ToList(), contextMenuStrip1.Items); SetSnapToGrid(GuiEnvironment.SnapToGrid); } private void ChartColorTheme() { if (_settings.isDark) { // Dark color theme chart1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.ChartAreas[0].AxisX.LabelStyle.ForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisX.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX.MajorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX.MinorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX.MinorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX.TitleForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisX2.LabelStyle.ForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisX2.MajorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX2.MajorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX2.MinorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX2.MinorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisX2.TitleForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisY.LabelStyle.ForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisY.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY.MajorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY.MinorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY.MinorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY.TitleForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisY2.LabelStyle.ForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisY2.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY2.MajorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY2.MajorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY2.MinorGrid.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY2.MinorTickMark.LineColor = System.Drawing.Color.Gray; chart1.ChartAreas[0].AxisY2.TitleForeColor = System.Drawing.Color.White; chart1.ChartAreas[0].BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.ChartAreas[0].BorderColor = System.Drawing.Color.Gray; chart1.ChartAreas[1].BackColor = System.Drawing.Color.Transparent; chart1.ChartAreas[1].BorderColor = System.Drawing.Color.Gray; chart1.Legends[0].ForeColor = System.Drawing.Color.White; chart1.Series[0].LabelBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.Series[0].LabelForeColor = System.Drawing.Color.White; chart1.Series[1].LabelBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.Series[1].LabelForeColor = System.Drawing.Color.White; chart1.Series[2].LabelBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.Series[2].LabelForeColor = System.Drawing.Color.White; chart1.Series[3].LabelBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37))))); chart1.Series[3].LabelForeColor = System.Drawing.Color.White; chart1.Series[4].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[4].LabelForeColor = System.Drawing.Color.White; chart1.Series[5].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[5].LabelForeColor = System.Drawing.Color.White; chart1.Series[6].BorderColor = System.Drawing.Color.Gray; chart1.Series[6].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[6].LabelForeColor = System.Drawing.Color.White; } else { //Light Color theme chart1.BackColor = System.Drawing.Color.White; chart1.ChartAreas[0].AxisX.LabelStyle.ForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.MajorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.MinorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.MinorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX.TitleForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.LabelStyle.ForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.MajorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.MajorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.MinorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.MinorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisX2.TitleForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.LabelStyle.ForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.MajorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.MinorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.MinorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY.TitleForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.LabelStyle.ForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.MajorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.MajorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.MinorGrid.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.MinorTickMark.LineColor = System.Drawing.Color.Black; chart1.ChartAreas[0].AxisY2.TitleForeColor = System.Drawing.Color.Black; chart1.ChartAreas[0].BackColor = System.Drawing.Color.Transparent; chart1.ChartAreas[0].BorderColor = System.Drawing.Color.Black; chart1.ChartAreas[1].BackColor = System.Drawing.Color.Transparent; chart1.ChartAreas[1].BorderColor = System.Drawing.Color.Black; chart1.Legends[0].ForeColor = System.Drawing.Color.Black; chart1.Series[0].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[0].LabelForeColor = System.Drawing.Color.Black; chart1.Series[1].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[1].LabelForeColor = System.Drawing.Color.Black; chart1.Series[2].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[2].LabelForeColor = System.Drawing.Color.Black; chart1.Series[3].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[3].LabelForeColor = System.Drawing.Color.Black; chart1.Series[4].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[4].LabelForeColor = System.Drawing.Color.Black; chart1.Series[5].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[5].LabelForeColor = System.Drawing.Color.Black; chart1.Series[6].BorderColor = System.Drawing.Color.Black; chart1.Series[6].LabelBackColor = System.Drawing.Color.Transparent; chart1.Series[6].LabelForeColor = System.Drawing.Color.Black; } } private void AddExtraMenuItems(List menuItems, ToolStripItemCollection into) { foreach (TIToolStripMenuItem menuItem in menuItems) { AddExtraMenuItem(menuItem, into); } } private void AddExtraMenuItem(TIToolStripMenuItem menuItemTemplate, ToolStripItemCollection into) { TIToolStripMenuItem thisMenuItem = menuItemTemplate.Clone(); thisMenuItem.Click += new EventHandler(menuItem_Click); into.Add(thisMenuItem); if (menuItemTemplate.HasDropDownItems) AddExtraMenuItems(menuItemTemplate.DropDownItems.Cast().ToList(), thisMenuItem.DropDownItems); } void menuItem_Click(object sender, EventArgs e) { TIToolStripMenuItem menuItem = sender as TIToolStripMenuItem; if (null != menuItem) menuItem.ClickedCode(menuItem, this); } private void UpdateWindowTitle() { string windowTitle; windowTitle = _phrases.Node("WINDOW_TITLE").PropertyForCulture("TEXT", "***"); string bullName = _bullishSeries.LegendText; string bearName = _bearishSeries.LegendText; if (((bullName != null) && (bearName != null)) && ((bullName != "") && (bearName != ""))) windowTitle = bullName + " vs. " + bearName; if (_connectionMaster.LoginManager.IsDemo) { windowTitle += GuiEnvironment.XmlConfig.Node("COMMON_PHRASES").Node("DEMO_DISCLAIMER").PropertyForCulture("TEXT", "***"); saveToCloudToolStripMenuItem.Enabled = false; } else { saveToCloudToolStripMenuItem.Enabled = true; } Text = windowTitle; // Update context menu text List sharedPhrases = GuiEnvironment.XmlConfig.Node("ALERT_WINDOW").Node("PHRASES"); toolStripMenuItemConfigure.Text = sharedPhrases.Node("CONFIGURE").PropertyForCulture("TEXT", "***"); toolStripMenuItemDuplicate.Text = sharedPhrases.Node("DUPLICATE").PropertyForCulture("TEXT", "***"); toolStripMenuItemClear.Text = sharedPhrases.Node("CLEAR").PropertyForCulture("TEXT", "***"); //toolStripMenuItemSymbolLinking.Text = sharedPhrases.Node("SYMBOL_LINKING_MENU").PropertyForCulture("TEXT", "***"); toolStripMenuItemSaveAs.Text = sharedPhrases.Node("SAVE_AS").PropertyForCulture("TEXT", "***"); saveAsDefaultToolStripMenuItem.Text = sharedPhrases.Node("SAVE_AS_DEFAULT").PropertyForCulture("TEXT", "***"); showPercentToolStripMenuItem.Text = _phrases.Node("SHOW_PERCENT").PropertyForCulture("TEXT", "***"); showPointsToolStripMenuItem.Text = _phrases.Node("SHOW_POINTS").PropertyForCulture("TEXT", "***"); showBothToolStripMenuItem.Text = _phrases.Node("SHOW_BOTH").PropertyForCulture("TEXT", "***"); showLegendToolStripMenuItem.Text = _phrases.Node("SHOW_LEGEND").PropertyForCulture("TEXT", "***"); darkBackgroundToolStripMenuItem.Text = _phrases.Node("DARK_BACKGROUND").PropertyForCulture("TEXT", "***"); //Allows us to hide item for ScottradeELITE if (_phrases.Node("SAVE_TO_CLOUD").PropertyForCulture("TEXT", "***") == "---") { saveToCloudToolStripMenuItem.Visible = false; } else { saveToCloudToolStripMenuItem.Text = _phrases.Node("SAVE_TO_CLOUD").PropertyForCulture("TEXT", "***"); } //Allows us to hide item for ScottradeELITE if (_phrases.Node("SMALL_BORDERS").PropertyForCulture("TEXT", "***") == "---") { smallBordersToolStripMenuItem.Visible = false; } else { smallBordersToolStripMenuItem.Text = _phrases.Node("SMALL_BORDERS").PropertyForCulture("TEXT", "***"); } // Update legend and secondary Y axis of the percent series chart1.Series["Percent"].LegendText = "% " + bullName; chart1.ChartAreas[0].AxisY2.Title = chart1.Series["Percent"].LegendText; GuiEnvironment.HideMenuItems(contextMenuStrip1.Items); } void IDemoMode.OnDemoModeChanged() { UpdateWindowTitle(); } void ICultureListener.CultureChanged() { // Not very exciting, but the DEMO warning was already translated, so why not. UpdateWindowTitle(); } private Settings _settings; public Settings Settings { get { _settings.BearConfigString = _bearishSeries.Settings; _settings.BullConfigString = _bullishSeries.Settings; _settings.showBoth = showBothToolStripMenuItem.Checked; _settings.showPercent = showPercentToolStripMenuItem.Checked; _settings.showPoints = showPointsToolStripMenuItem.Checked; _settings.smallBorders = smallBordersToolStripMenuItem.Checked; _settings.showLegend = showLegendToolStripMenuItem.Checked; _settings.isDark = darkBackgroundToolStripMenuItem.Checked; return _settings.Clone(); } set { _settings = value.Clone(); smallBordersToolStripMenuItem.Checked = _settings.smallBorders; darkBackgroundToolStripMenuItem.Checked = _settings.isDark; showPointsToolStripMenuItem.Checked = _settings.showPoints; showBothToolStripMenuItem.Checked = _settings.showBoth; showPercentToolStripMenuItem.Checked = _settings.showPercent; showLegendToolStripMenuItem.Checked = _settings.showLegend; _bullishSeries.Settings = _settings.BullConfigString; _bullishSeries.ResetSeries(); _bullishSeries.Add(chart1.Series[0], _settings.FastRecentWeight, _settings.SecondsPerDataPoint); _bullishSeries.SetSumSeries(chart1.Series[4]); _bearishSeries.Settings = _settings.BearConfigString; _bearishSeries.ResetSeries(); _bearishSeries.Add(chart1.Series[2], _settings.FastRecentWeight, _settings.SecondsPerDataPoint); _bearishSeries.SetSumSeries(chart1.Series[5]); timer1.Interval = _settings.SecondsPerDataPoint * 1000; if (_settings.ShowOneLine) { chart1.Series[1].Points.Clear(); chart1.Series[3].Points.Clear(); } else { // Show two lines. _bullishSeries.Add(chart1.Series[1], _settings.SlowRecentWeight, _settings.SecondsPerDataPoint); _bearishSeries.Add(chart1.Series[3], _settings.SlowRecentWeight, _settings.SecondsPerDataPoint); } } } private ConfigManager _bullishSeries; private ConfigManager _bearishSeries; /// /// Standard cleanup. Stop requesting data! /// /// Unused. /// Unused. private void CompareCount_FormClosing(object sender, FormClosingEventArgs e) { if (timer1 != null) timer1.Stop(); _bullishSeries.Settings = null; _bearishSeries.Settings = null; foreach (var series in chart1.Series) series.Points.Clear(); contextMenuStrip1.Opening -= LayoutManager.Instance().contextMenuStrip_Opening; } private class ConfigManager { private readonly ICompareCountMainControl _mainControl; private readonly Control _invoker; private readonly IConnectionMaster _connectionMaster; public StreamingAlerts _dataProvider; private double _recentCount; private String _settings; private Series SumSeries; private int _secondsPerDataPoint; public class SeriesDescription { public Series Series { get; private set; } public double RecentWeight { get; private set; } public string LegendText { get { return Series.LegendText; } set { Series.LegendText = value; Series.IsVisibleInLegend = value != ""; } } private double _previousCount; private double _previousCountWeight = 0.0; private bool _recentHasBeenCreated; public SeriesDescription(Series series, double recentWeight) { Series = series; RecentWeight = recentWeight; LegendText = ""; // A good default until the server tells us the real name. } public void UpdateLastPoint(double recentCount, DateTime time, bool freeze) { if (null == Series.Points) return; double currentValue; currentValue = recentCount * RecentWeight + _previousCount * _previousCountWeight; currentValue /= RecentWeight + _previousCountWeight; double [] valueList = { currentValue }; if (_recentHasBeenCreated) { /*When we've cleared data points with the clear function, this method UpdateLastPoint will still be called during the timer_Tick event. As a result, there will be a time where the point will be 0, which will cause an exception...*/ if (Series.Points.Count != 0) { Series.Points[Series.Points.Count - 1].YValues = valueList; Series.Points[Series.Points.Count - 1].Tag = 0; //Series.Points.RemoveAt(Series.Points.Count - 1); //Series.Points.Add(valueList); Series.Points[Series.Points.Count - 1].AxisLabel = time.ToString(GuiEnvironment.AlertTimeShortFormat); // Show time to the minute } else { return; } } else { //Remove oldest data once we reach MAXCOUNT if (Series.Points.Count == MAXCOUNT) { //DataPoint point0 = Series.Points[0].Clone(); Series.Points.RemoveAt(0); } Series.Points.Add(valueList); Series.Points[Series.Points.Count - 1].Tag = 1; Series.Points[Series.Points.Count - 1].AxisLabel = time.ToString(GuiEnvironment.AlertTimeShortFormat); // Show time to the minute if (Series.Points.Count == 1) // A line chart with only one data point seems to be invisible. So we switch // to this mode to make it visible. Series.ChartType = SeriesChartType.Point; else Series.ChartType = SeriesChartType.Line; } if (freeze) { // Freeze this data point as is. Start a new data point the next time we get data. _recentHasBeenCreated = false; _previousCount = currentValue; // When we first start, the unknown weight is 100%. We have no previous data, so the // previous data weight is 0%. These two have to add up to 100%. As the previous // weight grows over time, the unknown wieght must shrink. double unknownWeight = 1.0 - _previousCountWeight; // We just added a new point. That data was merged into the _previousCount. So // the unknown shrinks and the prevous weight grows. The more weight we give to // that last point, the more quickly the unknown shrinks. unknownWeight *= 1.0 - RecentWeight; // Save the new previous weight for next time. _previousCountWeight = 1.0 - unknownWeight; } else // Overwrite this data point next time. _recentHasBeenCreated = true; } } public ConfigManager(Control invoker, IConnectionMaster connectionMaster, ICompareCountMainControl mainControl) { _invoker = invoker; _connectionMaster = connectionMaster; _mainControl = mainControl; } void dataProvider_StreamingAlertsData(List data, StreamingAlerts source) { try { DateTime time = ServerFormats.Now; if (_connectionMaster.LoginManager.IsDemo) time = time.AddMinutes(DEMOTIMEDELAY); //Subtract time delay when logged in as DEMO if (_invoker.InvokeRequired) _invoker.Invoke((MethodInvoker)delegate { dataProvider_StreamingAlertsData(data, source); }); else if (source == _dataProvider) { int count = 0; CompareCount test = (CompareCount)_invoker; // Add logic to avoid exceptions when test is null. bool testIsAvailable = true; if (test == null) testIsAvailable = false; foreach (var rowData in data) { if (rowData.GetAsString("HISTORICAL") != "1") count++; if (testIsAvailable) { if (source == test._bearishSeries._dataProvider) { test.tickerSymbol1.addSymbol(test._bearishSeries._dataProvider.Config, rowData, Color.Red); } else if (source == test._bullishSeries._dataProvider) { test.tickerSymbol1.addSymbol(test._bullishSeries._dataProvider.Config, rowData, Color.Green); } } DateTime? possibleTime = rowData.GetTime(); if (possibleTime.HasValue) time = possibleTime.Value; } // Counts of zero are now displayed // Add logic to avoid dividing by something too small if (_secondsPerDataPoint >= 5) _recentCount += (double)count / (double)_secondsPerDataPoint; else _recentCount += (double)count / 5.0; // To avoid an underflow exception if (_recentCount <= 0.01) _recentCount = 0.0; foreach (var series in _all_EMASeries) series.UpdateLastPoint(_recentCount, time, false); UpdateSumSeries(_recentCount); // Update axis scale and percent series _mainControl.CheckMinMax(); } } catch (Exception e) { string debugView = e.ToString(); } } /// /// Copies the chart series to the local sum series. /// /// public void SetSumSeries(Series series) { System.Diagnostics.Debug.Assert(null != series); SumSeries = new Series(); SumSeries = series; //Need to add a seed point to avoid invalid data for the stackedcolumn100 chart if (SumSeries.Points.Count == 0) SumSeries.Points.AddY(0.0001); } /// /// Updates the sumseries with the current count data. /// SumSeries contains just one point. /// /// private void UpdateSumSeries(double recentCount) { if ((SumSeries == null) || (SumSeries.Points == null) || (recentCount == 0)) return; if (SumSeries.Points.Count == 0) { SumSeries.Points.AddY(recentCount); } else { double UpdatedValue = SumSeries.Points[0].YValues[0] + recentCount; double[] valueList = { UpdatedValue }; SumSeries.Points[0].YValues = valueList; } } public void StartNewDataPoint() { DateTime currentTime = ServerFormats.Now; if (_connectionMaster.LoginManager.IsDemo) currentTime = currentTime.AddMinutes(DEMOTIMEDELAY); //Subtract time delay when logged in as DEMO foreach (var series in _all_EMASeries) series.UpdateLastPoint(_recentCount, currentTime, true); UpdateSumSeries(_recentCount); // Update axis scale and percent series _mainControl.CheckMinMax(); _recentCount = 0; } void dataProvider_StreamingAlertsConfig(StreamingAlerts source) { if (_invoker.InvokeRequired) _invoker.Invoke((MethodInvoker)delegate { dataProvider_StreamingAlertsConfig(source); }); else if (source == _dataProvider) { _settings = source.Config; LegendText = source.WindowName; _mainControl.CheckWindowName(); } } /// /// Get or set the legend text for the strategy. /// Presumably you don't want one entry for each series, but one per strategy. /// For simplicity we always apply the legend to the first series added. /// public string LegendText { get { if (_all_EMASeries.Count == 0) return null; else return _all_EMASeries[0].LegendText; } private set { if (_all_EMASeries.Count > 0) _all_EMASeries[0].LegendText = value; } } public string Settings { get { return _settings; } set { _settings = value; if (null != _dataProvider) { _dataProvider.Stop(); _dataProvider.StreamingAlertsConfig -= dataProvider_StreamingAlertsConfig; _dataProvider.StreamingAlertsData -= dataProvider_StreamingAlertsData; _dataProvider = null; } if (null == value) _dataProvider = null; else { _dataProvider = _connectionMaster.StreamingAlertsManager.GetAlerts(_settings, saveToMru: true); _dataProvider.StreamingAlertsConfig += new StreamingAlertsConfig(dataProvider_StreamingAlertsConfig); _dataProvider.StreamingAlertsData += new StreamingAlertsData(dataProvider_StreamingAlertsData); _dataProvider.Start(); } } } private readonly List _all_EMASeries = new List(); public void ResetSeries() { _all_EMASeries.Clear(); _recentCount = 0; } public void Add(Series series, double recentWeight, int secondsPerDataPoint) { _secondsPerDataPoint = secondsPerDataPoint; System.Diagnostics.Debug.Assert(null != series); _all_EMASeries.Add(new SeriesDescription(series, recentWeight)); series.Points.Clear(); } } private void timer1_Tick(object sender, EventArgs e) { _bullishSeries.StartNewDataPoint(); _bearishSeries.StartNewDataPoint(); if ((chart1.ChartAreas[0].AxisX.ScrollBar.IsVisible) && chart1.Series[0].Points.Count > 0) { //Return scrollbar to the extreme right if it is close to the right end otherwise do not change current view if ((chart1.Series[0].Points.Count - chart1.ChartAreas[0].AxisX.ScaleView.Position) <= (chart1.ChartAreas[0].AxisX.ScaleView.Size)) chart1.ChartAreas[0].AxisX.ScaleView.Position = chart1.ChartAreas[0].AxisX.ScaleView.ViewMaximum - chart1.ChartAreas[0].AxisX.ScaleView.Size; } } private void UpdatePercentSeries() { if ( !chart1.Disposing && chart1.Series.Count > 0 && ((chart1.Series[0].Points.Count > 0) && (chart1.Series[2].Points.Count > 0) && (chart1.Series[0].Points.Count == chart1.Series[2].Points.Count))) { if ((int)chart1.Series[0].Points[chart1.Series[0].Points.Count - 1].Tag != (int)chart1.Series[2].Points[chart1.Series[0].Points.Count - 1].Tag) return; double ratio = 0; double sum = 0; double [] bull = chart1.Series[0].Points[chart1.Series[0].Points.Count - 1].YValues; double[] bear = chart1.Series[2].Points[chart1.Series[2].Points.Count - 1].YValues; sum = bull[0] + bear[0]; if (sum == 0) ratio = 0.5 * 100; else ratio = (bull[0] / sum) * 100; double[] valueList = { ratio }; // Modify or add percent data if (( (int) chart1.Series[0].Points[chart1.Series[0].Points.Count - 1].Tag == 0 ) && (chart1.Series["Percent"].Points.Count > 0)) chart1.Series["Percent"].Points[chart1.Series["Percent"].Points.Count - 1].YValues = valueList; else { if (chart1.Series["Percent"].Points.Count == MAXCOUNT) chart1.Series["Percent"].Points.RemoveAt(0); chart1.Series["Percent"].Points.Add(valueList); } chart1.Series["Percent"].Points[chart1.Series["Percent"].Points.Count - 1].AxisLabel = chart1.Series[0].Points[chart1.Series[0].Points.Count - 1].AxisLabel; } } private const string FORM_TYPE = "COMPARE_COUNT_WINDOW"; static public void RegisterLayout() { // change parameters to accommodate dock panel changes - RVH20210402 //LayoutManager.Instance().AddRestoreRule(FORM_TYPE, (RestoreLayout)delegate(XmlNode description, bool ignorePosition, bool cascadePosition) LayoutManager.Instance().AddRestoreRule(FORM_TYPE, (RestoreLayout)delegate (XmlNode description, bool ignorePosition, bool cascadePosition, bool dockPanelMode, string mainDockPanelName, string mainDockPanelTitle, string dockPanelID) { IConnectionMaster connectionMaster = GuiEnvironment.FindConnectionMaster(description.Property("CONNECTION")); if (null == connectionMaster) { // We could report an error here, but it's simpler just to do nothing. Any error message we tried to // report would probably be confusing at best to the user. } else { CompareCount form = new CompareCount(connectionMaster); // change parameters to accommodate dock panel changes - RVH20210402 //form.Restore(description, ignorePosition, cascadePosition); form.Restore(description, ignorePosition, cascadePosition, dockPanelMode, mainDockPanelName, mainDockPanelTitle, dockPanelID); form.RestoredLayout = description; } }); } private bool _pinned = false; public bool Pinned { get { return _pinned; } set { _pinned = value; } } // change parameters to accommodate dock panel changes - RVH20210402 //public void Restore(XmlNode description, bool ignorePosition, bool cascadePosition) public void Restore(XmlNode description, bool ignorePosition, bool cascadePosition, bool dockPanelMode = false, string mainDockPanelName = "", string mainDockPanelTitle = "", string dockPanelID = "") { //restore the "small borders" functionality before restoring form position _settings.Load(description); // change parameters to accommodate dock panel changes - RVH20210402 // LayoutManager.RestoreBase(description, this, ignorePosition, cascadePosition); LayoutManager.RestoreBase(description, this, ignorePosition, cascadePosition, null, false, dockPanelMode, mainDockPanelName, mainDockPanelTitle, dockPanelID); _dockPanelMode = dockPanelMode; smallBordersToolStripMenuItem.Checked = _settings.smallBorders; darkBackgroundToolStripMenuItem.Checked = _settings.isDark; _pinned = description.Property("PINNED", false); pinnedToolStripMenuItem.Checked = _pinned; ChartColorTheme(); // only call this if not in dock panel mode - RVH20210329 if (!_dockPanelMode) setBorders(); Settings = _settings; UpdateChartDisplay(); } public static readonly WindowIconCache WindowIconCache = new WindowIconCache("COMPARE_COUNT"); void ISaveLayout.SaveLayout(XmlNode parent) { if (null != PreSaveLayoutCode) PreSaveLayoutCode(this); XmlNode description = LayoutManager.SaveBase(parent, this, FORM_TYPE, ActualSize); if (null != SaveLayoutCode) SaveLayoutCode(this, description); description.SetProperty("PINNED", _pinned); _settings.Save(description); } private void toolStripMenuItemDuplicate_Click(object sender, EventArgs e) { LayoutManager.Instance().Duplicate(this); } private void smallBordersToolStripMenuItem_Click(object sender, EventArgs e) { setBorders(); } private void setBorders() { _settings.smallBorders = smallBordersToolStripMenuItem.Checked; if (smallBordersToolStripMenuItem.Checked) FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; else FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; } private void toolStripMenuItemSaveAs_Click(object sender, EventArgs e) { LayoutManager layoutManager = LayoutManager.Instance(); SaveFileDialog dialog = new SaveFileDialog(); if (null != layoutManager.Directory) dialog.InitialDirectory = layoutManager.Directory; dialog.Filter = GuiEnvironment.XmlConfig.Node("COMPARE_COUNT").Node("PHRASES").Node("WINDOW_FILTER").PropertyForCulture("TEXT", "***"); dialog.DefaultExt = "WTI"; string fileName = ""; if (_fileNameSaved == null) { fileName = GuiEnvironment.XmlConfig.Node("COMPARE_COUNT").Node("PHRASES").Node("FILE_PREFIX").PropertyForCulture("TEXT", "***") + "Test"; // +_shortWindowName; } else { fileName = _fileNameSaved; } dialog.FileName = FileNameMethod.QuoteFileName(fileName); if (dialog.ShowDialog() == DialogResult.OK) { layoutManager.SaveOne(this, dialog.FileName); _fileNameSaved = Path.GetFileName(dialog.FileName); } dialog.Dispose(); } private void toolStripMenuItemConfigure_Click(object sender, EventArgs e) { DoConfiguration(); } private void DoConfiguration() { Settings clonedSettings = _settings.Clone(); CompareCountConfig form = new CompareCountConfig(_connectionMaster, clonedSettings); form.ShowDialog(); if (form.DialogResult == System.Windows.Forms.DialogResult.OK) { clearAllPoints(); Settings = clonedSettings; UpdateWindowTitle(); } form.Dispose(); } WindowIconCache ISaveLayout.WindowIconCache { get { return WindowIconCache; } } private void toolStripMenuItemClear_Click(object sender, EventArgs e) { clearAllPoints(); tickerSymbol1.reset(); } private void clearAllPoints() //clears all points for series..restarts again { chart1.SuspendLayout(); // Reset zoom operations when we clear data points while (chart1.ChartAreas[0].AxisX.ScaleView.IsZoomed) chart1.ChartAreas[0].AxisX.ScaleView.ZoomReset(); foreach (var series in chart1.Series) series.Points.Clear(); Settings = _settings; chart1.ResumeLayout(); chart1.Update(); } void ICompareCountMainControl.CheckMinMax() { try { UpdatePercentSeries(); SetYAxisScale(); chart1.ChartAreas[0].RecalculateAxesScale(); } catch (Exception e) { string debugView = e.ToString(); } } void ICompareCountMainControl.CheckWindowName() { UpdateWindowTitle(); } /// /// Be smart when creating the scale of the y axis when we have y values of one or less. /// private void SetYAxisScale() { // Check the green fast series if (chart1.Series[0].Enabled && (chart1.Series[0].Points.Count > 0) && (chart1.Series[0].Points.FindMaxByValue("Y1", 0).YValues[0] <= _minYValue)) { chart1.ChartAreas[0].AxisY.Maximum = _minYValue; } else { // Return once we have Y data greater than _minYValue chart1.ChartAreas[0].AxisY.Maximum = Double.NaN; //set to auto return; } // Check the red fast series if (chart1.Series[2].Enabled && (chart1.Series[2].Points.Count > 0) && (chart1.Series[2].Points.FindMaxByValue("Y1", 0).YValues[0] <= _minYValue)) { chart1.ChartAreas[0].AxisY.Maximum = _minYValue; } else { // Return once we have Y data greater than _minYValue chart1.ChartAreas[0].AxisY.Maximum = Double.NaN; //set to auto return; } } private void showPlots_Click(object sender, EventArgs e) { UpdateCheckedItems(sender.ToString()); Settings.showPoints = showPointsToolStripMenuItem.Checked; Settings.showBoth = showBothToolStripMenuItem.Checked; Settings.showPercent = showPercentToolStripMenuItem.Checked; Settings.showLegend = showLegendToolStripMenuItem.Checked; UpdateChartDisplay(); } private void UpdateCheckedItems(string item) { // Update checked items if (item == "Show Points") { showPointsToolStripMenuItem.Checked = true; showPercentToolStripMenuItem.Checked = false; showBothToolStripMenuItem.Checked = false; } else if (item == "Show Percent") { showPointsToolStripMenuItem.Checked = false; showPercentToolStripMenuItem.Checked = true; showBothToolStripMenuItem.Checked = false; } else if (item == "Show Both") { showPointsToolStripMenuItem.Checked = false; showPercentToolStripMenuItem.Checked = false; showBothToolStripMenuItem.Checked = true; } } public void UpdateChartDisplay() { // Show appropiate axis labels chart1.ChartAreas[0].AxisY.LabelStyle.Enabled = (showBothToolStripMenuItem.Checked) || (showPointsToolStripMenuItem.Checked); chart1.ChartAreas[0].AxisY2.LabelStyle.Enabled = (showBothToolStripMenuItem.Checked) || (showPercentToolStripMenuItem.Checked); // chart1.ChartAreas[0].AxisY2.MajorGrid.Enabled = (showBothToolStripMenuItem.Checked) || (showPercentToolStripMenuItem.Checked); chart1.ChartAreas[0].AxisY2.MajorGrid.Enabled = showPercentToolStripMenuItem.Checked; //show Legend foreach (Legend legend in chart1.Legends) { legend.Enabled = showLegendToolStripMenuItem.Checked; } // Display appropriate series chart1.Series[0].Enabled = (showBothToolStripMenuItem.Checked) || (showPointsToolStripMenuItem.Checked); chart1.Series[1].Enabled = (showBothToolStripMenuItem.Checked) || (showPointsToolStripMenuItem.Checked); chart1.Series[2].Enabled = (showBothToolStripMenuItem.Checked) || (showPointsToolStripMenuItem.Checked); chart1.Series[3].Enabled = (showBothToolStripMenuItem.Checked) || (showPointsToolStripMenuItem.Checked); chart1.Series["Percent"].Enabled = (showBothToolStripMenuItem.Checked) || (showPercentToolStripMenuItem.Checked); if (chart1.Series["Percent"].Enabled) if (chart1.Series[0].Enabled) // Make this skinny so it doesn't hide the other items. chart1.Series["Percent"].BorderWidth = 1; else chart1.Series["Percent"].BorderWidth = 3; } private void saveAsDefaultToolStripMenuItem_Click(object sender, EventArgs e) { string programDirFileName = _layoutManager.Directory + "\\" + _defaultFileName; _layoutManager.SaveOne(this, programDirFileName); } private void saveToCloudToolStripMenuItem_Click(object sender, EventArgs e) { SaveToCloud.DoIt(_connectionMaster.SendManager, this); } public void SetSnapToGrid(bool enabled) { formSnapper1.Enabled = enabled; if (GuiEnvironment.RunningWin10 && enabled) { formSnapper1.Win10HeightAdjustment = GuiEnvironment.HEIGHT_INCREASE; formSnapper1.Win10WidthAdjustment = GuiEnvironment.WIDTH_INCREASE; } } private void darkBackgroundToolStripMenuItem_Click(object sender, EventArgs e) { darkBackgroundToolStripMenuItem.Checked = !darkBackgroundToolStripMenuItem.Checked; _settings.isDark = darkBackgroundToolStripMenuItem.Checked; ChartColorTheme(); } private void toolStripMenuItemSymbolLinking_Click(object sender, EventArgs e) { _symbolLinking.ShowDialog(); } private bool _limitedMode = false; public bool LimitedMode { get { return _limitedMode; } set { _limitedMode = value; } } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { GuiEnvironment.HideMenuItems(contextMenuStrip1.Items); GuiEnvironment.EnforceLimitedMode(contextMenuStrip1); // add symbol linking channels here symbolLinkingToolStripMenuItem.DropDown.Items.Clear(); //Detect if the current window is in floating mode var floatingMode = string.IsNullOrEmpty(GuiEnvironment.GetDockWindowID(this)); foreach (KeyValuePair channel in SymbolLinkChannels.Channels) { if (channel.Key == SymbolLinkChannels.DockWindowChannel && floatingMode) continue; ToolStripMenuItem menuItem = new ToolStripMenuItem(channel.Key, null, delegate { tickerSymbol1.SetLinkChannel(channel.Key); // change window icon SymbolLinkingChannelsHelper.SetFormIcon(this, "CC", channel.Key); }); menuItem.BackColor = channel.Value; Color foreColor = GradientInfo.AltColor(channel.Value); menuItem.ForeColor = foreColor; menuItem.Checked = tickerSymbol1.GetLinkChannel() == channel.Key; symbolLinkingToolStripMenuItem.DropDown.Items.Add(menuItem); } } public void SetConfiguration(string config) { // not implemented } public void ShowConfiguration() { DoConfiguration(); } public List GetStrategyConfigs() { List toReturn = new List(); StrategyConfig bullishStrategy; bullishStrategy.Config = _settings.BullConfigString; bullishStrategy.ConfigurationType = TIProData.Configuration.ConfigurationType.Alerts; toReturn.Add(bullishStrategy); StrategyConfig bearishStrategy; bearishStrategy.Config = _settings.BearConfigString; bearishStrategy.ConfigurationType = TIProData.Configuration.ConfigurationType.Alerts; toReturn.Add(bearishStrategy); return toReturn; } private void pinnedToolStripMenuItem_Click(object sender, EventArgs e) { _pinned = pinnedToolStripMenuItem.Checked; } public void onClearData() { toolStripMenuItemClear.PerformClick(); } public void selectTheFont() { // Change fonts for only the context menu and symbol ticker controls contextMenuStrip1.Font = GuiEnvironment.FontSettings; tickerSymbol1.Font = GuiEnvironment.FontSettings; tickerSymbol1.Height = GuiEnvironment.FontSettings.Height + (int)(GuiEnvironment.FontSettings.Height/2); } private void CompareCount_TextChanged(object sender, EventArgs e) { // change Text of parent form if running in dock panel mode - RVH20210329 if (_dockPanelMode) { Form parent = (Form)this.Parent; if (parent != null) parent.Text = this.Text; } } public void RefreshNow() { Settings = _settings; } /// /// Set the symbol link channel from symbol linking /// /// The link channel void ISymbolLinkingChannel.SetLinkChannel(string linkChannel) { tickerSymbol1.SetLinkChannel(linkChannel); // change window icon SymbolLinkingChannelsHelper.SetFormIcon(this, "CC", linkChannel); } /// /// Get the symbol link channel /// /// string ISymbolLinkingChannel.GetLinkChannel() { return tickerSymbol1.GetLinkChannel(); } } public interface ICompareCountMainControl { void CheckMinMax(); void CheckWindowName(); } public class Settings { public String BullConfigString; public String BearConfigString; public int SecondsPerDataPoint; public double FastRecentWeight; public double SlowRecentWeight; public bool showPoints; public bool showPercent; public bool showBoth; public bool showLegend; public bool smallBorders; public bool isDark; /// /// This could become a check box or something. For now I'm just changing the config data based on /// a known workaround in the config GUI. /// public bool ShowOneLine { get { return FastRecentWeight == SlowRecentWeight; } } /// /// This is mostly aimed at testing, before the config window works. /// public static Settings DecentSample() { List _decentSample = GuiEnvironment.XmlConfig.Node("COMPARE_COUNT").Node("DECENT_SAMPLE"); Settings result = new Settings(); // The following settings are from Brad (8/8/12) result.BullConfigString = _decentSample.Node("BULL_CONFIG").PropertyForCulture("TEXT", "***"); //fed to config window when you click on "Config" for Green Data result.BearConfigString = _decentSample.Node("BEAR_CONFIG").PropertyForCulture("TEXT", "***"); //fed to config window when you click on "Config" for Red Data result.SecondsPerDataPoint = _decentSample.Node("SECONDS_PER_DATA_POINT").Property("TEXT", 5); result.FastRecentWeight = _decentSample.Node("FAST_RECENT_WEIGHT").Property("TEXT", 0.01); result.SlowRecentWeight = _decentSample.Node("SLOW_RECENT_WEIGHT").Property("TEXT", 0.01); result.showBoth = _decentSample.Node("SHOW_BOTH").Property("TEXT", false); result.showPercent = _decentSample.Node("SHOW_PERCENT").Property("TEXT", false); result.showPoints = _decentSample.Node("SHOW_POINTS").Property("TEXT", true); result.isDark = _decentSample.Node("IS_DARK").Property("TEXT", false); result.showLegend = _decentSample.Node("SHOW_LEGEND").Property("TEXT", true); return result; } public Settings Clone() { return (Settings)MemberwiseClone(); } /// /// Load saved settings. Use values defined in DecentSample as defaults /// /// public void Load(XmlNode source) { XmlNode description = source.Node("SETTINGS"); BullConfigString = description.Property("BULLISH", BullConfigString); BearConfigString = description.Property("BEARISH", BearConfigString); showBoth = description.Property("SHOW_BOTH", showBoth); showPoints = description.Property("SHOW_POINTS", showPoints); showPercent = description.Property("SHOW_PERCENT", showPercent); showLegend = description.Property("SHOW_LEGEND", showLegend); smallBorders = description.Property("SMALL_BORDERS", smallBorders); isDark = description.Property("IS_DARK", isDark); SecondsPerDataPoint = description.Property("SECONDS", SecondsPerDataPoint); FastRecentWeight = description.Property("FAST_WEIGHT", FastRecentWeight); SlowRecentWeight = description.Property("SLOW_WEIGHT", SlowRecentWeight); } /// /// Save all settings /// /// public void Save(XmlNode destination) { XmlNode settings = destination.NewNode("SETTINGS"); settings.SetProperty("BULLISH", BullConfigString); settings.SetProperty("BEARISH", BearConfigString); settings.SetProperty("SECONDS", SecondsPerDataPoint); settings.SetProperty("FAST_WEIGHT", FastRecentWeight); settings.SetProperty("SLOW_WEIGHT", SlowRecentWeight); settings.SetProperty("SHOW_PERCENT", showPercent); settings.SetProperty("SHOW_POINTS", showPoints); settings.SetProperty("SHOW_BOTH", showBoth); settings.SetProperty("SHOW_LEGEND", showLegend); settings.SetProperty("SMALL_BORDERS", smallBorders); settings.SetProperty("IS_DARK", isDark); } } }