using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text.RegularExpressions; using System.Web; using System.Windows.Forms; using System.Xml; using TradeIdeas.MiscSupport; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI { public delegate void OddsMakerTradesFormSymbolClickHandler(RowData rowData); public partial class OddsMakerTrades : Form, ICultureListener, IFont { public ISymbolLinkingForOwner _symbolLinking; private IConnectionMaster _connectionMaster; private FontManager _fontManager; private const float DEFAULT_FONT_SIZE = 9.75F; private List _tradeRecords; private List _filteredRecords; private BindingList _boundList = new BindingList(); private List _addedColumns; private IList _columns = new List(); private List _config; private bool _sortIsDescending = false; private string _sortingBy = "EntryTime"; private HashSet _builtInColumns = new HashSet(); private ISendManager _sendManager; public static readonly WindowIconCache WindowIconCache = new WindowIconCache("ODDSMAKER_TRADES"); public OddsMakerTrades(IConnectionMaster connectionMaster, List tradeRecords, List addedColumns) { _connectionMaster = connectionMaster; _sendManager = connectionMaster.SendManager; InitializeComponent(); WindowIconCache.SetIcon(this); _config = GuiEnvironment.XmlConfig.Node("ODDSMAKER"); Text = _config.Node("PHRASES").Node("ODDSMAKER_TRADES").PropertyForCulture("TEXT", "***"); _symbolLinking = new SymbolLinking(this); _tradeRecords = tradeRecords; _addedColumns = addedColumns; AddTradesToBoundList(_tradeRecords); dataGridView1.AutoGenerateColumns = false; dataGridView1.DataSource = _boundList; _fontManager = new FontManager(this, DEFAULT_FONT_SIZE); selectTheFont(); InstallColumns(); _builtInColumns.Add("Symbol"); _builtInColumns.Add("Type"); _builtInColumns.Add("EntryTime"); _builtInColumns.Add("EntryPrice"); _builtInColumns.Add("ExitTime"); _builtInColumns.Add("ExitPrice"); _builtInColumns.Add("Shares"); _builtInColumns.Add("Profit"); } private void RecordExternalLinkUseCase(RowData rowData) { GuiEnvironment.RecordExternalLinkingUseCase(rowData, "OMTrades", _sendManager); } private void SendToExternalLinking(RowData rowData) { RecordExternalLinkUseCase(rowData); string symbol = rowData.GetSymbol(); string exchange = rowData.GetExchange(); string listName = _symbolLinking.SavedSymbolListName; GuiEnvironment.sendSymbolToExternalConnector(symbol, exchange, listName, this, rowData); } private void AddTradesToBoundList(List trades) { _boundList.Clear(); foreach (OddsMakerTradeRecord trade in trades) { RowData rowdata = ConvertTradeToRowData(trade); _boundList.Add(rowdata); } ResizeGrid(dataGridView1); } private RowData ConvertTradeToRowData(OddsMakerTradeRecord trade) { Dictionary data = new Dictionary(); data.Add("Symbol", trade.Symbol); if (trade.EntryAlert != null) data.Add("TYPE", trade.EntryAlert); if (trade.Exchange != null) data.Add("EXCHANGE", trade.Exchange); data.Add("IS_TRADE", "1"); data.Add("FROM_OM", "1"); data.Add("EntryTime", trade.EntryTime); data.Add("EntryPrice", trade.EntryPrice); data.Add("ExitPrice", trade.ExitPrice); data.Add("StopPrice", trade.StopPrice); data.Add("TargetPrice", trade.TargetPrice); data.Add("ExitTime", trade.ExitTime); data.Add("Shares", trade.Shares); data.Add("Profit", trade.ProfitDollars()); data.Add("IsLong", trade.Long); // Show 4 decimal places when prices are less than a dollar. data.Add("four_digits", (trade.EntryPrice < 1) ? "1" : "0"); foreach (string header in _addedColumns) { string key = CommonAlertFields.GetFilterWireName(GetCodeFromHeader(header)); double? asDouble = trade.GetFilterValueAsDouble(header); if (null == asDouble) data.Add(key, ""); else data.Add(key, asDouble); } RowData rowdata = new RowData(); rowdata.Data = data; return rowdata; } private void InstallColumns() { _columns.Clear(); dataGridView1.Columns.Clear(); AddConstantColumns(); AddOtherColumns(); } private void AddOtherColumns() { foreach (string columnHeader in _addedColumns) { double? maxValueInTradeSet = _tradeRecords.Max(x => x.GetFilterValueAsDouble(columnHeader)); double? avgValueInTradeSet = _tradeRecords.Average(x => x.GetFilterValueAsDouble(columnHeader)); string sizeHint = ""; int decimalPlaces = 2; if (null != avgValueInTradeSet && avgValueInTradeSet > 1000) decimalPlaces = 0; if (null != maxValueInTradeSet) sizeHint = Math.Round((double)maxValueInTradeSet, decimalPlaces).ToString(); XmlNode columnXml = GetColumnXmlFromHeader(columnHeader, decimalPlaces.ToString()); ColumnInfo columnInfo = GetColumnInfo(columnXml); if (sizeHint != "") columnInfo.PreferredWidth = CalculatePreferredWidth(sizeHint, dataGridView1.Font, CreateGraphics()); DataGridViewColumn column = DataCell.GetColumn(columnInfo, _connectionMaster, this); _columns.Add(columnInfo); dataGridView1.Columns.Add(column); } } private string GetCodeFromHeader(string header) { string code = GetMatch("\\[(.+)\\]", header); return code; } private XmlNode GetColumnXmlFromHeader(string header, string format) { XmlDocument xmlDoc = new XmlDocument(); string description = GetMatch("^(.+)\\(", header); string units = GetMatch("\\((.+)\\)", header); string code = GetCodeFromHeader(header); if (format == "" || units == "$") format = "2"; xmlDoc.InnerXml = ""; return xmlDoc.FirstChild; } private string GetMatch(string regex, string text) { Regex regexEngine = new Regex(regex); Match match = regexEngine.Match(text); if (match.Success) return match.Groups[1].Value; else return ""; } private ColumnInfo GetColumnInfo(XmlNode columnXml) { // add parameter for form type - RVH20210602 //ColumnInfo columnInfo = new ColumnInfo(columnXml); ColumnInfo columnInfo = new ColumnInfo(columnXml, "ODDS_MAKER_RESULTS_WINDOW"); string sizeHint = columnXml.Property("SIZEHINT", ""); if (sizeHint != "") columnInfo.PreferredWidth = CalculatePreferredWidth(sizeHint, dataGridView1.Font, this.CreateGraphics()); return columnInfo; } private void AddConstantColumns() { List constantTradeColumns = _config.Node("ODDSMAKER_TRADES_CONFIG").Node("CONSTANT_COLUMNS"); foreach (XmlNode columnXml in constantTradeColumns.Enum()) { ColumnInfo columnInfo = GetColumnInfo(columnXml); DataGridViewCell cellTemplate = null; if (columnInfo.InternalCode == "D_Type") cellTemplate = new AlertTypeCell(); DataGridViewColumn column = DataCell.GetColumn(columnInfo, _connectionMaster, this, cellTemplate); _columns.Add(columnInfo); dataGridView1.Columns.Add(column); } } public static int CalculatePreferredWidth(string sizeHint, Font font, Graphics graphics) { SizeF size = graphics.MeasureString(sizeHint, font); int preferredWidth = (int)Math.Floor(size.Width) + 20; return preferredWidth; } public void CultureChanged() { } public void selectTheFont() { _fontManager.selectTheFont(); this.Refresh(); } public void ApplyFilter(string filterVariable, double? filterMin, double? filterMax) { if (null == filterMin && null == filterMax) _filteredRecords = (List)_tradeRecords.Where(x => x.GetFilterValueAsDouble(filterVariable) == null).ToList(); else _filteredRecords = (List)_tradeRecords.Where(x => x.GetFilterValueAsDouble(filterVariable) >= filterMin && x.GetFilterValueAsDouble(filterVariable) <= filterMax).ToList(); AddTradesToBoundList(_filteredRecords); //RefreshDataSource(); } public void ApplyFilter(string filterVariable, string filterValue) { _filteredRecords = (List)_tradeRecords.Where(x => x.FilterEquals(filterVariable, filterValue)).ToList(); try { AddTradesToBoundList(_filteredRecords); //RefreshDataSource(); } catch (Exception e) { string debugView = e.ToString(); } } public void ApplyOpenDateFilter(DateTime day) { _filteredRecords = (List)_tradeRecords.Where(x => x.EntryTime.ToMarketTimeZone().ToString("yyyyMMdd") == day.ToString("yyyyMMdd")).ToList(); try { AddTradesToBoundList(_filteredRecords); } catch (Exception e) { string debugView = e.ToString(); } } public void ApplyCloseDateFilter(DateTime day) { _filteredRecords = (List)_tradeRecords.Where(x => x.ExitTime != null && ((DateTime)x.ExitTime.ToMarketTimeZone()).ToString("yyyyMMdd") == day.ToString("yyyyMMdd")).ToList(); try { AddTradesToBoundList(_filteredRecords); } catch (Exception e) { string debugView = e.ToString(); } } private void RefreshDataSource() { dataGridView1.DataSource = _boundList; ResizeGrid(dataGridView1); } private void dataGridView1_Paint(object sender, PaintEventArgs e) { } public void ResizeGrid(DataGridView grid) { this.InvokeIfRequired(delegate { int totalWidth = 0; foreach (DataGridViewColumn column in grid.Columns) { totalWidth += column.Width; } Screen screen = Screen.FromControl(this); int edgeOfScreen = screen.WorkingArea.Right; int newWidth = totalWidth + 40; if (newWidth + Left > edgeOfScreen) Width = edgeOfScreen - Left - 50; else Width = newWidth; }); } private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { try { if (e.RowIndex == -1) { Column column = (Column)dataGridView1.Columns[e.ColumnIndex]; string internalCode = column.ColumnInfo.InternalCode; if (!_builtInColumns.Contains(internalCode)) { // TODO avoid using the "c_" literal constant. Consider using CommonAlertFields.GetFilterWireName(). // TODO The names are a bit confusing. "Price" is an example of an "internal code." "c_Price" is the corresponding "wire name." internalCode = "c_" + internalCode; } if (internalCode == _sortingBy && !_sortIsDescending) { _sortIsDescending = true; _boundList = new BindingList(_boundList.OrderByDescending(x => x.Data[internalCode]).ToArray()); } else { _sortIsDescending = false; _boundList = new BindingList(_boundList.OrderBy(x => x.Data[internalCode]).ToArray()); } _sortingBy = internalCode; dataGridView1.DataSource = _boundList; } else { // there has been some rare crashes that we haven't been able to reproduce but the errors // lean towards trying to access an index that is out of bounds. if (!GuiEnvironment.IntegrationSupportSingleClick) { if (_boundList.Count > e.RowIndex) { RowData trade = _boundList[e.RowIndex]; string symbol = trade.GetSymbol(); string exchange = trade.GetExchange(); if (GuiEnvironment.IntegrationSupportSingleClick == false) SendToExternalLinking(trade); } } } } catch (Exception exc) { string debugView = exc.Message; } } private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex != -1) { if (GuiEnvironment.IntegrationSupportSingleClick) { if (_boundList.Count > e.RowIndex) { RowData trade = _boundList[e.RowIndex]; string symbol = trade.GetSymbol(); string exchange = trade.GetExchange(); SendToExternalLinking(trade); } } } } } }