After the program connects to TWS using the eConnect() method, EWrapper's nextValidId() callback method is automatically triggered. The value passed into this method must be captured and stored, as it represents the next available unique id to be used when placing an order. Failure to use this order id may generate an error. In this example, I ignored the value returned to nextValidID() and issued an order with order id of 10, which causes an error.
[API.msg2] Duplicate order id {10, 103}
Therefore, the value generated in nextValidID must be used and incremented for every additional order. As with some of the callback methods, it's impossible to know exactly when nextValidID() will be triggered. I will make a note that the program will have to check for this event before placing an actual order.
Once an order id has been initialized by nextValidID(), it's safe to place an order using the EClientSocket.placeOrder() method. The status of the order can be checked in the EWrapper's orderStatus() call back method. When the status of the order callback is completed, openOrderEnd() call back is called. This signal, which indicates that the request has ended, is new to API v 5.60.
The following code example submits a limit order (done in after trading hours)
require 'java'
require 'TwsApi.jar'
include_class 'ib.client.EClientSocket'
include_class 'ib.client.Contract'
include_class 'ib.client.Order'
include_class 'ib.client.AnyWrapper'
include_class 'ib.client.EWrapper'
class TestStockOrder
include EWrapper #note "class TestMktData < EWrapper" syntax is no longer supported in JRuby 1.0
attr_accessor :order_id # makes order_id variable accessible
@mySocket
def initialize
puts 'init'
@mySocket = EClientSocket.new(self)
end
def eConnect
@mySocket.eConnect("127.0.0.1", 7496, 0)
end
# Request all open orders that were placed from all API clients linked to one TWS,
# and also from the TWS
# This is a one time shot call. When its done you DO NOT continue to receive
# information about new placed orders
def reqAllOpenOrders
@mySocket.reqAllOpenOrders
end
def submitStockOrder(order_id, symbol, buy_sell, qty, order_type, limit_price, tif)
# --------------------------------
myContract = Contract.new
myContract.m_symbol = symbol
myContract.m_secType = 'STK'
myContract.m_exchange = 'SMART'
myContract.m_currency = 'USD'
myOrder = Order.new
myOrder.m_action = buy_sell # BUY, SELL
myOrder.m_totalQuantity = qty
myOrder.m_orderType = order_type # MKT, LMT, STP, SPLMT, TRAIL, etc
myOrder.m_lmtPrice = limit_price
myOrder.m_tif = tif # DAY, GTC
@mySocket.placeOrder(order_id, myContract, myOrder)
end
def cancelOrder(order_id)
@mySocket.cancelOrder(order_id)
end
def eDisconnect
@mySocket.eDisconnect
end
def contract_msg(contract)
puts ' contract_msg:'
puts ' conid = ' + contract.m_conId.to_s
puts ' symbol = ' + contract.m_symbol
puts ' secType = ' + contract.m_secType
puts ' exchange = ' + contract.m_exchange.to_s
puts ' currency = ' + contract.m_currency
puts ' localSymbol = ' + contract.m_localSymbol.to_s
end
def order_msg(order)
puts ' order_msg:'
puts ' order id =' + order.m_orderId.to_s
puts ' client id =' + order.m_clientId.to_s
puts ' action =' + order.m_action.to_s
puts ' quantity =' + order.m_totalQuantity.to_s
puts ' type =' + order.m_orderType.to_s
puts ' lmtPrice =' + order.m_lmtPrice.to_s
puts ' TIF =' + order.m_tif.to_s
puts ' parent Id =' + order.m_parentId.to_s
puts ' permId =' + order.m_permId.to_s
end
def order_state_msg(order_state)
puts ' order_state_msg:'
puts ' status =' + order_state.m_status.to_s
puts ' initMargin =' + order_state.m_initMargin.to_s
puts ' maintMargin =' + order_state.m_maintMargin.to_s
puts ' commission =' + order_state.m_commission.to_s
end
#///////////////////////////////////////////////////////////////////////
#// Interface methods
#///////////////////////////////////////////////////////////////////////
def tickPrice( ticker_id, field, price, can_auto_execute)
end
def tickSize( ticker_id, field, size)
end
def tickOptionComputation( ticker_id, field, implied_vol,
delta, model_price, pv_dividend)
end
def tickGeneric( ticker_id, tick_type, value)
end
def tickString( ticker_id, tick_type, value)
end
def tickEFP( ticker_id, tick_type, basis_points,
formatted_basis_points, implied_future, hold_days,
future_expiry, dividend_impact, dividends_to_expiry)
end
def orderStatus( order_id, status, filled, remaining,
avg_fill_price, perm_id, parent_id, last_fill_price,
client_id, why_held)
puts '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
puts 'orderStatus>: orderId=' + order_id.to_s + ', clientId=' + client_id.to_s + ', permId=' + perm_id.to_s +
', status=' + status + ' filled=' + filled.to_s + ', remaining=' + remaining.to_s + ', '
puts ' avgFillPrice=' + avg_fill_price.to_s + ', lastFillPrice=' + last_fill_price.to_s +
', parent Id=' + parent_id.to_s + ', whyHeld=' + why_held.to_s
end
def openOrder( order_id, contract, order, order_state)
puts '--------------------------------------------------------'
puts 'openOrder> open order: orderId=' + order_id.to_s + ' --- '
contract_msg(contract)
order_msg(order)
order_state_msg(order_state)
end
def updateAccountValue( key, value, currency, account_name)
end
def updatePortfolio( contract, position, market_price, market_value,
average_cost, unrealized_pnl, realized_pnl, account_name)
end
def updateAccountTime( time_stamp)
end
# triggered right after logging into TWS
def nextValidId( order_id)
@order_id = order_id #storing order id to be used when placing order
puts 'nextValidId> Next Valid Order Id = ' + @order_id.to_s
end
def contractDetails( req_id, contract_details)
end
def bondContractDetails( req_id, contract_details)
end
def contractDetailsEnd( req_id)
end
def execDetails( order_id, contract, execution)
end
def updateMktDepth( ticker_id, position, operation, side, price, size)
end
def updateMktDepthL2( ticker_id, position, market_maker, operation,
side, price, size)
end
def updateNewsBulletin( msg_id, msgType, message, orig_exchange)
end
def managedAccounts( accounts_list)
end
def receiveFA( fa_data_type, xml)
end
def historicalData( req_id, date, open, high, low,
close, volume, count, eWAP, has_gaps)
end
def scannerParameters( xml)
end
def scannerData( req_id, rank, contract_details, distance,
benchmark, projection, legs_str)
end
def scannerDataEnd( req_id)
end
def realtimeBar( req_id, time, open, high, low, close, volume, wap, count)
end
def currentTime( time)
end
def fundamentalData( req_id, data)
end
# ---------------------------------------------------
# new callback methods added in API 9.60
# ---------------------------------------------------
def openOrderEnd() # invoked when all orders are sent to a client as a response to reqOpenOrders(),
# reqAllOpenOrders and right after connected to TWS
puts 'openOrderEnd> Ended'
end
def accountDownloadEnd(account_name) #invoked when a complete snapshot of an account state is sent to a client as a response to reqAccountUpdates()
end
def execDetailsEnd( req_id) # invoked when all executions are sent to a client as a response to reqExecutions()
end
def deltaNeutralValidation(req_id, under_comp) # for Delta-Neutral DN RFQ
end
# ---------------------------------------------------
# -- methods from AnyWrapper -- must be declared
# ---------------------------------------------------
def connectionClosed()
puts ' [API.connectionClosed] Closed connection with TWS'
end
def error(err_obj_str)
puts ' [API.msg1] ' + err_obj_str if err_obj_str.is_a?(String)
puts ' [API.msg3] ' + err_obj_str.getMessage() if err_obj_str.is_a?(Exception)
end
def error(one, two, str)
puts ' [API.msg2] ' + str + ' {' + one.to_s + ', ' + two.to_s + '}'
end
end
# *********************************************************************************************
# Running the code
# *********************************************************************************************
x = TestStockOrder.new()
begin
x.eConnect
puts 'connected ...'
sleep(2) # need this here to give time for nextValidId() to be called
puts '*****************************'
puts '**** LIMIT ORDER - LIMIT ****'
o1 = x.order_id
x.submitStockOrder(o1, 'IWM', 'BUY', 50, 'LMT', 10, 'DAY')
sleep(5)
puts '*** requesting open orders ***'
x.reqAllOpenOrders
sleep(5)
x.eDisconnect
puts 'disconnected'
rescue Exception => e
puts 'Exception ' + e.message
x.eDisconnect
end
Line 13: declaration of variable order_id to store order id
Line 147: initialize order_id after connected to TWS
Running the code produces the following output:
init
Server Version:43
TWS Time at connection:20090311 22:22:42 EST
connected ...
nextValidId> Next Valid Order Id = 47
openOrderEnd> Ended
[API.msg2] Market data farm connection is OK:usopt {-1, 2104}
[API.msg2] Market data farm connection is OK:usfarm {-1, 2104}
*****************************
**** LIMIT ORDER - LIMIT ****
[API.msg2] Order Message:
Warning: your order will not be placed at the exchange until 2009-03-12 09:30:00 US/Eastern {47, 399}
--------------------------------------------------------
openOrder> open order: orderId=47 ---
contract_msg:
conid = 9579970
symbol = IWM
secType = STK
exchange = SMART
currency = USD
localSymbol = IWM
order_msg:
order id =47
client id =0
action =BUY
quantity =50
type =LMT
lmtPrice =10.0
TIF =DAY
parent Id =0
permId =1309177719
order_state_msg:
status =PreSubmitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=45, clientId=0, permId=1309177719, status=PreSubmitted filled=0, remaining=50,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
*** requesting open orders ***
--------------------------------------------------------
openOrder> open order: orderId=47 ---
contract_msg:
conid = 9579970
symbol = IWM
secType = STK
exchange = SMART
currency = USD
localSymbol = IWM
order_msg:
order id =47
client id =0
action =BUY
quantity =50
type =LMT
lmtPrice =10.0
TIF =DAY
parent Id =0
permId =1309177719
order_state_msg:
status =PreSubmitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=47, clientId=0, permId=1309177719, status=PreSubmitted filled=0, remaining=50,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
openOrderEnd> Ended
disconnected
Note method openOrderEnd() was triggered right after connecting to TWS and after call to reqAllOpenOrders().
openOrder() method was also triggered right after submitting the order using placeOrder().
The order was successfully created and may be validated in TWS.
03/12/09 Update
The market is now open and I'm testing order cancellation and market order type. A limit order for PFE is issued and then canceled. After that, a market order for INTC is issued. The code is as follows:
# *********************************************************************************************
# Running the code
# *********************************************************************************************
x = TestStockOrder.new()
begin
x.eConnect
puts 'connected ...'
sleep(2) # need this here to give time for nextValidId() to be called
puts '*****************************'
puts '**** LIMIT ORDER and CANCEL ****'
o2 = x.order_id += 1
x.submitStockOrder(o2, 'PFE', 'BUY', 10, 'LMT', 5.50, 'DAY') # Order 16
sleep(5)
puts '*** Cancelling order ***'
x.cancelOrder(o2) # does not trigger anything, need to check status of order
sleep(5)
puts '*** requesting open orders ***'
x.reqAllOpenOrders
puts '*****************************'
puts '**** MARKET ORDER ****'
x.submitStockOrder(x.order_id += 1, 'INTC', 'BUY', 20, 'MKT', 0, 'DAY')
sleep(5)
puts '*** requesting open orders ***'
x.reqAllOpenOrders
sleep(5)
x.eDisconnect
puts 'disconnected'
rescue Exception => e
puts 'Exception ' + e.message
x.eDisconnect
end
Running the code produces the following output:
init
Server Version:43
TWS Time at connection:20090312 15:10:08 EST
connected ...
nextValidId> Next Valid Order Id = 51
--------------------------------------------------------
openOrder> open order: orderId=47 ---
contract_msg:
conid = 9579970
symbol = IWM
secType = STK
exchange = SMART
currency = USD
localSymbol =
order_msg:
order id =47
client id =0
action =BUY
quantity =50
type =LMT
lmtPrice =10.0
TIF =DAY
parent Id =0
permId =1309177719
order_state_msg:
status =Submitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=47, clientId=0, permId=1309177719, status=Submitted filled=0, remaining=50,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
openOrderEnd> Ended
[API.msg2] Market data farm connection is OK:usopt {-1, 2104}
[API.msg2] Market data farm connection is OK:usfarm {-1, 2104}
*****************************
**** LIMIT ORDER and CANCEL ****
--------------------------------------------------------
openOrder> open order: orderId=52 ---
contract_msg:
conid = 11031
symbol = PFE
secType = STK
exchange = SMART
currency = USD
localSymbol = PFE
order_msg:
order id =52
client id =0
action =BUY
quantity =10
type =LMT
lmtPrice =5.5
TIF =DAY
parent Id =0
permId =888579469
order_state_msg:
status =Submitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=52, clientId=0, permId=888579469, status=Submitted filled=0, remaining=10,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
*** Cancelling order ***
[API.msg2] Order Canceled - reason: {52, 202}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=52, clientId=0, permId=888579469, status=Cancelled filled=0, remaining=10,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
*** requesting open orders ***
--------------------------------------------------------
openOrder> open order: orderId=47 ---
contract_msg:
conid = 9579970
symbol = IWM
secType = STK
exchange = SMART
currency = USD
localSymbol =
order_msg:
order id =47
client id =0
action =BUY
quantity =50
type =LMT
lmtPrice =10.0
TIF =DAY
parent Id =0
permId =1309177719
order_state_msg:
status =Submitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=47, clientId=0, permId=1309177719, status=Submitted filled=0, remaining=50,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
openOrderEnd> Ended
*****************************
**** MARKET ORDER ****
--------------------------------------------------------
openOrder> open order: orderId=53 ---
contract_msg:
conid = 270639
symbol = INTC
secType = STK
exchange = SMART
currency = USD
localSymbol = INTC
order_msg:
order id =53
client id =0
action =BUY
quantity =20
type =MKT
lmtPrice =0.0
TIF =DAY
parent Id =0
permId =888579470
order_state_msg:
status =Filled
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=53, clientId=0, permId=888579470, status=Filled filled=20, remaining=0,
avgFillPrice=14.36, lastFillPrice=14.36, parent Id=0, whyHeld=
--------------------------------------------------------
openOrder> open order: orderId=53 ---
contract_msg:
conid = 270639
symbol = INTC
secType = STK
exchange = SMART
currency = USD
localSymbol = INTC
order_msg:
order id =53
client id =0
action =BUY
quantity =20
type =MKT
lmtPrice =0.0
TIF =DAY
parent Id =0
permId =888579470
order_state_msg:
status =Filled
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=53, clientId=0, permId=888579470, status=Filled filled=20, remaining=0,
avgFillPrice=14.36, lastFillPrice=14.36, parent Id=0, whyHeld=
--------------------------------------------------------
openOrder> open order: orderId=53 ---
contract_msg:
conid = 270639
symbol = INTC
secType = STK
exchange = SMART
currency = USD
localSymbol = INTC
order_msg:
order id =53
client id =0
action =BUY
quantity =20
type =MKT
lmtPrice =0.0
TIF =DAY
parent Id =0
permId =888579470
order_state_msg:
status =Filled
initMargin =
maintMargin =
commission =1.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=53, clientId=0, permId=888579470, status=Filled filled=20, remaining=0,
avgFillPrice=14.36, lastFillPrice=14.36, parent Id=0, whyHeld=
--------------------------------------------------------
*** requesting open orders ***
openOrder> open order: orderId=47 ---
contract_msg:
conid = 9579970
symbol = IWM
secType = STK
exchange = SMART
currency = USD
localSymbol =
order_msg:
order id =47
client id =0
action =BUY
quantity =50
type =LMT
lmtPrice =10.0
TIF =DAY
parent Id =0
permId =1309177719
order_state_msg:
status =Submitted
initMargin =
maintMargin =
commission =1.7976931348623157e+308
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
orderStatus>: orderId=47, clientId=0, permId=1309177719, status=Submitted filled=0, remaining=50,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=
openOrderEnd> Ended
disconnected
Note:
- Order for IWM submitted yesterday is in Submitted status(it was in PreSubmitted last night).
- After submitting an order for PFE, calling cancelOrder() method causes an 'Order Canceled' message to be returned and orderStatus() callback method is called with the order status of Cancelled.
- Market order to purchase INTC status is Filled and triggers orderStatus() callback method multiple times.
- Purchase of INTC can be verified in TWS.
No comments:
Post a Comment