Tuesday, 30 March 2021

Build a Trading Platform in C# - Part 10 - Order Management

Build a Trading Platform in C# - Part 10 - Order Management
 


# Control TabPages Members Text
1 TabControl TabPages (Collection) tabPage9 Orders

# Control Name HeaderText Width
0 dataGridView3 colTime Time 60
1 dataGridView3 colid ID 60
2 dataGridView3 colSymbol Symbol 60
3 dataGridView3 colPrice Price 60
4 dataGridView3 colTrigger Trigger 60
5 dataGridView3 colShares Shares 60
6 dataGridView3 colSide Side 60
7 dataGridView3 colType Type 60
8 dataGridView3 colStatus Status 60
9 dataGridView3 colFill Fill 60
10 dataGridView3 colCancel X 20


This code goes in the Form1_Load event method

	    // dataGridView3 Properties
            dataGridView3.RowHeadersVisible = false;
            dataGridView3.ShowCellToolTips = false;
            dataGridView3.BackgroundColor = SystemColors.AppWorkspace;
            dataGridView3.DefaultCellStyle.BackColor = Color.Black;
            dataGridView3.DefaultCellStyle.ForeColor = Color.White;
            dataGridView3.DefaultCellStyle.SelectionBackColor = SystemColors.Highlight;

            // Columns
            dataGridView3.Columns[0].Width = 60;
            dataGridView3.Columns[1].Width = 60;
            dataGridView3.Columns[2].Width = 60;
            dataGridView3.Columns[3].Width = 60;
            dataGridView3.Columns[4].Width = 60;
            dataGridView3.Columns[5].Width = 60;
            dataGridView3.Columns[6].Width = 60;
            dataGridView3.Columns[7].Width = 60;
            dataGridView3.Columns[8].Width = 60;
            dataGridView3.Columns[9].Width = 60;
            dataGridView3.Columns["colCancel"].DefaultCellStyle.BackColor = Color.DodgerBlue; // or SystemColors.Highlight;
            dataGridView3.Columns["colCancel"].DefaultCellStyle.SelectionBackColor = Color.FromArgb(0, 192, 192);
            dataGridView3.Columns["colCancel"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            
            dataGridView3.AlternatingRowsDefaultCellStyle.BackColor = Color.Black;
            dataGridView3.AlternatingRowsDefaultCellStyle.ForeColor = Color.White;

The highlighted code goes inside the CellFormatting event method. The following C# code will format the cells within the data grid view for the various orders


	private void dataGridView3_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
	    // adds a letter x to the 10th column
            if (e.ColumnIndex == 10)
            {
                e.Value = "X";
            }
            try
            {
		// checks if cell is empty
                if (dataGridView3.Rows[e.RowIndex].Cells[6].Value != null && !string.IsNullOrWhiteSpace(dataGridView3.Rows[e.RowIndex].Cells[6].Value.ToString()))
                {
                    // creates a fill status variable and gets the value of cell column 9
                    string fillstatus = dataGridView3.Rows[e.RowIndex].Cells[9].Value.ToString().Trim();

		    // checks if the cell value is SELL and if it is change the color to Red and bold
                    if (dataGridView3.Rows[e.RowIndex].Cells[6].Value.ToString().Trim() == "SELL")
                        dataGridView3.Rows[e.RowIndex].Cells[6].Style.BackColor = System.Drawing.Color.Red;
                    dataGridView3.Columns[6].DefaultCellStyle.Font = new Font(DataGridView.DefaultFont, FontStyle.Bold);

		    // checks if the cell value is BUY and if it is change the color to Green and bold
                    if (dataGridView3.Rows[e.RowIndex].Cells[6].Value.ToString().Trim() == "BUY")
                        dataGridView3.Rows[e.RowIndex].Cells[6].Style.BackColor = System.Drawing.Color.Green;
                    dataGridView3.Columns[6].DefaultCellStyle.Font = new Font(DataGridView.DefaultFont, FontStyle.Bold);

		    // checks if the value in cell column 8 if Filled and if it is changes the fore color (text) to Green
                    if (dataGridView3.Rows[e.RowIndex].Cells[8].Value.ToString().Trim() == "Filled")
                        dataGridView3.Rows[e.RowIndex].DefaultCellStyle = new DataGridViewCellStyle { ForeColor = Color.Green };

		    // checks if the value in cell 8 is Canceled and if so changes the fore color (text) to Green
                    if (dataGridView3.Rows[e.RowIndex].Cells[8].Value.ToString().Trim() == "Canceled")
                        if (fillstatus == "0.00")
                        {
                            dataGridView3.Rows[e.RowIndex].DefaultCellStyle = new DataGridViewCellStyle { ForeColor = Color.Green };
                        }

                    // checks for Partial fill in cell column 8 (status) column and changes text to yellow
                    if (dataGridView3.Rows[e.RowIndex].Cells[8].Value.ToString().Trim() == "Submitted")
                        if (dataGridView3.Rows[e.RowIndex].Cells[9].Value.ToString().Trim() != "0.00")
                        {
                            dataGridView3.Rows[e.RowIndex].DefaultCellStyle = new DataGridViewCellStyle { ForeColor = Color.Yellow };
                        }
                }
            
            	else
            	{
                	dataGridView3.Rows[e.RowIndex].Cells[6].Style = dataGridView3.DefaultCellStyle;
            	}
            }
            catch (Exception)
            {

            }
        }


The highlighted code goes inside the CellClick event method. The following C# code cancels the selected order


	private void dataGridView3_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 10) // Button Cancel is Located in Column 10
            {
                if (e.RowIndex == -1) return; //check if row index is not selected (The index must not be negative)
                if (e.RowIndex >= 0)
                {
                    
		    // gets the row index
                    DataGridViewRow row = this.dataGridView3.Rows[e.RowIndex];

		    // checks if cell value is not null
                    if (row.Cells[1].Value != null)
                    {
                        
                        // variable str is the order number to be cancelled
                        ibClient.ClientSocket.cancelOrder(Convert.ToInt32(row.Cells[1].Value)); // cancels the order
                        // this will change the color of the background of cell 8
                        //row.Cells[8].Style.BackColor = System.Drawing.Color.Red;
                        // removes the row from the grid
                        dataGridView3.Rows.RemoveAt(row.Index);
                    }
                    else
                    {
			// pop up message of nothing in order id cell coloumn
                        MessageBox.Show("no ID number in ID cell ");
                    }
                }
            }
        }

This c# code goes in the EWrapperImpl.cs file within the orderStatus() method


	    try
            {

                myform.AddDataGridViewItemOrderStatus(orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice);
            }
            catch (Exception)
            {

            }

This c# code goes in the EWrapperImpl.cs file within the openOrder() method


	string open_order = (order.PermId + "," + order.ClientId + "," + orderId + "," + order.Account +
                "," + contract.Symbol + "," + contract.SecType + "," + contract.Exchange + "," + order.Action + "," + order.OrderType +
                "," + order.TotalQuantity + "," + order.CashQty + "," + order.LmtPrice + "," + order.AuxPrice + "," + orderState.Status);

            try
            {
                myform.AddListBoxItemOpenOrder(open_order);
            }
            catch (Exception)
            {
            }


	delegate void SetTextCallbackOrderStatus(int orderId, string status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, string whyHeld, double mktCapPrice);
	
        public void AddDataGridViewItemOrderStatus(int orderId, string status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, string whyHeld, double mktCapPrice)
        {
            // See if a new invocation is required form a different thread
            if (this.dataGridView3.InvokeRequired)
            {
                SetTextCallbackOrderStatus d = new SetTextCallbackOrderStatus(AddDataGridViewItemOrderStatus);
                this.Invoke(d, new object[] { orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice });
            }
            else
            {
                string myStatus = status;

                if (myStatus == "Cancelled")
                {
                    myStatus = "Canceled";

                }
                
                // order status
                //"0" orderId + "1" status "2" filled "3" Remaining: "4" remaining
                //"5" avgFillPrice "6" + permId + "7" + parentId + "8" + lastFillPrice
                //"9" clientId + "10" whyHeld "11" mktCapPrice);

                string searchValue = Convert.ToString(orderId);// 0 represents order id
                int countRow = 0;
                Boolean wasFound = false;
                
                
                try
                {
                    foreach (DataGridViewRow row in dataGridView3.Rows)
                    {

                        if (row.Cells[1].Value.ToString().Equals(searchValue))  // orderId searchValue
                        {
                            //string v = tbTime.Text.Substring(tbTime.Text.Length - 8);

                            //Modify the value in the first cell of the second row.
                            dataGridView3.Rows[countRow].Cells[1].Value = orderId;  // Order Number

                            dataGridView3.Rows[countRow].Cells[5].Value = filled + "/" + remaining; // amount of shares filled
                                                                                                         
                            dataGridView3.Rows[countRow].Cells[8].Value = myStatus;  // Status of Order
                            dataGridView3.Rows[countRow].Cells[9].Value = lastFillPrice.ToString("N2");  // e.lastFillPrice
                            dataGridView3.Rows[countRow].Cells[10].Value = "X";  // Cancel
                            
                            wasFound = true;
                            break;
                        }
                        countRow++;
                    }
                }
                catch (Exception)
                {

                }
                if (wasFound)
                    {
                        int rowCount = 0;
                        dataGridView3.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

                        foreach (DataGridViewRow row in dataGridView3.Rows)
                        {

                            if (row.Cells[1].Value.ToString().Equals(searchValue))
                            {
                                this.dataGridView3.Rows[countRow].Cells[5].Value = filled + "/" + remaining; // amount of shares filled
                                // this.dataGridView3.Rows[countRow].Cells[6].Value = e.remaining;  // shares remaining
                                this.dataGridView3.Rows[countRow].Cells[8].Value = myStatus;        // Status of Order
                                this.dataGridView3.Rows[countRow].Cells[9].Value = lastFillPrice.ToString("N2");  // Filled price
                                this.dataGridView3.Rows[countRow].Cells[10].Value = "X";  // Cancel
                                
                                break;
                            }
                            rowCount++;

                        }
                    }
                    else if (!wasFound)  // was not found in Data Grid View
                    {
                        //string v = tbTime.Text.Substring(tbTime.Text.Length - 8);
                        int n = dataGridView3.Rows.Add();
                        {
                            //dataGridView3.Rows[n].Cells[0].Value = "";   // Time submitted
                            dataGridView3.Rows[n].Cells[1].Value = orderId;  // order id number
                            dataGridView3.Rows[n].Cells[2].Value = cbSymbol.Text;     // Stock Symbol
                            dataGridView3.Rows[n].Cells[3].Value = numPrice.Text;  // Submitted limit price
                            dataGridView3.Rows[n].Cells[5].Value = filled + "/" + remaining;        // amount of shares filled
                            dataGridView3.Rows[n].Cells[8].Value = myStatus;        // Status of Order
                            dataGridView3.Rows[n].Cells[9].Value = lastFillPrice.ToString("N2");  // Filled price
                            dataGridView3.Rows[n].Cells[10].Value = "X";     // Cancel Order
                            
                        }
                    }

                    else
                    {
                        int n = dataGridView3.Rows.Add();  // Not added yet in the Data Grid view
                        {
                            
                            dataGridView3.Rows[n].Cells[1].Value = orderId;  // order id number
                            // dataGridView3.Rows[n].Cells[2].Value = tbSymbol.Text;     // Stock Symbol
                            // dataGridView3.Rows[n].Cells[3].Value = e.order.lmtPrice;  // Submitted limit price
                            dataGridView3.Rows[n].Cells[5].Value = filled + "/" + remaining; // amount of shares filled

                            dataGridView3.Rows[n].Cells[8].Value = myStatus;        // Status of Order
                            dataGridView3.Rows[n].Cells[9].Value = lastFillPrice.ToString("N2");  // Filled price
                            dataGridView3.Rows[n].Cells[10].Value = "X";     // Cancel Order
                        }
                    }
                
                dataGridView3.FirstDisplayedScrollingRowIndex = dataGridView3.RowCount - 1;

                //if (myStatus == "Filled" || myStatus == "Canceled")
                //{
                //    timer6.Start(); // count down timer to remove the canceled and filled orders
                //}
					
            }
        }


delegate void SetTextCallbackOpenOrder(string open_order);

        public void AddListBoxItemOpenOrder(string open_order)
        {
            // See if a new invocation is required form a different thread
            if (this.lbData.InvokeRequired)
            {
                SetTextCallbackOpenOrder d = new SetTextCallbackOpenOrder(AddListBoxItemOpenOrder);
                this.Invoke(d, new object[] { open_order });
            }
            else
            {
                //string strArray = Convert.ToString(order_status);
                this.lbData.Items.Add(open_order);

                string[] myOpenOrder = new string[] { open_order };
                myOpenOrder = open_order.Split(',');

                // openOrder
                //"0" order.PermId   "1" order.ClientId
                //"2" + orderId + "3" + order.Account +
                //"4" + contract.Symbol + "5" + contract.SecType +
                //"6" + contract.Exchange + "7" + order.Action +
                //"8" + order.OrderType +
                //"9" + order.TotalQuantity + "10" + order.CashQty +
                //"11" + order.LmtPrice + "12" + order.AuxPrice + "13" + orderState.Status);

                string searchValue = Convert.ToString(myOpenOrder[2]);  // 2 = order id
                int countRow = 0;
                Boolean wasFound = false;

                double myLimitPrice = Convert.ToDouble(myOpenOrder[11]);  // 11 = lmtprice
                double myAuxPrice = Convert.ToDouble(myOpenOrder[12]);    // 12 = AuxPrice
				
                              
                try
                {
                    foreach (DataGridViewRow row in dataGridView3.Rows)
                    {
                        if (row.Cells[1].Value.ToString().Equals(searchValue))
                        {
                            dataGridView3.Rows[countRow].Cells[1].Value = myOpenOrder[2];  // Order Number
                            dataGridView3.Rows[countRow].Cells[2].Value = myOpenOrder[4];       // Stock Symbol
                            dataGridView3.Rows[countRow].Cells[3].Value = myLimitPrice.ToString("N2");   // Limit Price format 2 decimals
                            this.dataGridView3.Rows[countRow].Cells[4].Value = myAuxPrice.ToString("N2");     // Aux Price format 2 decimals
                            //dataGridView3.Rows[countRow].Cells[4].Value = e.filled + "/" + e.remaining; // amount of shares filled
                            dataGridView3.Rows[countRow].Cells[6].Value = myOpenOrder[7];  // Action (buy or sell)
                            dataGridView3.Rows[countRow].Cells[7].Value = myOpenOrder[8];        // Order Type (LMT, MKT etc.)
                                                                                                      
                            this.dataGridView3.Rows[countRow].Cells[10].Value = "X";  // Cancel button to cancel the order

                            wasFound = true;

                            break;
                        }
                        countRow++;
                    }
                }
                catch
                {
                    if (wasFound)
                    {
                        //Console.WriteLine("was found second part of Open order");
                        int rowCount = 0;
                        dataGridView3.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

                        foreach (DataGridViewRow row in dataGridView3.Rows)
                        {
                            if (row.Cells[1].Value.ToString().Equals(searchValue))
                            {
                                
                                this.dataGridView3.Rows[countRow].Cells[10].Value = "X";  // Cancel
                                break;
                            }
                            rowCount++;
                        }
                    }
                    else if (!wasFound)  // was not found in Data Grid View
                    {

                        //string v = tbTime.Text.Substring(tbTime.Text.Length - 8);
                        //Console.WriteLine("was not found in third part of Open order");
                        int n = dataGridView3.Rows.Add();
                        {
                            dataGridView3.Rows[n].Cells[1].Value = myOpenOrder[2];  // order id number
                            dataGridView3.Rows[n].Cells[2].Value = myOpenOrder[4];     // Stock Symbol
                            this.dataGridView3.Rows[countRow].Cells[3].Value = myLimitPrice.ToString("N2");   // Limit Price format 2 decimals
                            this.dataGridView3.Rows[countRow].Cells[4].Value = myAuxPrice.ToString("N2");
                            
                            dataGridView3.Rows[n].Cells[6].Value = myOpenOrder[7];     // Shares remaining
                            dataGridView3.Rows[n].Cells[7].Value = myOpenOrder[8];        // Order Type
                            dataGridView3.Rows[n].Cells[10].Value = "X";     // Cancel Order
                        }
                    }
                    else
                    {
                        // Console.WriteLine("Last part of Open order");
                        int n = dataGridView3.Rows.Add();  // Not added yet in the Data Grid view
                        {
                            dataGridView3.Rows[n].Cells[1].Value = myOpenOrder[2];  // order id number
                            dataGridView3.Rows[n].Cells[2].Value = myOpenOrder[4];     // Stock Symbol
                                                                                       
                            dataGridView3.Rows[n].Cells[6].Value = myOpenOrder[7];     // Shares remaining
                            dataGridView3.Rows[n].Cells[7].Value = myOpenOrder[8];        // Status of Order
                            
                        }
                    }
                }
            }
        }

1 comment:

  1. Thanks to all who donated, helps pay for the data subscriptions, and motivates me to add more content. Thrive and survive cheers!

    ReplyDelete