Trading Evolution

Markets are never wrong - opinions often are

Getting real-time data from TWS API in C#

Small code snippet to get real-time data using C# TWS API.

Here how it looks like:

Real-time data

  • Lines 13-15: Define contract (stock, futures, forex). In this case it is SPY ETF for S&P 500
  • Line 23: Connect when "Connect" button is clicked
  • Line 28: Request market data after application is connected
  • Lines 33-43: Handle real-time tick data
// Interactive Brokers fields
IBWrapper _ibWrapper;
Contract _ibContract;
int _nextTickerId = 0;

public Main()
{
	InitializeComponent();

	_ibWrapper = new IBWrapper(this);
	_ibContract = new Contract();

	_ibContract.Symbol			= "SPY";
	_ibContract.SecType			= "STK";
	_ibContract.Exchange		= "SMART";
}

private void Connect_Click(object sender, EventArgs e)
{
	_ibWrapper.ClientConnected      += IbWrapper_ClientConnected;
	_ibWrapper.TickPrice            += IbWrapper_TickPrice;

	_ibWrapper.Connect("127.0.0.1", 7496, 0);
}

private void IbWrapper_ClientConnected(object sender, EventArgs e)
{
	_ibWrapper.IBClient.reqMktData(_nextTickerId++, _ibContract, null, false, null);
}

private void IbWrapper_TickPrice(object sender, TickPriceEventArgs e)
{
	switch (e.Field)
	{
		case TickTypeEnum.Bid:
			_bidTextBox.Text = e.Price.ToString("C");
			break;
		case TickTypeEnum.Ask:
			_askTextBox.Text = e.Price.ToString("C");
			break;
		case TickTypeEnum.Last:
			_lastTextBox.Text = e.Price.ToString("C");
			break;
	}
}

 

Real-time data for paper trading account

One of the nice features of IB's paper trading account is ability to get the same real-time market data as your live brokerage account so you can do your simulated trading or test your automated system in conditions that are very similar to real live trading. There are few things you need to do to use it.

  • Do not use your real account at the same time as paper account
  • Go to "Manage Account" ⇒ Settings ⇒ "Paper Trading"
  • Click on "Share real-time market data with paper trading account"
  • Apply Change

Side note: If you still cannot get data like it happened to me. You need to call IB Support +1(866)694-2757 and ask them to delete your paper trading account and recreate it. Do not open support ticket online, they respond very slow to them. Phone call to support works much better. 

Paper Trading Account Settings

How to attach stop loss order to any order

Everybody knows that stop loss orders are important. Interactive Brokers API allows you to send an order with attached stop loss so you don't have to write code to monitor when order is filled then you place your stop order. You can send your order and attached stop loss order which will be monitored by Interactive Brokers and as soon as the main order is filled Interactive Brokers will activate your stop. When order is not filled and you cancel it stop loss order will be cancelled as well.

var entryOrder = new IBApi.Order();

entryOrder.OrderId	= _ibWrapper.NextOrderId++;
entryOrder.Action	= "BUY";
entryOrder.OrderType	= "LMT";
entryOrder.LmtPrice	= price;
entryOrder.TotalQuantity = quantity;
entryOrder.Tif		= "GTC";
entryOrder.Transmit	= false;
_ibWrapper.IBClient.placeOrder(entryOrder.OrderId, contract, entryOrder);

var stopOrder = new IBApi.Order();

stopOrder.OrderId	= _ibWrapper.NextOrderId++;
stopOrder.ParentId	= entryOrder.OrderId;
stopOrder.Action	= "SELL";
stopOrder.OrderType	= "STP";
stopOrder.AuxPrice	= stopPrice;
stopOrder.TotalQuantity	= entryOrder.TotalQuantity;
stopOrder.Tif		= "GTC";
stopOrder.Transmit	= false;
_ibWrapper.IBClient.placeOrder(stopOrder.OrderId, contract, stopOrder);

Thread.Sleep(1000); // Let IB process orders first and then transmit parent order

entryOrder.Transmit         = true;
_ibWrapper.IBClient.placeOrder(entryOrder.OrderId, contract, entryOrder);

Few things to note here. First, set stop loss order ParentId to entry order Id. Second, entry order and stop loss order are sent with Transmit field set to "false" and finally transmit entry order.

How to create an order that automatically cancels in 5 min

When you write your automated system sometimes your signal is valid only for the next 5, 10 or 15 min. It is useful to create orders that auto expire if not filled after certain period of time so you don't have to write code that cancels them. All is needed is to set Time In Force (Tif) property to "GTD" and set GoodTillDate to the time in a future you want this order to expire if it is not filled. In the example below I used DateTime.Now.AddMinutes to add 10 minutes to current time.

var order = new IBApi.Order();

order.OrderId = _ibWrapper.NextOrderId++;
order.Action = "BUY";
order.OrderType = "LMT";
order.LmtPrice = price;
order.TotalQuantity = quantity;
order.Tif = "GTD";
order.GoodTillDate     = DateTime.Now.AddMinutes(10).ToString("yyyyMMdd HH:mm:ss ");

_ibWrapper.IBClient.placeOrder(order.OrderId, ..., order);

 

How to enable API access in TWS

 

  1. File ⇒ Global Configuration or Edit ⇒ Global Configuration (Classic TWS)
  2. API ⇒ Settings
  3. Check "Enable ActiveX and Socket Clients"
  4. Uncheck "Read-Only API"
  5. Verify socket port. The default it 7496
  6. Check "Allow connections from localhost only"

 

More details on InteractiveBrokers.com Trader Workstation API Settings