Friday, 22 January 2021

Build a Trading Platform in C# Part 3 - Send Orders

Build a Trading Platform in csharp Part 3 send order. I added three buttons one for disconnecting from the server, a sell button and a buy button. Added a checkbox for trading premarket and after hours. Click events for the textboxes of bid ask and last, also a timer and a text box to hold the next valid id.

 

 


# Control Name Text or Value
1 Textbox
tbValid_Id 0
2 Button btnDisconnect
Disconnect
3 Button
btnSell SELL
4 Button
btnBuy
BUY
5 Checkbox
chkOutside
OutsideRTH
6 Timer
Timer1
100



add the highlighted code to the Form1.cs file in the appropriate location


	// This delegate enables asynchronous calls for setting
        // the text property on a ListBox control.
        delegate void SetTextCallback(string text);
        delegate void SetTextCallbackTickPrice(string _tickPrice);

        int order_id = 0;
        int timer1_counter = 5;





	// Set up the form object in the EWrapper
        ibClient.myform = (Form1)Application.OpenForms[0];


	// gets the next order id and puts it in the textbox 
        tbValid_Id.Text = ibClient.NextOrderId.ToString();
        // updates the order_id value
        order_id = ibClient.NextOrderId;



	public void btnDisconnect_Click(object sender, EventArgs e)
        {
            ibClient.ClientSocket.eDisconnect();
        }



	public void send_order(string side)
        {
            // Create a new contract to specify the security we are searching for
            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";

            IBApi.Order order = new IBApi.Order();
            // gets the next order id from the text box
            order.OrderId = order_id;
            // gets the side of the order (BUY, or SELL)
            order.Action = side;
            // gets order type from combobox market or limit order(MKT, or LMT)
            order.OrderType = cbOrderType.Text;
            // number of shares from Quantity
            order.TotalQuantity = Convert.ToDouble(numQuantity.Value);
            // Value from limit price
            order.LmtPrice = Convert.ToDouble(numPrice.Value);
            // checks for a stop order
            if (cbOrderType.Text == "STP")
            {
                // Stop order value from the limit textbox
                order.AuxPrice = Convert.ToDouble(numPrice.Value);
            }
            //Visible shares to the market
            order.DisplaySize = Convert.ToInt32(tbVisible.Text);
            //order.OutsideRth = cbOutsideRTH.Checked;
            order.OutsideRth = chkOutside.Checked;

            // Place the order
            ibClient.ClientSocket.placeOrder(order_id, contract, order);

            // increase the order id value
            order_id++;
            tbValid_Id.Text = Convert.ToString(order_id);
        }



	private void tbAsk_Click(object sender, EventArgs e)
        {
            numPrice.Value = Convert.ToDecimal(tbAsk.Text);
        }

        private void tbBid_Click(object sender, EventArgs e)
        {
            numPrice.Value = Convert.ToDecimal(tbBid.Text);
        }

        private void tbLast_Click(object sender, EventArgs e)
        {
            numPrice.Value = Convert.ToDecimal(tbLast.Text);
        }


Add the highlighted code to the bottom of the getData() function it is used to start the timer.



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



	private void timer1_Tick(object sender, EventArgs e)
        {
            if (timer1_counter == 0)
            {
                timer1.Stop(); // stop the timer
                //add the bid price to the limit box
                numPrice.Value = Convert.ToDecimal(tbBid.Text);
                timer1_counter = 5;// resets timer counter back to 5
            }
            timer1_counter--; // subtract 1 every time their is a tick
        }

Friday, 15 January 2021

Updated Trading Platform in C# Streaming Data

 
 
 
here is a link to all of the the streaming data that you can request
 
 
 
 

 


# Control Name Text or Value Increment Decimal
1 Combobox
cbSymbol MSFT - -
2 numericupdown numQuantity
100 100 0
3 numericupdown
numPrice 0 0.01 2
4 Combobox
cbMarket
SMART
- -
5 Combobox
cbOrderType
LMT
- -
6 Text box
tbVisible
100
- -
7 Text Box
tbPrimaryEx
NASDAQ
- -
8 Combobox
cbTif
DAY
- -
9 Text Box
tbBid
0.00
- -
10 Text Box
tbAsk
0.00
- -
11 Text Box
tbLast
0.00
- -



The code goes in the tickPrice method in the EWrapperImpl.cs file

                         string _tickPrice = tickerId + "," + field +
                      "," + price + "," + attribs.CanAutoExecute;
            
	    // sends the string to Form1
            myform.AddTextBoxItemTickPrice(_tickPrice);          
            

 

 

C# additions are highlighted in yellow for the Form1.cs file.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using IBApi;

namespace IB_TradingPlatform
{
    public partial class Form1 : Form
    {

        // This delegate enables asynchronous calls for setting
        // the text property on a ListBox control.
        delegate void SetTextCallback(string text);
        delegate void SetTextCallbackTickPrice(string _tickPrice);

        public void AddListBoxItem(string text)
        {
            // See if a new invocation is required form a different thread          
            if (this.lbData.InvokeRequired) 
            {
                SetTextCallback d = new SetTextCallback(AddListBoxItem);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                // Add the text string to the list box
                this.lbData.Items.Add(text);
            }
        }


        // Create the ibClient object to represent the connection
        IB_TradingPlatform.EWrapperImpl ibClient;


        public Form1()
        {
            InitializeComponent();

            // instantiate the ibClient
            ibClient = new IB_TradingPlatform.EWrapperImpl();
        }

        
        private void btnConnect_Click(object sender, EventArgs e)
        {
            // Parameters to connect to TWS are:
            // host       - IP address or host name of the host running TWS
            // port       - listening port 7496 or 7497
            // clientId   - client application identifier can be any number
            ibClient.ClientSocket.eConnect("", 7497, 0);

            var reader = new EReader(ibClient.ClientSocket, ibClient.Signal);
            reader.Start();
            new Thread(() => {
                while (ibClient.ClientSocket.IsConnected())
                {
                    ibClient.Signal.waitForSignal();
                    reader.processMsgs();
                }
            })
            { IsBackground = true }.Start();
            // Wait until the connection is completed
            while (ibClient.NextOrderId <= 0) { }

            // Set up the form object in the EWrapper
            ibClient.myform = (Form1)Application.OpenForms[0];

            getData();
        }

        public void AddTextBoxItemTickPrice(string _tickPrice)
        {
            if (this.tbLast.InvokeRequired)            {
                SetTextCallbackTickPrice d = new SetTextCallbackTickPrice(AddTextBoxItemTickPrice);
                try
                {
                    this.Invoke(d, new object[] { _tickPrice });
                }
                catch (Exception e)
                {
                    Console.WriteLine("This is from tickPrice", e);                }
            }
            else
            {

                string[] tickerPrice = new string[] { _tickPrice };
                tickerPrice = _tickPrice.Split(',');

                if (Convert.ToInt32(tickerPrice[0]) == 1)                {
                    if (Convert.ToInt32(tickerPrice[1]) == 4)// Delayed Last quote 68, if you want realtime use tickerPrice == 4
                    {
                        // Add the text string to the list box
                        
                        this.tbLast.Text = tickerPrice[2];
                        
                    }
                    else if (Convert.ToInt32(tickerPrice[1]) == 2)  // Delayed Ask quote 67, if you want realtime use tickerPrice == 2
                    {
                        // Add the text string to the list box
                        
                        this.tbAsk.Text = tickerPrice[2];

                    }
                    else if (Convert.ToInt32(tickerPrice[1]) == 1)  // Delayed Bid quote 66, if you want realtime use tickerPrice == 1
                    {
                        // Add the text string to the list box
                        
                        this.tbBid.Text = tickerPrice[2];

                    }
                }
            }
        }

        private void getData()
        {
            ibClient.ClientSocket.cancelMktData(1); // cancel market data

            // Create a new contract to specify the security we are searching for
            IBApi.Contract contract = new IBApi.Contract();
            // Create a new TagValueList object (for API version 9.71 and later) 
            List mktDataOptions = new List();

            // 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 = "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";

            // If using delayed market data subscription
            // in the line below to make sure parameter is 3 not 1 
            ibClient.ClientSocket.reqMarketDataType(1);  // delayed data = 3 live = 1

            // Kick off the subscription for real-time data (add the mktDataOptions list for API v9.71)
            //ibClient.ClientSocket.reqMktData(1, contract, "", false, mktDataOptions);
            // For API v9.72 and higher, add one more parameter for regulatory snapshot
            ibClient.ClientSocket.reqMktData(1, contract, "", false, false, mktDataOptions);

        }


        private void cbSymbol_SelectedIndexChanged(object sender, EventArgs e)
        {
            getData();
        }

        private void cbSymbol_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsLower(e.KeyChar))
            {
                e.KeyChar = char.ToUpper(e.KeyChar);
            }
        }

        private void cbSymbol_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                cbSymbol.SelectionStart = 0;
                cbSymbol.SelectionLength = cbSymbol.Text.Length;
                
                e.SuppressKeyPress = true;                

                string name = cbSymbol.Text;
                

                // adds the security symbol to the dropdown list in the symbol combobox
                if (!cbSymbol.Items.Contains(name))                {
                    cbSymbol.Items.Add(name);
                }
                cbSymbol.SelectAll();

                getData();  
            }
        }
    }
}