Thursday, 25 February 2021

Build a Trading Platform in C# Part 6 - Market Scanner

 Build a Trading Platform in C# Part 6 - Market Scanner


 

 



# Control Name Text or Value Columns or Tabs
1 TabControl
tabControl2 Scan
2 DataGridView
dataGridView1 Profit Target Pos, Symbol, Last
3 Button btnScan
Scan
4 Button
btnStopScan Stop Scan


 

 This highlighted code goes in the scannerData function within the EWrapperImpl.cs file


public virtual void scannerData(int reqId, int rank, ContractDetails contractDetails, string distance, string benchmark, string projection, string legsStr)
        {
            string strScanner = reqId + "," + rank + "," + contractDetails.Contract.Symbol + "," + distance + "," + benchmark;
            myform.AddScannerItemScanner(strScanner);

        }

 


	private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                dataGridView1.Rows.Add();
            }   
        }


	delegate void SetTextCallbackScanner(string strScanner);
        
        public void AddScannerItemScanner(string strScanner)
        {
            if (this.tbLast.InvokeRequired)            {
                SetTextCallbackScanner d = new SetTextCallbackScanner(AddScannerItemScanner);
                try
                {
                    this.Invoke(d, new object[] { strScanner });
                }
                catch (Exception e)
                {
                    Console.WriteLine("this is from _tickPrice ", e);
                }
            }
            else
            {
                string[] scanner = new string[] { strScanner };
                scanner = strScanner.Split(',');
                int position = Convert.ToInt32(scanner[1]);
                
                
                // this creates 10 rows in our datagridview to hold the list of stocks that the scanner finds
                if (position == 0)                {
                    for (int i = 0; i < dataGridView1.Columns.Count; i++)
                    {
                    for (int j = 0; j < dataGridView1.Rows.Count; j++)
                        {
                            dataGridView1.Rows[j].Cells[i].Value = DBNull.Value;
                        }
                    }
                }

                // adds the value for the position in the first cell in the datagrid column
                // adds one to the value so it does not show 0 in the first row
                dataGridView1.Rows[position].Cells[0].Value = position + 1;
                // adds the stock symbol in the second column (symbol)
                dataGridView1.Rows[position].Cells[1].Value = scanner[2];
                // cancels the market data for that position
                ibClient.ClientSocket.cancelMktData(position);

                // create a contract for streaming data
                IBApi.Contract contract = new IBApi.Contract();
                // Create a new TagValue List object (for API version 9.71 and later) 
                List<IBApi.TagValue> mktDataOptiones = new List<IBApi.TagValue>();
                // Set stock symbol that the scanner found
                contract.Symbol = scanner[2];
                // Set the Security type to STK for a Stock
                contract.SecType = "STK";
                // Use "SMART" as the general exchange
                contract.Exchange = "SMART";
                // Set the primary exchange (sometimes called Listing exchange)
                // Use either NYSE or ISLAND
                contract.PrimaryExch = "ISLAND";
                // Set the currency to USD
                contract.Currency = "USD";

                ibClient.ClientSocket.reqMarketDataType(1);

                ibClient.ClientSocket.reqMktData(position, contract, "", false, false, mktDataOptiones);

            }      
        }

 

 

 

This code goes in the tickprice function within the -  public void AddTextBoxItemTickPrice(string _tickPrice)


		switch (Convert.ToInt32(tickerPrice[0]))
                {
                    case 0:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 0].Value = tick_price.ToString();
                            break;
                        } 
                        break;
                    case 1:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 1].Value = tick_price.ToString();
                            break;
                        }
                        
                        break;
                    case 2:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 2].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 3:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 3].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 4:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 4].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 5:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 5].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 6:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 6].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 7:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 7].Value = tick_price.ToString();
                            break; ;
                        }
                        break;
                    case 8:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 8].Value = tick_price.ToString();
                            break;
                        }
                        break;
                    case 9:
                        if (Convert.ToInt32(tickerPrice[1]) == 4)
                        {
                            double tick_price = Convert.ToDouble(tickerPrice[2]);
                            tick_price = Math.Round(tick_price, 2);
                            dataGridView1[2, 9].Value = tick_price.ToString();
                            break;
                        }
                        break;
                }



private void btnScan_Click(object sender, EventArgs e)
        {
            // Create a new TagValue List object (for API version 9.71) 
            //List TagValue = new List();

            // these are codes from the Scanner Parameters output.
            TagValue t1 = new TagValue("avgVolumeAbove", "10000000");
            TagValue t2 = new TagValue("priceAbove", "2");
            //TagValue t3 = new TagValue("priceBelow", "100");

            // Create a Scanner Subscription
            ScannerSubscription scsScanner = new ScannerSubscription();

            // Number of rows the scanner should retrieve (max 50)
            scsScanner.NumberOfRows = 10;
            // Scanner will look for Stocks
            scsScanner.Instrument = "STK";
            // Scanner will look at all US major stocks
            // other examples are: STK.US , STK.US.MAJOR , STK.MINOR , STK.NASDAQ , STK.NYSE , STK.AMEX
            scsScanner.LocationCode = "STK.US.MAJOR"; 
            // Indicate a pre-defined Market Scanner
            scsScanner.ScanCode = "TOP_PERC_GAIN";
            // Only look for Corporate stocks (not ADRs or ETFs)
            //scsScanner.StockTypeFilter = "CORP";
            
            //scsScanner.AboveVolume = 500000;

            //create a list to hold all the scanner parameters
            List<TagValue> TagValues = new List<TagValue> { t1, t2 };
            // Launch the Scanner
            ibClient.ClientSocket.reqScannerSubscription(87, scsScanner, null, TagValues);
            
            // will display all the scanner parameter in the console in xml format
            //ibClient.ClientSocket.reqScannerParameters();
        }



private void btnStopScan_Click(object sender, EventArgs e)
        {
            // cancels scanner data subscription
            ibClient.ClientSocket.cancelScannerSubscription(87);

            // cancels each symbol streaming data in the scanner datagridview
            for (int i = 0; i < 9; i++)
            {
                ibClient.ClientSocket.cancelMktData(i);
            }
        }




	private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1) return; //check if row index is not selected
            if (dataGridView1.CurrentCell.ColumnIndex.Equals(1))
            	if (dataGridView1.CurrentCell != null && dataGridView1.CurrentCell.Value != null)
                    cbSymbol.Text = Convert.ToString(dataGridView1.CurrentCell.Value);
                    getData();
        }


Saturday, 13 February 2021

Build a Trading Platform in C# Part 5 - Bracket Orders

 Build a Trading Platform in C# Part 5 - Bracket Orders.

A bracket order gets you in a trade and sets a profit target, and a stop loss order.  Once the profit target or the stop loss order is triggered the remaining order is canceled.  

The order types for entering a trade are limit ("LMT"), stop ("STP") and stop limit ("STP LMT") also the stop and stop limit orders can be used as a stop loss order.



 



# Control Name Text or Value
1 Label

Profit Target
2 Label
Stop Loss
3 Textbox
tbProfitTarget 0.00
4 Textbox
tbStopLoss
0.00

 

Button click event for the BUY button


	private void btnBuy_Click(object sender, EventArgs e)
        {
            string side = "BUY";

            if (Form.ModifierKeys == Keys.Control)
            {
                send_bracket_order(side);
            }
            else
            {
                send_order(side);
            }
        }
 

Button click event for the sell button



        private void btnSell_Click(object sender, EventArgs e)
        {
            string side = "SELL";

            if (Form.ModifierKeys == Keys.Control)            {
                send_bracket_order(side);
            }else
            {
                send_order(side);
            }
            
        }

Function that creates the contract and the variables necessary to sends each the order and then send each order that was created in the BracketOrder function.


        public void send_bracket_order(string side)
        {
            // create a new contract
            IBApi.Contract contract = new IBApi.Contract();
            // Set the underlying stock symbol from the cbSymbol combobox
            contract.Symbol = cbSymbol.Text;
            // Set the Security type to STK for a Stock
            contract.SecType = "STK";
            // Use "SMART" as the general exchange
            contract.Exchange = cbMarket.Text;
            // Set the primary exchange (sometimes called Listing exchange)
            // Use either NYSE or ISLAND
            contract.PrimaryExch = "ISLAND";
            // Set the currency to USD
            contract.Currency = "USD";

            // order_id, action (Buy or Sell), Quantity, entryPrice, targetPrice, stopLoss, order_type

            string order_type = cbOrderType.Text; // order type LMT or STP from the combobox
            string action = side; // side (BUY or SELL) passed on from the button click event
            double quantity = Convert.ToDouble(numQuantity.Value); // number of shares
            double lmtPrice = Convert.ToDouble(numPrice.Text);  // limit price from numeric up down box on the form
            double takeProfit = Convert.ToDouble(tbTakeProfit.Text);  // take profit amount from text box on the form
            double stopLoss = Convert.ToDouble(tbStopLoss.Text);  // stop loss from the text box on the form

            // side is the either buy or sell
            // calls a BracketOrder function and stores the results in a list variable called bracket
            List<Order> bracket = BracketOrder(order_id++, action, quantity, lmtPrice, takeProfit, stopLoss, order_type);
            foreach (Order o in bracket) // loops through each order in the list
                ibClient.ClientSocket.placeOrder(o.OrderId, contract, o);
            
            // increase the order id number by 3 so you don't use the same order id number twice,
            // and get an error
            order_id +=3;

        }

 

Function that creates each order



        public static List<Order> BracketOrder(int parentOrderId, string action, double quantity, double limitPrice, 
            double takeProfitLimitPrice, double stopLossPrice, string order_type)
        {
            //This will be our main or "parent" order
            Order parent = new Order();
            parent.OrderId = parentOrderId;
            parent.Action = action;  // "BUY" or "SELL"
            parent.OrderType = order_type;  // "LMT", "STP", or "STP LMT"
            parent.TotalQuantity = quantity;
            parent.LmtPrice = limitPrice;
            //The parent and children orders will need this attribute set to false to prevent accidental executions.
            //The LAST CHILD will have it set to true
	    parent.Transmit = false;

	    // Profit Target order
            Order takeProfit = new Order();
            takeProfit.OrderId = parent.OrderId + 1;
            takeProfit.Action = action.Equals("BUY") ? "SELL" : "BUY"; // if statement
            takeProfit.OrderType = "LMT";
            takeProfit.TotalQuantity = quantity;
            takeProfit.LmtPrice = takeProfitLimitPrice;
            takeProfit.ParentId = parentOrderId;
            takeProfit.Transmit = false;
			
	    // Stop loss order
            Order stopLoss = new Order();
            stopLoss.OrderId = parent.OrderId + 2;
            stopLoss.Action = action.Equals("BUY") ? "SELL" : "BUY";
            stopLoss.OrderType = "STP"; //or "STP LMT"
            //Stop trigger price
            // add stopLoss.LmtPrice here if you are going to use a stop limit order
            stopLoss.AuxPrice = stopLossPrice;
            stopLoss.TotalQuantity = quantity;
            stopLoss.ParentId = parentOrderId;
            //In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to true
	    //to activate all its predecessors
            stopLoss.Transmit = true;			
            List<Order> bracketOrder = new List<Order>();
            bracketOrder.Add(parent);
            bracketOrder.Add(takeProfit);
            bracketOrder.Add(stopLoss);
            return bracketOrder;
        }


Thursday, 4 February 2021

Build a Trading Platform in C# part 4 - Time and Sales


Build a trading platform in csharp part 4 - Time and Sales. I added a listView box to hold the time and sales information, and added some more code. 

 


 



# Control Name Text or Value
1 listView
listViewTns

 Add this to the getData() function near the top


	// used to clear the contents of the listView
	listViewTns.Items.Clear();

Make sure you add the number 233 in the within the getdata method. The number 233 is used to request the time and sales market data.


ibClient.ClientSocket.reqMktData(1, contract, "233", false, false, mktDataOptions);

Add this part to the Form1.cs file under the getData() method

	delegate void SetTextCallbackTickString(string _tickString);

        public void AddListViewItemTickString(string _tickString)
        {
            if (this.listViewTns.InvokeRequired)
            {
                try
                {
                    SetTextCallbackTickString d = new SetTextCallbackTickString(AddListViewItemTickString);
                    this.Invoke(d, new object[] { _tickString });
                }
                catch (Exception)
                {

                }
            }
            else
            {
                try
                {
                    // get the bid price from the textbox Bid
                    double theBid = Convert.ToDouble(tbBid.Text);
                    // gets the ask price from the textbox Ask
                    double theAsk = Convert.ToDouble(tbAsk.Text);

                    // Contains Last Price, Trade Size, Trade Time, Total Volume, VWAP, 
                    // single trade flag true, or false.
                    // 6 items all together
                    // example 701.28;1;1348075471534;67854;701.46918464;true
                    // extract each value from string and store it in a string list
                    string[] listTimeSales = _tickString.Split(';');

                    // get the first value form the list convert it to a double this value is the last price
                    double last_price = Convert.ToDouble(listTimeSales[0]);

                    int trade_size = Convert.ToInt32(listTimeSales[1]);

                    double trade_time = Convert.ToDouble(listTimeSales[2]);

                    // adds 2 zeros to the trade size
                    int share_size = trade_size * 100;

                    // formats a string to commas
                    string strShareSize = share_size.ToString("###,####,##0");

                    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                    epoch = epoch.AddMilliseconds(trade_time);
                    // *************************************************
                    epoch = epoch.AddHours(-5);   //Daylight saving time use -4 Summer otherwise use -5 Winter

                    string strSaleTime = epoch.ToString("h:mm:ss:ff");

                    double myMeanPrice = ((theAsk - theBid) / 2);
                    double myMean = (theBid + myMeanPrice);

                    ListViewItem lx = new ListViewItem();

                    // string dt = String.Format("{0:hh:mm:ss}", dnt);

                    // if the last price is the same as the ask change the color to green
                    if (last_price == theAsk)
                    {
                        lx.ForeColor = Color.Green; // listview foreground color
                        lx.Text = (listTimeSales[0]); // last price
                        lx.SubItems.Add(strShareSize); // share size
                        lx.SubItems.Add(strSaleTime); // time
                        listViewTns.Items.Insert(0, lx); // use Insert instead of Add listView.Items.Add(li); 
                    }
                    // if the last price is the same as the bid change the color to red
                    else if (last_price == theBid)
                    {
                        lx.ForeColor = Color.Red;
                        lx.Text = (listTimeSales[0]);
                        lx.SubItems.Add(strShareSize);
                        lx.SubItems.Add(strSaleTime);
                        listViewTns.Items.Insert(0, lx);

                        lbData.Items.Insert(0, strSaleTime);
                    }
                    // if the last price in greater than the mean price and
                    // less than the ask price change the color to lime green
                    else if (last_price > myMean && last_price < theAsk)
                    {
                        lx.ForeColor = Color.Lime;
                        lx.Text = (listTimeSales[0]);
                        lx.SubItems.Add(strShareSize);
                        lx.SubItems.Add(strSaleTime);
                        listViewTns.Items.Insert(0, lx);

                        lbData.Items.Add(epoch);
                    }
                    else
                    {
                        lx.ForeColor = Color.DarkRed;
                        lx.Text = (listTimeSales[0]);
                        lx.SubItems.Add(strShareSize);
                        lx.SubItems.Add(strSaleTime);
                        listViewTns.Items.Insert(0, lx);
                    }
                }
                catch
                {

                }
            }
        }

Place the highlighted csharp code into the tickString method within the EWrapperlmpl.cs file


        public virtual void tickString(int tickerId, int tickType, string value)
        {

            // Contains Last Price, Trade Size, Trade Time, Total Volume, VWAP, single trade flag true, or false 6 items all together
            // example 701.28;1;1348075471534;67854;701.46918464;true
            if (tickType == 48) // used for time and sales (RTVolume)
            {
                string _tickString = value;
                myform.AddListViewItemTickString(_tickString);
            }

        }