Sunday, March 1, 2009

Proof Of Concept 8 of 8d : Order Status

TWS API offers three methods to check open orders. They are reqOpenOrders(), reqAllOpenOrders(), and reqAutoOpenOrders(). Results are supplied through EWrapper's orderStatus() and openOrder() callback methods.

reqOpenOrders() and reqAllOpenOrders() are both one time calls and current open order information is provided through the callback methods.

reqAutoOpenOrders() works a little bit differently. It is a 'continuous' method such that it gets turned 'on' when called with a TRUE parameter. Current open order information will be fed through the callback methods. In addition, any future open orders will also get reported until the method is turned 'off' with a FALSE parameter. I'm not sure how useful this 'continuous' method will be for my application, so I will not pay attention to this method now.

In this example, I have set up two open orders. One is a day order to buy CAT stock and the other is a good-to-cancel options order to sell RUT MARCH 490 call.



The code demonstrating reqAllOpenOrders() is as follows:

require 'java'
require 'TwsApi.jar'

include_class 'ib.client.EClientSocket'
include_class 'ib.client.Contract'
include_class 'ib.client.Order'
include_class 'ib.client.OrderState'
include_class 'ib.client.AnyWrapper'
include_class 'ib.client.EWrapper'



class TestOrderStatus
include EWrapper #note "class TestMktData < EWrapper" syntax is no longer supported in JRuby 1.0

@mySocket

def initialize
puts 'init'
@mySocket = EClientSocket.new(self)
end

def eConnect
@mySocket.eConnect("127.0.0.1", 7496, 0)
end

# To request the open orders that were placed from this client. Each open
# order will be fed back through the openOrder() and orderStatus() functions
# on the EWrapper.
# This is a one time shot call. When its done you DO NOT continue to receive
# information about new placed orders
def reqOpenOrders
@mySocket.reqOpenOrders
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

# Request that newly created TWS orders be implicitly associated with the client
# Bind - If set to TRUE, newly created TWS orders will be implicitly associated
# with the client. If set to FALSE, no association will be made.
#
def reqAutoOpenOrders(bind)
@mySocket.reqAutoOpenOrders(bind)
end


def eDisconnect
@mySocket.eDisconnect
end

def requestStockQuote(id, ticker)
# --------------------------------
myContract = Contract.new
myContract.m_symbol = ticker
myContract.m_secType = 'STK'
myContract.m_exchange = 'SMART'
myContract.m_currency = 'USD'
request_id = id
ticklist = ''

puts '>requestStockQuote - calling reqMktData id='+id.to_s+', ticker='+ticker
@mySocket.reqMktData(request_id, myContract, ticklist, true)
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 ' expiry = ' + contract.m_expiry.to_s
puts ' strike = ' + contract.m_strike.to_s
puts ' right = ' + contract.m_right
puts ' multiplier = ' + contract.m_multiplier.to_s
puts ' exchange = ' + contract.m_exchange.to_s
puts ' primaryExch = ' + contract.m_primaryExch.to_s
puts ' currency = ' + contract.m_currency
puts ' localSymbol = ' + contract.m_localSymbol
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 ' auxPrice =' + order.m_auxPrice.to_s
puts ' TIF =' + order.m_tif.to_s
puts ' parent Id =' + order.m_parentId.to_s
puts ' permId =' + order.m_permId.to_s
puts ' outsideRth =' + order.m_outsideRth.to_s
puts ' hidden =' + order.m_hidden.to_s
puts ' discretionaryAmt=' + order.m_discretionaryAmt.to_s
puts ' triggerMethod=' + order.m_triggerMethod.to_s
puts ' goodAfterTime=' + order.m_goodAfterTime.to_s
puts ' goodTillDate =' + order.m_goodTillDate.to_s
puts ' faGroup =' + order.m_faGroup.to_s
puts ' faMethod =' + order.m_faMethod.to_s
puts ' faPercentage =' + order.m_faPercentage.to_s
puts ' faProfile =' + order.m_faProfile.to_s
puts ' shortSaleSlot=' + order.m_shortSaleSlot.to_s
puts ' designatedLocation=' + order.m_designatedLocation.to_s
puts ' ocaGroup =' + order.m_ocaGroup.to_s
puts ' ocaType =' + order.m_ocaType.to_s
puts ' rule80A =' + order.m_rule80A.to_s
puts ' allOrNone =' + order.m_allOrNone.to_s #yes=1, no=0
puts ' minQty =' + order.m_minQty.to_s
puts ' percentOffset=' + order.m_percentOffset.to_s
puts ' eTradeOnly =' + order.m_eTradeOnly.to_s
puts ' firmQuoteOnly=' + order.m_firmQuoteOnly.to_s
puts ' nbboPriceCap =' + order.m_nbboPriceCap.to_s
puts ' auctionStrategy=' + order.m_auctionStrategy.to_s
puts ' startingPrice=' + order.m_startingPrice.to_s
puts ' stockRefPrice=' + order.m_stockRefPrice.to_s
puts ' delta =' + order.m_delta.to_s
puts ' stockRangeLower=' + order.m_stockRangeLower.to_s
puts ' stockRangeUpper=' + order.m_stockRangeUpper.to_s
puts ' volatility =' + order.m_volatility.to_s
puts ' volatilityType=' + order.m_volatilityType.to_s
puts ' deltaNeutralOrderType=' + order.m_deltaNeutralOrderType.to_s
puts ' deltaNeutralAuxPrice=' + order.m_deltaNeutralAuxPrice.to_s
puts ' continuousUpdate=' + order.m_continuousUpdate.to_s
puts ' referencePriceType=' + order.m_referencePriceType.to_s
puts ' trailStopPrice=' + order.m_trailStopPrice.to_s
puts ' account =' + order.m_account # institutional only
puts ' settlingFirm =' + order.m_settlingFirm.to_s
puts ' clearingAccount=' + order.m_clearingAccount.to_s
puts ' clearingIntent=' + order.m_clearingIntent.to_s
puts ' whatIf =' + order.m_whatIf.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 ' equityWithLoan=' + order_state.m_equityWithLoan.to_s
puts ' commission =' + order_state.m_commission.to_s
puts ' minCommission =' + order_state.m_minCommission.to_s
puts ' maxCommission =' + order_state.m_maxCommission.to_s
puts ' commissionCurrency=' + order_state.m_commissionCurrency.to_s
puts ' warningText =' + order_state.m_warningText.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 '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 '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

def nextValidId( order_id)
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

# ---------------------------------------------------
# -- 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 # class TestOrderStatus

#*********************************************************************************************
# Running the code
# *********************************************************************************************
x = TestOrderStatus.new()
begin
x.eConnect
puts 'connected ...'
x.reqAllOpenOrders # requesting open orders information
x.requestStockQuote(-99, 'DONE_OPEN_ORDERS') # call to reqMktData() for invalid quote.
# Will generate error AFTER all
# open orders info are returned
sleep(5)
x.eDisconnect
puts 'disconnected'
rescue Exception => e
puts 'Exception>>' + e.message
x.eDisconnect
end


Examining the code shows the program structure to be consistent with my previous examples of TWS API. Information is requested and it is delivered asynchronously via callback methods. However, a major drawback to this model is that there is no event or indicator that the information being delivered is finished. This is where a workaround is needed. One way to do this is to immediately issue a reqMktData() with an invalid ticker symbol to intentionally cause an error. This error will be fed through error() callback method after the open order request is finished.
Line 287 demonstrates this workaround. It's not very elegant and I will have to keep this in mind when designing the application.

Running the code produces the following output:


init
Server Version:43

TWS Time at connection:20090301 16:07:19 EST

connected ...
>requestStockQuote - calling reqMktData id=-99, ticker=DONE_OPEN_ORDERS
openOrder> open order: orderId=2 ---
contract_msg:
conid = 54528396
symbol = RUT
secType = OPT
expiry = 20090319
strike = 490.0
right = C
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = RUWCA
order_msg:
order id =2
client id =0
action =SELL
quantity =1
type =LMT
lmtPrice =2.0
auxPrice =0.0
TIF =GTC
parent Id =0
permId =1664800509
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PendingSubmit
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=2, clientId=0, permId=1664800509, status=PendingSubmit filled=0, remaining=1,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

openOrder> open order: orderId=1 ---
contract_msg:
conid = 5437
symbol = CAT
secType = STK
expiry =
strike = 0.0
right = ?
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = CAT
order_msg:
order id =1
client id =0
action =BUY
quantity =100
type =LMT
lmtPrice =20.0
auxPrice =0.0
TIF =DAY
parent Id =0
permId =1664800505
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PreSubmitted
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=1, clientId=0, permId=1664800505, status=PreSubmitted filled=0, remaining=100,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

[API.msg2] Market data farm connection is OK:usopt {-1, 2104}
[API.msg2] Market data farm connection is OK:usfarm {-1, 2104}
openOrder> open order: orderId=2 ---
contract_msg:
conid = 54528396
symbol = RUT
secType = OPT
expiry = 20090319
strike = 490.0
right = C
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = RUWCA
order_msg:
order id =2
client id =0
action =SELL
quantity =1
type =LMT
lmtPrice =2.0
auxPrice =0.0
TIF =GTC
parent Id =0
permId =1664800509
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PendingSubmit
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=2, clientId=0, permId=1664800509, status=PendingSubmit filled=0, remaining=1,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

openOrder> open order: orderId=1 ---
contract_msg:
conid = 5437
symbol = CAT
secType = STK
expiry =
strike = 0.0
right = ?
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = CAT
order_msg:
order id =1
client id =0
action =BUY
quantity =100
type =LMT
lmtPrice =20.0
auxPrice =0.0
TIF =DAY
parent Id =0
permId =1664800505
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PreSubmitted
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=1, clientId=0, permId=1664800505, status=PreSubmitted filled=0, remaining=100,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

[API.msg2] No security definition has been found for the request {-99, 200}
disconnected



Note that even though I currently have two open orders (RUT call option and CAT), callback methods get triggered twice for each order. I'm not sure why this happens, but fortunately, orderId is unique so I can use it to tell if an order is an original or duplicate.

After experimenting some more, I found out that when a connection is made to TWS, a call to reqAllOpenOrders() is automatically issued. Since my code example explicitly calls reqAllOpenOrders(), two sets of information get printed. Changing the code to the following proves my point:

# *********************************************************************************************
# Running the code
# *********************************************************************************************
x = TestOrderStatus.new()
begin
x.eConnect
puts 'connected ...'
sleep(5)
x.eDisconnect
puts 'disconnected'
rescue Exception => e
puts 'Exception>>' + e.message
x.eDisconnect
end



init
Server Version:43

TWS Time at connection:20090301 17:11:38 EST

connected ...
openOrder> open order: orderId=2 ---
contract_msg:
conid = 54528396
symbol = RUT
secType = OPT
expiry = 20090319
strike = 490.0
right = C
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = RUWCA
order_msg:
order id =2
client id =0
action =SELL
quantity =1
type =LMT
lmtPrice =2.0
auxPrice =0.0
TIF =GTC
parent Id =0
permId =1664800509
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PendingSubmit
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=2, clientId=0, permId=1664800509, status=PendingSubmit filled=0, remaining=1,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

openOrder> open order: orderId=1 ---
contract_msg:
conid = 5437
symbol = CAT
secType = STK
expiry =
strike = 0.0
right = ?
multiplier =
exchange = SMART
primaryExch =
currency = USD
localSymbol = CAT
order_msg:
order id =1
client id =0
action =BUY
quantity =100
type =LMT
lmtPrice =20.0
auxPrice =0.0
TIF =DAY
parent Id =0
permId =1664800505
outsideRth =false
hidden =false
discretionaryAmt=0.0
triggerMethod=0
goodAfterTime=
goodTillDate =
faGroup =
faMethod =
faPercentage =
faProfile =
shortSaleSlot=0
designatedLocation=
ocaGroup =
ocaType =3
rule80A =
allOrNone =false
minQty =0
percentOffset=0.0
eTradeOnly =false
firmQuoteOnly=false
nbboPriceCap =0.0
auctionStrategy=0
startingPrice=0.0
stockRefPrice=0.0
delta =0.0
stockRangeLower=0.0
stockRangeUpper=0.0
volatility =0.0
volatilityType=0
deltaNeutralOrderType=None
deltaNeutralAuxPrice=0.0
continuousUpdate=0
referencePriceType=0
trailStopPrice=0.0
account =DU58265
settlingFirm =DEMO
clearingAccount=
clearingIntent=IB
whatIf =false
order_state_msg:
status =PreSubmitted
initMargin =
maintMargin =
equityWithLoan=
commission =1.7976931348623157e+308
minCommission =1.7976931348623157e+308
maxCommission =1.7976931348623157e+308
commissionCurrency=USD
warningText =
orderStatus>: orderId=1, clientId=0, permId=1664800505, status=PreSubmitted filled=0, remaining=100,
avgFillPrice=0.0, lastFillPrice=0.0, parent Id=0, whyHeld=

[API.msg2] Market data farm connection is OK:usopt {-1, 2104}
[API.msg2] Market data farm connection is OK:usfarm {-1, 2104}
disconnected




03/09/09 Update

Upgrading to API v. 9.60
requires addition of these new callback methods.

 
# ---------------------------------------------------
# new callback methods added in API 9.60
# ---------------------------------------------------
def openOrderEnd() # invoked when all orders are sent to a client as a response to reqOpenOrders() and right after connected to TWS
puts 'openOrderEnd()'
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

Running the code produces the same result except openOrderEnd() method is called back.

...
openOrderEnd()
disconnected

2 comments:

Anonymous said...

Hi,
Interesting blog post.
Any reason you didn't use the ib-ruby library?

I think there is now (just added) 'end-of-...' call back method for data such as orders, and others - haven't used it but seems it's worth updating the API version you use.

HTH

System Trader said...

I did look at ib-ruby, but I felt it was better for me to stay with TWS Java API since it has a larger user base.

And yes, I just looked at IB site yesterday and noticed the endxxx callback methods on new v. 5.60. I've made the decision to upgrade to this version and will post new entry shortly.

Thanks!