using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; 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.TIProGUI; using TradeIdeas.TIProGUI.AI; using TradeIdeas.XML; namespace AIStrategyWindow { public partial class AIStrategyForm : Form, ISaveLayout, ISnapToGrid, IAccountStatusChanged, IFont, IRowSelect, IContextMenuStrip, IHaveGrids, ISymbolLinkingChannel { private AIStrategyGrid _strategyGrid = null; private IConnectionMaster _connectionMaster; private List _selectedStrategyList = new List(); //contains the strategies that were checked in the *Strategy* combobox dropdown private List _selectedStrategyNameList = new List(); //names of AI strategies selected from the *Strategy* combobox dropdown private List _filteredAllAIStrategyList = new List(); //contains the strategies that meet requirements from checked items in *Filter* combobox dropdown (computed using *all* AIStrategies) private List _filteredUserStrategies = new List(); //contains the strategies that meet requirements from checked items in *Filter* combobox dropdown (computed using user-selected AIStrategies) private List _selectedFilterNamesList = new List(); //names of filters that were checked from the *Filter* combobox dropdown private CustomCheckedListBox _strategiesCheckedListBox = new CustomCheckedListBox(); private CustomCheckedListBox _filtersCheckedListBox = new CustomCheckedListBox(); private const string FORM_TYPE = "AI_FORM"; private const float FLOW_LAYOUT_HEIGHT_OFFSET = 13f; private const int CHECKBOX_WIDTH_ADJUSTMENT = 40; private const int CHECKBOX_HEIGHT_ADJUSTMENT = 6; private const String LONGS = "All Long Strategies"; private const String SHORTS = "All Short Strategies"; private const String ACTIVE_STRAT = "Active Strategies"; private const String INACTIVE_STRAT = "Inactive Strategies"; private const String ACTIVE_LONGS = "Active Long Strategies"; private const String ACTIVE_SHORTS = "Active Short Strategies"; private const String INACTIVE_LONGS = "Inactive Long Strategies"; private const String INACTIVE_SHORTS = "Inactive Short Strategies"; private string message = GuiEnvironment.XmlConfig.Node("MARKETING_MESSAGE").PropertyForCulture("TEXT", "***"); private LinkLabel.Link _link; private const int SPACING = 10; public static AIStrategyForm AI_STRAT_FORM; public static readonly WindowIconCache WindowIconCache = new WindowIconCache("AI_FORM"); /// /// 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; } private ColumnListState _columnListState = new ColumnListState(); private string _windowTitle = "AI Strategies"; Timer _refreshTimer = new Timer(); // new variable to set that dock panel is being used - RVH20210329 private bool _dockPanelMode = true; private List _dataGrids = new List(); /// /// Exposes the right click menu for wrappers to access. /// public ContextMenuStrip MyContextMenuStrip { get { return _strategyGrid.contextMenuStrip; } } /// /// Exposes the data grids. /// public List DataGrids { get { return _dataGrids; } } public AIStrategyForm(string segmentCode) { InitializeComponent(); _strategyGrid = new AIStrategyGrid(GuiEnvironment.FindConnectionMaster(""), segmentCode); _strategyGrid.GridDataUpdated += _strategyGrid_GridDataUpdated; _strategyGrid.StrategiesLoaded += _strategyGrid_StrategiesLoaded; FormClosing += AIStrategyForm_FormClosing; _strategyGrid.Dock = DockStyle.Fill; tableLayoutPanel1.Controls.Add(_strategyGrid, 1, 1); //tableLayoutPanel1.RowStyles[0].SizeType = SizeType.Absolute; //tableLayoutPanel1.RowStyles[0].Height = 0; _strategyGrid.Dock = DockStyle.Fill; _strategiesCheckedListBox.Font = Font; _filtersCheckedListBox.Font = Font; _dataGrids.Add(_strategyGrid.getDataGridView()); UpdateWindowTitle(); lblMessage.Text = message; linkLabel.Text = GuiEnvironment.XmlConfig.Node("MARKETING_MESSAGE_LEARN").PropertyForCulture("TEXT", "***"); _link = new LinkLabel.Link(); _link.LinkData = GuiEnvironment.MarketingLink + GuiEnvironment.UserMarketingData + "product=ai"; linkLabel.Links.Clear(); linkLabel.Links.Add(_link); // Hide link if marketing link is null or empty. if (string.IsNullOrEmpty(GuiEnvironment.MarketingLink)) linkLabel.Visible = false; _connectionMaster = GuiEnvironment.FindConnectionMaster(""); SetAuthorizedStatus(); //saveToCloudToolStripMenuItem.Image = SaveToCloud.WindowIconCache.MenuImage; //TODO //WindowIconCache.SetIcon(this); this.StartPosition = FormStartPosition.Manual; //Added to correct location issue when snap to window is disabled. SetSnapToGrid(GuiEnvironment.SnapToGrid); _selectedStrategyList.Clear(); LoadStrategies(); loadFilterComboBox(); cboFilters.SelectedIndex = 0; cboFilters.DropDownHeight = 1; // Hide dropdown list selectTheFont(); Rectangle r = Screen.GetWorkingArea(this.Bounds); if (this.Width > r.Width) { this.Width = r.Width - SPACING; } SetupProfitChart(chartPandL); _refreshTimer = new Timer(); _refreshTimer.Interval = 1000; _refreshTimer.Tick += _refreshTimer_Tick; _refreshTimer.Start(); AI_STRAT_FORM = this; } void _refreshTimer_Tick(object sender, EventArgs e) { UpdateWindowTitle(); } private void UpdateWindowTitle() { this.InvokeIfRequired(delegate() { string segmentName = _strategyGrid.SegmentName; // Change displayed time in the window title to reflect user selected timezone. Text = _windowTitle + " - " + ServerFormats.Now.ToString(GuiEnvironment.AlertDateTimeShortFormat) + " (" + segmentName + ") " + " - " + GetCurrentTradeCount() + " trades"; }); } void _strategyGrid_StrategiesLoaded(AIStrategyGrid grid) { this.InvokeIfRequired(delegate() { loadStrategyComboBox(); cboStrategies.SelectedIndex = 0; cboStrategies.DropDownHeight = 1; // Hide dropdown list }); } void _strategyGrid_GridDataUpdated(AIStrategyGrid grid) { try { doRowHiding(); _strategyGrid.updateActiveStrategies(); //these states can change _strategyGrid.updateOpenTradeFormPositions();//these states can change UpdateProfitAndLossChart(); } catch (Exception exc) { string debugView = exc.ToString(); } } private void UpdateProfitAndLossChart() { DateTime? firstTrade = GetFirstTrade(); if (firstTrade.HasValue) { List profits = new List(); DateTime tradingMinute = firstTrade.Value; DateTime now = ServerFormats.Now; DateTime marketClose = GuiEnvironment.GetMarketCloseLocalTime(now); int minutesAgo = (int)(now - tradingMinute).TotalMinutes; while (tradingMinute >= firstTrade.Value && tradingMinute <= marketClose && tradingMinute < now && minutesAgo > 1) { double profit = GetTotalProfit(tradingMinute); profits.Add(profit); tradingMinute = tradingMinute.AddMinutes(1); minutesAgo = (int)(now - tradingMinute).TotalMinutes; } this.InvokeIfRequired(delegate() { AiUtils.DrawProfitChart(chartPandL, profits, MIN_PIXELS_PER_BAR); SetProfitSummaryValues(); SetProfitPercentLabel(); }); } else { this.InvokeIfRequired(delegate() { AiUtils.ClearProfitChart(chartPandL); SetProfitSummaryValues(); SetProfitPercentLabel(); }); } } private void SetProfitPercentLabel() { labelProfitPercent.Font = new Font(labelProfitPercent.Font, FontStyle.Bold); labelProfitPercent.ForeColor = Color.White; labelProfitPercent.MaximumSize = new Size(tableLayoutPanelPandLChart.Width, 0); labelProfitPercent.AutoSize = true; String labelText = ""; if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.FixedShares) labelText = "On " + GuiEnvironment.AiSharesPerTrade.ToString() + " shares per trade"; else if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.FixedDollars) labelText = "On $" + GuiEnvironment.AiDollarsPerTrade.ToString() + " per trade"; else if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.BasedOnStopLoss) labelText = "On $" + GuiEnvironment.AiRiskDollars.ToString() + " risk based on stop loss per trade"; if (!String.IsNullOrEmpty(labelText)) { labelProfitPercent.Text = Environment.NewLine + labelText; } } /// /// Sets the profit summary values on the top panel to their appropriate values. /// private void SetProfitSummaryValues() { this.InvokeIfRequired(delegate() { labelTotalProfitValue.Text = GetCurrentProfitDisplay(); SetProfitSummaryColors(); }); } private Color _defaultProfitColor = Color.FromArgb(217, 217, 217); private Color _greenProfitColor = Color.FromArgb(0, 255, 0); private Color _redProfitColor = Color.FromArgb(255, 0, 0); private void SetProfitSummaryColors() { double profit = GetCurrentProfitFullRiskDollars(); if (profit > 0) labelTotalProfitValue.ForeColor = _greenProfitColor; else if (profit < 0) labelTotalProfitValue.ForeColor = _redProfitColor; else labelTotalProfitValue.ForeColor = _defaultProfitColor; } /// /// Sets the profit summary labels on the top panel to their appropriate values. /// private void SetProfitSummaryLabels() { this.InvokeIfRequired(delegate() { labelTotalProfit.Text = "Profit"; //labelOpenProfit.Text = "Open ($)"; //labelClosedProfit.Text = "Closed ($)"; }); } private string GetCurrentProfitDisplay() { return "$" + GetCurrentProfitFullRiskDollars().ToString("N2"); } /// /// Returns the total profit of strategy using Full Risk profit. /// /// private double GetCurrentProfitFullRiskDollars() { double currentProfit = 0; foreach (AIStrategy strategy in GetFilteredStrategies()) { currentProfit += strategy.FullRiskProfit; } return currentProfit; } /// /// Returns the total win profit of strategy percent using Full Risk profit. /// /// private double GetCurrentWinProfitFullRiskPercent() { int currentWinProfitCount = 0; double currentWinProfitPercent = 0; int totalCount = 0; foreach (AIStrategy strategy in GetFilteredStrategies()) { foreach (StrategyTrade strategyTrade in strategy.StrategyTrades.ToList()) { totalCount++; if (strategy.FullRiskProfit > 0) currentWinProfitCount++; } } if (totalCount > 0) currentWinProfitPercent = (double)currentWinProfitCount / (double)totalCount * 100; return currentWinProfitPercent; } /// /// Trades with riskoff - normal exits /// /// private int GetCurrentTradeCount() { int trades = 0; foreach (AIStrategy strategy in GetFilteredStrategies()) { trades += strategy.TradesToday; } return trades; } private readonly double MIN_PIXELS_PER_BAR = 5; public void ClearPLChartRisk() { AiUtils.ClearProfitChart(chartPandL); // Reset risk on/off and profit/loss labels. labelTotalProfitValue.Text = "0"; labelTotalProfitValue.ForeColor = _defaultProfitColor; SetProfitPercentLabel(); } private bool NoFiltering() { return _strategiesCheckedListBox.CheckedItems.Count == 0 && _filtersCheckedListBox.CheckedItems.Count == 0; } private List GetFilteredStrategies() { if (NoFiltering()) return _strategyGrid.getAIStrategies(); else { if (_strategiesCheckedListBox.CheckedItems.Count == 0) { return _filteredAllAIStrategyList; } else { return _filteredUserStrategies; } } } private double GetTotalProfit(DateTime tradingMinute) { List allProfits = new List(); double totalDollarsAtWork = 0; foreach (AIStrategy strategy in GetFilteredStrategies()) { if (strategy.StrategyTrades.Count > 0) { DateTime firstTrade = strategy.StrategyTrades.Min(x => x.EntryTime); TimeSpan sinceFirstTrade = tradingMinute - firstTrade; int index = (int)sinceFirstTrade.TotalMinutes; Thermograph thermograph = strategy.TodayPerformanceFullRisk; if (index >= 0 && null != thermograph && thermograph.Values.Count >= index + 1) { double profitDollars = thermograph.Values[index]; allProfits.Add(profitDollars); } foreach (StrategyTrade trade in strategy.StrategyTrades) { totalDollarsAtWork += trade.EntryPrice; } } } double profit = 0; if (allProfits.Count > 0) profit = allProfits.Sum(); return profit; } private DateTime? GetFirstTrade() { DateTime? firstTrade = null; foreach (AIStrategy strategy in GetFilteredStrategies()) { if (strategy.StrategyTrades.Count > 0 && (!firstTrade.HasValue || strategy.StrategyTrades.Min(x => x.EntryTime) < firstTrade.Value)) firstTrade = strategy.StrategyTrades.Min(x => x.EntryTime); } return firstTrade; } 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 { // Prior to creating a new AIStrategyForm close other instances. // This makes sure that a currently pinned AIStrategyForm window is closed before restoring the new instance from the layout. //CheckForOtherAIStrategyInstance(); // AI segment string segmentCode = description.Property("SEGMENT_NAME"); if (segmentCode == "") segmentCode = description.Property("SEGMENT_CODE", "all"); try { AIStrategyForm form = new AIStrategyForm(segmentCode); // 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; } catch (Exception e) { string debugView = e.StackTrace; } } }); } //static private void CheckForOtherAIStrategyInstance() //{ // //We're preventing the case of having more than one instance of AIStrategyWindow being open. // //The form being restored from the layout is the form that shall be shown. // foreach (Form form in Application.OpenForms.Cast().Where(x => !x.IsDisposed).ToList()) // { // AIStrategyForm test = form as AIStrategyForm; // if (null != test) // { // form.Close(); // break; // } // } //} private ColumnInfo GetKeyFromValue(DataGridViewColumn c) { //In this case, each columninfo(key) is unique as well as each DataGridViewColumn (value) associated with it. So we will get exactly // one hit from searching by value with this LINQ call Dictionary temp = _strategyGrid.getDataGridViewColumnMap(); ColumnInfo[] keysByValue = temp.Where(x => x.Value == c).Select(pair => pair.Key).ToArray(); if (keysByValue.Length != 0) return keysByValue[0]; return null; } public void SaveLayout(XmlNode parent) { if (null != PreSaveLayoutCode) PreSaveLayoutCode(this); XmlNode description = LayoutManager.SaveBase(parent, this, FORM_TYPE); XmlNode colHeaders = description.NewNode("COL_HEADERS"); if (null != SaveLayoutCode) SaveLayoutCode(this, description); description.SetProperty("PINNED", _strategyGrid.Pinned); //showing toolstrip (e.g. strategy drop-down) description.SetProperty("SHOW_TOOL_STRIP", _strategyGrid.ShowToolStrip); description.SetProperty("SHOW_PROFIT_CHART", _strategyGrid.ShowProfitChart); description.SetProperty("SEGMENT_CODE", _strategyGrid.SegmentCode); //save Column Order... _columnListState.LoadFrom(_strategyGrid.getDataGridView()); _columnListState.SaveTo(description.NewNode("COLUMNS")); //save SortOrder... description.SetProperty("LOCALSORTENABLED", _strategyGrid.LocalSortEnabled); if (null != _strategyGrid.getSortByColumn()) description.SetProperty("LOCALSORTCODE", _strategyGrid.ImportSortBy); description.SetProperty("LOCALSORTTYPE", _strategyGrid.LocalSortType); //save column visibility DataGridView dgv = _strategyGrid.getDataGridView(); foreach (DataGridViewColumn c in dgv.Columns) { XmlNode visibleNode = colHeaders.NewNode("VISIBILITY"); visibleNode.SetProperty("HEADER_NAME", c.HeaderText); visibleNode.SetProperty("IS_VISIBLE", c.Visible); //This is for GWT, we use the internal code for this (Header names can change...) ColumnInfo inf = GetKeyFromValue(c); string internalCode = ""; if (inf != null) internalCode = inf.InternalCode; visibleNode.SetProperty("INTERNAL_CODE", internalCode); } //save checked filters XmlNode filtersNode = description.NewNode("FILTERS"); foreach (int index in _filtersCheckedListBox.CheckedIndices) { XmlNode filterNode = filtersNode.NewNode("FILTER"); filterNode.SetProperty("INDEX", index); } } // 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 = "") { // 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; _strategyGrid.Pinned = description.Property("PINNED", false); // restore toolstrip visibility _strategyGrid.ShowToolStrip = description.Property("SHOW_TOOL_STRIP", false); // restore profit chart visibility _strategyGrid.ShowProfitChart = description.Property("SHOW_PROFIT_CHART", false); showHidePandLGraph(_strategyGrid.ShowProfitChart); // restore profit header settings SetProfitSummaryLabels(); SetYAxisFormatting(chartPandL); //restore column order.. _columnListState.LoadFrom(description.Node("COLUMNS")); // add parameter for form type - RVH20210528 //_columnListState.SaveTo(_strategyGrid.getDataGridView()); _columnListState.SaveTo(_strategyGrid.getDataGridView(), FORM_TYPE); //restore sort order... if (null != description.Property("LOCALSORTENABLED")) { bool enabled = bool.Parse(description.Property("LOCALSORTENABLED", "False")); _strategyGrid.LocalSortEnabled = enabled; } if (null != description.Property("LOCALSORTTYPE")) { SortType value = (SortType)Enum.Parse(typeof(SortType), description.Property("LOCALSORTTYPE", "Descending")); _strategyGrid.LocalSortType = value; } if (null != description.Property("LOCALSORTCODE") && description.Property("LOCALSORTCODE") != String.Empty) { _strategyGrid.ImportSortBy = description.Property("LOCALSORTCODE"); _strategyGrid.NeedToRestoreSortBy = true; } if (_strategyGrid.NeedToRestoreSortBy) { List columns = _strategyGrid.getColumnInfoList(); ColumnInfo sortCol = null; //Get the columnInfo from the "ImportSortBy" property.. foreach (ColumnInfo c in columns) { if (c.InternalCode == _strategyGrid.ImportSortBy) { sortCol = c; _strategyGrid.SortByColumn = c; break; } } if (sortCol != null) { DataGridView dgv = _strategyGrid.getDataGridView(); object o = dgv.DataSource; BindingList rowDatas = (BindingList)o; RowDataHelper.DoSorting(dgv, rowDatas, sortCol, _strategyGrid.LocalSortType); RowDataHelper.FixCellHeaders(dgv, columns, sortCol); } } // get the column Visibility if (_columnListState._columnOrder.Count <= _strategyGrid.getDataGridView().Columns.Count) { XmlNode colHeaderCollection = description.Node("COL_HEADERS"); Dictionary dictionary = new Dictionary(); foreach (XmlNode visibility in colHeaderCollection.Enum()) { bool test; Boolean.TryParse(visibility.Property("IS_VISIBLE"), out test); dictionary.Add(visibility.Property("HEADER_NAME"),test); } DataGridViewColumnCollection dgvCols = _strategyGrid.getDataGridView().Columns; string platform = description.Property("PLATFORM", ""); if (platform == "GWT") { // Since all columns saved in GWT are the only columns and always visible., we first set every column invisible here, then make //the columns in dictionary foreach (DataGridViewColumn c in dgvCols) { c.Visible = false; } foreach (DataGridViewColumn c in dgvCols) { string hText = c.HeaderText; if (dictionary.ContainsKey(hText)) { c.Visible = true; } } } else { foreach (DataGridViewColumn c in dgvCols) { string hText = c.HeaderText; if (dictionary.ContainsKey(hText)) { c.Visible = dictionary[hText]; } } } } //restore checked filters XmlNode filterCollection = description.Node("FILTERS"); foreach (XmlNode filter in filterCollection.Enum()) { int index = filter.Property("INDEX", -1); if (index != -1) { _filtersCheckedListBox.SetItemChecked(index, true); processCheckedFilter(); } } } private void processCheckedFilter() { _selectedFilterNamesList.Clear(); _filteredAllAIStrategyList.Clear(); try { foreach (object item in _filtersCheckedListBox.CheckedItems) { string test = (string)item; _selectedFilterNamesList.Add(test); } doRowHiding(); updateFilterComoboxText(); UpdateProfitAndLossChart(); } catch (Exception exc) { string debugView = exc.ToString(); } } WindowIconCache ISaveLayout.WindowIconCache { get { return WindowIconCache; } } public bool Pinned { get { return _strategyGrid.Pinned; } set { _strategyGrid.Pinned = value; } } void AIStrategyForm_FormClosing(object sender, FormClosingEventArgs e) { try { if (_refreshTimer != null) { _refreshTimer.Stop(); _refreshTimer.Tick -= _refreshTimer_Tick; } _refreshTimer.Dispose(); chartPandL.ChartAreas.Clear(); chartPandL.Series.Clear(); _strategyGrid.Close(); _strategyGrid.GridDataUpdated -= _strategyGrid_GridDataUpdated; _strategyGrid.StrategiesLoaded -= _strategyGrid_StrategiesLoaded; MyContextMenuStrip.Opening -= LayoutManager.Instance().contextMenuStrip_Opening; _strategyGrid = null; _filtersCheckedListBox.AfterItemCheck -= _filtersCheckedListBox_AfterItemCheck; _filtersCheckedListBox.ItemCheck -= _filtersCheckedListBox_ItemCheck; _filtersCheckedListBox.Items.Clear(); _strategiesCheckedListBox.AfterItemCheck -= _strategiesCheckedListBox_AfterItemCheck; _strategiesCheckedListBox.Items.Clear(); } catch (Exception exc) { string debugView = exc.ToString(); } } private void LoadStrategies() { _strategyGrid.LoadStrategies(); } private void loadStrategyComboBox() { this.InvokeIfRequired(delegate() { try { List strategies = _strategyGrid.getAIStrategies(); _strategiesCheckedListBox.Items.Clear(); foreach (AIStrategy strategy in strategies) { _strategiesCheckedListBox.Items.Add(strategy, false); } } catch (Exception e) { string debugView = e.StackTrace; } }); } private void loadFilterComboBox() { this.InvokeIfRequired(delegate() { _filtersCheckedListBox.Items.Clear(); _filtersCheckedListBox.Items.Add(ACTIVE_STRAT, false); _filtersCheckedListBox.Items.Add(INACTIVE_STRAT, false); _filtersCheckedListBox.Items.Add(LONGS, false); _filtersCheckedListBox.Items.Add(SHORTS, false); }); } void _strategiesCheckedListBox_AfterItemCheck(object sender, EventArgs e) //This detects *after* the check has completed, which makes things a little easier for our coding purposes... { _selectedStrategyList.Clear(); _selectedStrategyNameList.Clear(); try { //now collect the checked items foreach (object item in _strategiesCheckedListBox.CheckedItems) { AIStrategy strategy = item as AIStrategy; if (null != strategy) { _selectedStrategyNameList.Add(strategy.Strategy); if (!_selectedStrategyList.Contains(strategy)) _selectedStrategyList.Add(strategy); } } doRowHiding(); updateStrategyComboboxText(); UpdateProfitAndLossChart(); } catch(Exception exc) { string debugView = exc.ToString(); } } private void updateStrategyComboboxText() { this.InvokeIfRequired(delegate { if (_selectedStrategyNameList.Count == 0) { cboStrategies.Items[0] = "All Strategies"; } else if (_selectedStrategyNameList.Count == 1) { cboStrategies.Items[0] = _selectedStrategyNameList[0]; } else { cboStrategies.Items[0] = _selectedStrategyNameList.Count + " Strategies"; } // Update width of combobox cboStrategies.Width = TextRenderer.MeasureText(cboStrategies.Items[0].ToString(), cboStrategies.Font).Width + SystemInformation.VerticalScrollBarWidth; }); } private void doRowHiding() { _filteredUserStrategies.Clear(); _filteredUserStrategies = computeFilteredStrategies(_selectedStrategyList, _selectedFilterNamesList); _filteredAllAIStrategyList = computeFilteredStrategies(_strategyGrid.getAIStrategies(), _selectedFilterNamesList); _strategyGrid.showTheFilteredStrategies(_filteredUserStrategies, _filteredAllAIStrategyList, _selectedFilterNamesList, _selectedStrategyNameList); } /* * In the filter dropdown, we'll move the 4 filters and away from the strategies dropdown in the * strategies dropdown. for filters, the combo indices are as follows : * 0, "Active Strategies" * 1, "Inactive Strategies" * 2, "All Long Strategies" * 3, "All Short Strategies" * A user can check either the Active or Inactive strategies boxes (or neither). But *both* cannot be checked. * Same with the long and short strategies. Either one or the other can be chosen (or neither) . But *both* * long and short strategies cannot be checked. * So if the user checks "Active" and "Long" then he'll see All Active Long strategies. * If it just so happened that he selected a strategy from the list on the right, and it did * not meet the filter criteria on the left hand combobox, then it will not be displayed in the * AI Grid. */ void _filtersCheckedListBox_AfterItemCheck(object sender, EventArgs e) { processCheckedFilter(); } void _filtersCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { CheckState x = e.CurrentValue; //*before* the actual check or unchecked is "completed" int index = e.Index; //Make sure that "Active Strategies" and "Inactive Strategies are not *both* checked": if (index == 0 && x == CheckState.Unchecked && _filtersCheckedListBox.CheckedIndices.Contains(1)) { _filtersCheckedListBox.SetItemCheckState(1, CheckState.Unchecked); return; } if (index == 1 && x == CheckState.Unchecked && _filtersCheckedListBox.CheckedIndices.Contains(0)) { _filtersCheckedListBox.SetItemCheckState(0, CheckState.Unchecked); return; } //Make sure that "All Long Strategies" and "All Short Strategies are not *both* checked: if (index == 2 && x == CheckState.Unchecked && _filtersCheckedListBox.CheckedIndices.Contains(3)) { _filtersCheckedListBox.SetItemCheckState(3, CheckState.Unchecked); return; } if (index == 3 && x == CheckState.Unchecked && _filtersCheckedListBox.CheckedIndices.Contains(2)) { _filtersCheckedListBox.SetItemCheckState(2, CheckState.Unchecked); return; } } private void updateFilterComoboxText() { this.InvokeIfRequired(delegate { if (_selectedFilterNamesList.Count == 0) { cboFilters.Items[0] = "None"; } else if (_selectedFilterNamesList.Count == 1) { cboFilters.Items[0] = _selectedFilterNamesList[0]; } else if (_selectedFilterNamesList.Contains(ACTIVE_STRAT) && _selectedFilterNamesList.Contains(LONGS)) { cboFilters.Items[0] = ACTIVE_LONGS; } else if (_selectedFilterNamesList.Contains(INACTIVE_STRAT) && _selectedFilterNamesList.Contains(LONGS)) { cboFilters.Items[0] = INACTIVE_LONGS; } else if (_selectedFilterNamesList.Contains(ACTIVE_STRAT) && _selectedFilterNamesList.Contains(SHORTS)) { cboFilters.Items[0] = ACTIVE_SHORTS; } else if (_selectedFilterNamesList.Contains(INACTIVE_STRAT) && _selectedFilterNamesList.Contains(SHORTS)) { cboFilters.Items[0] = INACTIVE_SHORTS; } // Update width of combobox cboFilters.Width = TextRenderer.MeasureText(cboFilters.Items[0].ToString(), cboFilters.Font).Width + SystemInformation.VerticalScrollBarWidth; }); } public List getSelectedStrategyNameList() { return _selectedStrategyNameList; } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { _link.LinkData = GuiEnvironment.MarketingLink + GuiEnvironment.UserMarketingData + "product=ai"; string link = e.Link.LinkData as string; if (null != link) Process.Start(link); } private List computeFilteredStrategies(List chosenStrategies, List filterNameList) { List retVal = new List(); foreach (AIStrategy strategy in chosenStrategies) { if (filterNameList.Contains(LONGS) && filterNameList.Contains(ACTIVE_STRAT)) { if (strategy.IsLong && strategy.TradesToday != 0) retVal.Add(strategy); } else if (filterNameList.Contains(LONGS) && filterNameList.Contains(INACTIVE_STRAT)) { if (strategy.IsLong && strategy.TradesToday == 0) retVal.Add(strategy); } else if (filterNameList.Contains(SHORTS) && filterNameList.Contains(ACTIVE_STRAT)) { if (strategy.IsLong == false && strategy.TradesToday != 0 ) retVal.Add(strategy); } else if (filterNameList.Contains(SHORTS) && filterNameList.Contains(INACTIVE_STRAT)) { if (strategy.IsLong == false && strategy.TradesToday == 0) retVal.Add(strategy); } else if (filterNameList.Contains(SHORTS)) { if (strategy.IsLong == false) retVal.Add(strategy); } else if (filterNameList.Contains(LONGS)) { if (strategy.IsLong) retVal.Add(strategy); } else if (filterNameList.Contains(ACTIVE_STRAT)) { if (strategy.TradesToday > 0) retVal.Add(strategy); } else if (filterNameList.Contains(INACTIVE_STRAT)) { if (strategy.TradesToday == 0) retVal.Add(strategy); } else if (filterNameList.Count == 0) //unfiltered { retVal.Add(strategy); } } return retVal; } public void onAccountStatusChanged() { SetAuthorizedStatus(); } private void SetAuthorizedStatus() { if (_connectionMaster.LoginManager.AccountStatus == AccountStatus.Good) { if (GuiEnvironment.Authorizations.Count != 0 && (GuiEnvironment.Authorizations.ContainsKey("ai") && GuiEnvironment.Authorizations["ai"])) { tableLayoutPanel1.Visible = true; } else { tableLayoutPanel1.Visible = false; lblMessage.Text = message; // Hide link if marketing link is null or empty. if (string.IsNullOrEmpty(GuiEnvironment.MarketingLink)) linkLabel.Visible = false; else linkLabel.Visible = true; } } else { tableLayoutPanel1.Visible = true; lblMessage.Text = "No Connection"; linkLabel.Visible = false; } } public void SetSnapToGrid(bool enabled) { formSnapper1.Enabled = enabled; if (GuiEnvironment.RunningWin10 && enabled) { formSnapper1.Win10HeightAdjustment = GuiEnvironment.HEIGHT_INCREASE; formSnapper1.Win10WidthAdjustment = GuiEnvironment.WIDTH_INCREASE; } } public void showHideStrategyMenu(bool isChecked) { tableLayoutPanelTop.Visible = isChecked; } public void selectTheFont() { Font = GuiEnvironment.FontSettings; (_strategyGrid.getDataGridView()).DefaultCellStyle.Font = GuiEnvironment.FontSettings; _strategiesCheckedListBox.Font = GuiEnvironment.FontSettings; _filtersCheckedListBox.Font = GuiEnvironment.FontSettings; _strategyGrid.setContextMenuFont(GuiEnvironment.FontSettings); _strategyGrid.RefreshColumns(); if (tableLayoutPanel1.RowStyles[0].Height != 0f) { tableLayoutPanel1.RowStyles[0].Height = Font.GetHeight() + FLOW_LAYOUT_HEIGHT_OFFSET; } // Update fonts to several of the controls to assure that their sizes and texts scale correctly during a font change. tableLayoutPanelTop.Font = GuiEnvironment.FontSettings; label3.Font = GuiEnvironment.FontSettings; tableLayoutPanelProfitHeader.Font = GuiEnvironment.FontSettings; tableLayoutPanelOpenProfitHeader.Font = GuiEnvironment.FontSettings; tableLayoutPanelClosedProfitHeader.Font = GuiEnvironment.FontSettings; flowLayoutPanelSummary.Font = GuiEnvironment.FontSettings; flowLayoutPanel1.Font = GuiEnvironment.FontSettings; cboStrategies.Font = GuiEnvironment.FontSettings; cboFilters.Font = GuiEnvironment.FontSettings; label1.Font = GuiEnvironment.FontSettings; label2.Font = GuiEnvironment.FontSettings; labelTotalProfitValue.Font = GuiEnvironment.FontSettings; // Update width of comboboxes cboStrategies.Width = TextRenderer.MeasureText(cboStrategies.Items[0].ToString(), cboStrategies.Font).Width + SystemInformation.VerticalScrollBarWidth; cboFilters.Width = TextRenderer.MeasureText(cboFilters.Items[0].ToString(), cboFilters.Font).Width + SystemInformation.VerticalScrollBarWidth; } private void cboStrategies_Click(object sender, EventArgs e) { if (_strategiesCheckedListBox.Items.Count > 0) { _strategiesCheckedListBox.BorderStyle = BorderStyle.None; List strategies = _strategyGrid.getAIStrategies(); _strategiesCheckedListBox.AfterItemCheck -= _strategiesCheckedListBox_AfterItemCheck; _strategiesCheckedListBox.AfterItemCheck += new EventHandler(_strategiesCheckedListBox_AfterItemCheck); _strategiesCheckedListBox.CheckOnClick = true; _strategiesCheckedListBox.Visible = true; _strategiesCheckedListBox.Location = new Point(cboStrategies.Left, cboStrategies.Bottom); Size minimumSize = TextRenderer.MeasureText("All Strategies", _strategiesCheckedListBox.Font); int widest = minimumSize.Width; foreach (AIStrategy strategy in strategies) { Size itemSize = TextRenderer.MeasureText(strategy.ToString(), _strategiesCheckedListBox.Font); if (itemSize.Width > widest) widest = itemSize.Width + CHECKBOX_WIDTH_ADJUSTMENT; } _strategiesCheckedListBox.Width = widest; // Set the height of a WinForms CheckedListBox to fit to dynamic contents without scrollbars // from https://camerondwyer.wordpress.com/2013/08/09/how-to-set-the-height-of-a-winforms-checkedlistbox-to-fit-to-dynamic-contents-without-scrollbars/ _strategiesCheckedListBox.ClientSize = new Size(_strategiesCheckedListBox.ClientSize.Width, _strategiesCheckedListBox.GetItemRectangle(0).Height * _strategiesCheckedListBox.Items.Count); ToolStripDropDown popup = new ToolStripDropDown(); popup.AutoSize = false; popup.Margin = new Padding(0, 0, 0, 3); popup.Padding = Padding.Empty; popup.Size = new Size(_strategiesCheckedListBox.Width, _strategiesCheckedListBox.Height + CHECKBOX_HEIGHT_ADJUSTMENT); ToolStripControlHost host = new ToolStripControlHost(_strategiesCheckedListBox); host.Margin = new Padding(5, 3, 0, 0); host.AutoSize = false; host.Size = new Size(_strategiesCheckedListBox.Width, _strategiesCheckedListBox.Height); popup.Items.Add(host); popup.Show(cboStrategies, 0, cboStrategies.Height); popup.Focus(); } } private void cboFilters_Click(object sender, EventArgs e) { if (_filtersCheckedListBox.Items.Count > 0) { _filtersCheckedListBox.BorderStyle = BorderStyle.None; _filtersCheckedListBox.AfterItemCheck -= _filtersCheckedListBox_AfterItemCheck; _filtersCheckedListBox.AfterItemCheck += new EventHandler(_filtersCheckedListBox_AfterItemCheck); _filtersCheckedListBox.ItemCheck -= _filtersCheckedListBox_ItemCheck; _filtersCheckedListBox.ItemCheck += new ItemCheckEventHandler(_filtersCheckedListBox_ItemCheck); _filtersCheckedListBox.CheckOnClick = true; _filtersCheckedListBox.Visible = true; _filtersCheckedListBox.Location = new Point(cboFilters.Left, cboFilters.Bottom); Size itemSize = TextRenderer.MeasureText(SHORTS, _filtersCheckedListBox.Font); int widest = itemSize.Width + CHECKBOX_WIDTH_ADJUSTMENT; _filtersCheckedListBox.Width = widest; // Set the height of a WinForms CheckedListBox to fit to dynamic contents without scrollbars // from https://camerondwyer.wordpress.com/2013/08/09/how-to-set-the-height-of-a-winforms-checkedlistbox-to-fit-to-dynamic-contents-without-scrollbars/ _filtersCheckedListBox.ClientSize = new Size(_filtersCheckedListBox.ClientSize.Width, _filtersCheckedListBox.GetItemRectangle(0).Height * _filtersCheckedListBox.Items.Count); ToolStripDropDown popup = new ToolStripDropDown(); popup.AutoSize = false; popup.Margin = new Padding(0, 0, 0, 3); popup.Padding = Padding.Empty; popup.Size = new Size(_filtersCheckedListBox.Width, _filtersCheckedListBox.Height + CHECKBOX_HEIGHT_ADJUSTMENT); ToolStripControlHost host = new ToolStripControlHost(_filtersCheckedListBox); host.Margin = new Padding(5, 3, 0, 0); host.AutoSize = false; host.Size = new Size(_filtersCheckedListBox.Width, _filtersCheckedListBox.Height); popup.Items.Add(host); popup.Show(cboFilters, 0, cboFilters.Height); popup.Focus(); } } private void SetupProfitChart(Chart chart) { chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false; chart.Series[0].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Time; chart.BackColor = Color.Black; chart.BorderColor = Color.FromArgb(100, 100, 100); chart.ChartAreas[0].BackColor = Color.Black; chart.ChartAreas[0].BorderColor = Color.FromArgb(55, 55, 55); chart.ChartAreas[0].AxisY.LabelStyle.ForeColor = Color.FromArgb(55, 55, 55); chart.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.FromArgb(55, 55, 55); chart.ChartAreas[0].AxisY.MinorGrid.LineColor = Color.FromArgb(55, 55, 55); SetYAxisFormatting(chart); showHidePandLGraph(_strategyGrid.ShowProfitChart); } private void SetYAxisFormatting(Chart chart) { chart.ChartAreas[0].AxisY.LabelStyle.Format = "0.00"; } internal void showHidePandLGraph(bool show) { tableLayoutPanelPandLChart.Visible = show; if (show) { tableLayoutPanel1.ColumnStyles[0].SizeType = SizeType.AutoSize; tableLayoutPanel1.ColumnStyles[0].Width = 0; } else { tableLayoutPanel1.ColumnStyles[0].SizeType = SizeType.Absolute; tableLayoutPanel1.ColumnStyles[0].Width = 0; } } private void AIStrategyForm_Resize(object sender, EventArgs e) { } public void chooseRowSelect() { if (_strategyGrid != null) _strategyGrid.chooseRowSelect(); } public enum AiRiskMode { RiskOff, RiskOn, FullRisk } private void AIStrategyForm_VisibleChanged(object sender, EventArgs e) { if (Visible) { if (GuiEnvironment.CLICKED_MAIN_FORM_MENU) { GuiEnvironment.CLICKED_MAIN_FORM_MENU = false; GuiEnvironment.SetWindowOpeningPosition(this, null); } } } private void AIStrategyForm_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; } } /// /// Set the symbol link channel from symbol linking /// /// The link channel void ISymbolLinkingChannel.SetLinkChannel(string linkChannel) { _strategyGrid.SetLinkChannel(linkChannel); } /// /// Set the symbol link channel icon /// /// The link channel public void SetLinkChannelIcon(string linkChannel) { // change window icon SymbolLinkingChannelsHelper.SetFormIcon(this, "AI", linkChannel); } /// /// Get the symbol link channel /// /// string ISymbolLinkingChannel.GetLinkChannel() { return _strategyGrid.GetLinkChannel(); } } }