ranaroussi / ezibpy

ezIBpy, a Pythonic Client for Interactive Brokers API
Apache License 2.0
324 stars 116 forks source link

Bracket Order for stock - target order Id doesn't work #2

Closed rossdem699 closed 7 years ago

rossdem699 commented 7 years ago

Ran, i am trying to create a bracket order for TSLA but i think the orderID's aren't incrementing correctly. I get a reply from TWS but order ID's are 1 , 2 & 3. So i am guessing that i am not creating orders with ID's that start at 504. I would expect that my order id's should be 504,505 & 506. Is this correct? Any assistance on using this component of ezibpy would be much appreciated.

Below is the code i used and the results i get back.

import ezibpy import time

initialize ezIBpy

ibConn = ezibpy.ezIBpy() ibConn.connect(clientId=100, host="localhost", port=7496)

create a contract

contract = ibConn.createStockContract("TSLA")

submit a bracket order (entry=0 = MKT order)

order=ibConn.createBracketOrder(contract,quantity=1,entry=0,target=210,stop=190,targetType=None,trailingStop=None,group=None,tif="DAY",fillorkill=False,iceberg=False,rth=False,stop_limit=False)

orderId = ibConn.placeOrder(contract,order,orderId=504)

let order fill

time.sleep(5)

see the positions

print("Positions") print(ibConn.positions) print(orderId) print(order)

disconnect

ibConn.disconnect() The output I get seems that my OrderId’s aren’t working correctly.

Server Version: 76 TWS Time at connection:20161016 14:24:49 Australian Eastern Standard Time (Victoria) Positions {} 504 {'targetOrderId': 2, 'entryOrderId': 1, 'stopOrderId': 3, 'group': 'bracket_1476588290'}

Process finished with exit code 0

I think the order Id’s are incrementing but the orderId isn’t using my 504 above.

    # main order
    enteyOrder = self.createOrder(quantity, price=entry, transmit=False,
        tif=tif, fillorkill=fillorkill, iceberg=iceberg, rth=rth)
    entryOrderId = self.placeOrder(contract, enteyOrder)

    # target
    targetOrderId = 0
    if target > 0:
        targetOrder = self.createTargetOrder(-quantity,
            parentId  = entryOrderId,
            target    = target,
            transmit  = False if stop > 0 else True,
            orderType = targetType,
            group     = group,
            rth       = rth

        )
        targetOrderId = self.placeOrder(contract, targetOrder, self.orderId+1)
ranaroussi commented 7 years ago

Hi,

ezIBpy uses the next available orderId by querying TWS when it starts. By default, order IDs always starts at 1 for every client id used by TWS (you can reset the order ids via TWS, tho).

Creating a single order involves 2 steps:

  1. creating the order using ibConn.createOrder(...)
  2. submitting the order using ibConn.placeOrder(...)

When you call ibConn.placeOrder(...) and passes a value for orderId, it uses that order id to place the order.

However, bracket orders auto-submits the order and therefore using the next available order id as returned by TWS.

ibConn.createBracketOrder(...), automatically creates and submits the order group and simply returns the order ids for the entry, target and stop orders. When you then call ibConn.placeOrder(...) - it does nothing since you actually passed the order ids dict and not an order object.

If you would have submitted a single order first with an id of 500, and then created a bracket order - it would have used 501, 502 and 503 automatically as these are the next available order ids.

I hope this makes things a little bit clearer... Please LMK if that made sense :)

Ran

rossdem699 commented 7 years ago

Day2.

import ezibpy import time

initialize ezIBpy

ibConn = ezibpy.ezIBpy() ibConn.connect(clientId=100, host="localhost", port=7496)

create a contract

contract = ibConn.createStockContract("TSLA")

submit a bracket order (entry=0 = MKT order)

order = ibConn.createBracketOrder(contract,quantity=1,entry=0,target=210,stop=190,targetType=None,trailingStop=None, group=None,tif="DAY",fillorkill=False,iceberg=False,rth=False,stop_limit=False)

orderId = ibConn.placeOrder(contract,order,orderId=510)

orderId = ibConn.placeOrder(contract,order)

let order fill

time.sleep(30)

see the positions

print("Positions") print(ibConn.positions) print(orderId) print(order)

disconnect

ibConn.disconnect() Result >>> I have logged into TWS for the first time today. First time I submit order with above code to TWS – notes, I dropped the “orderId=510” when placing this order. TWS hasn’t received order. The returned result is ----

/usr/bin/python3.5 /usr/lib/python3.5/tzlocal-1.2.2/ezIBPY.py Server Version: 76 TWS Time at connection:20161017 09:20:42 Australian Eastern Standard Time (Victoria) Positions {} 509 {'entryOrderId': 509, 'group': 'bracket_1476656443', 'targetOrderId': 510, 'stopOrderId': 511}

Process finished with exit code 0 ###################################### This is the second time I run above code and again, order isn’t submitted on TWS and order ID’s have reset to 1,2,3. >>>>> #######################################

/usr/bin/python3.5 /usr/lib/python3.5/tzlocal-1.2.2/ezIBPY.py Server Version: 76 TWS Time at connection:20161017 09:23:33 Australian Eastern Standard Time (Victoria) Positions {} 1 {'group': 'bracket_1476656614', 'stopOrderId': 3, 'entryOrderId': 1, 'targetOrderId': 2}

Process finished with exit code 0

Ran, I don’t have the python skills to digest the code and get this to simply place a bracket order as defined above for TSLA.

TWS doesn’t receive my bracket order at this stage? Could this be a timing issue? Maybe the parent order needs to be created first then profit target and finally stop order?

And when I first start TWS and then place order as above, it uses my previous last orderID used yesterday ie. 509, 510 & 511 but then resets to 1,2 & 3 for my next bracket order. Ideally, it should increment from 511 onwards – so maybe it needs to query TWS before building the bracket order for previous orderID’s used and then build bracket order.

I am very excited by your work and really want to implement ezIBpy into real trading strategies. Your package, ezIBpy, can simplify IBPY coding and greatly increase the speed to getting order execution done in less than 10 lines of code!!!! and I only have 2 months python coding experience...huge potential.

Thank you Heaps for your efforts.

ranaroussi commented 7 years ago

If you're using edemo/demouser - it may reset the order ids whenever you start TWS.

What I wrote earlier is that currently you cannot decide on an order id when creating a bracket order as it will automatically use the next available order id.

If the previous order was 500, then the next bracket order will use 501-503. If this is your first order sent, the bracket order will use 1-3.

If you don't mind me asking... is there a specific reason you need the bracket order to use 501-503? Why do you care what the Order ID is?

rossdem699 commented 7 years ago

Ran,

thanks again for taking the time to reply. I'm using a paper trading account to test python code and not the edemo/demouser account. I have been able to use your ezIBPY to extract current holdings in my trading account and also to just place an order for a stock. All with very little code thanks to your python skills.

I don't care using order ID's 1,2 &3 but either order ID's are not creating the bracket order on the TWS platform. After viewing some IBPY tutorials on creating orders - there is often a reference to the need to increment the orderID so i have just assumed this may be the issue with creating the bracket order. I really don't know. This is also noted when using ezIBPY to submit consecutive "BUY" orders - i had to +1 to the order ID to have it placed on the TWS platform. It doesn't matter what the order ID's are - my bracket order just doesn't get placed. I have also thought that in my attached code above i haven't determined if it is a 'BUY' or 'SELL' bracket order for the parent order. Could this be the reason my bracket order isn't being placed?

Are you able to place a bracket order as defined above?

Again - thanks for your time and patience.

On Wed, Oct 19, 2016 at 2:46 AM, Ran Aroussi notifications@github.com wrote:

If you're using edemo/demouser - it may reset the order ids whenever you start TWS.

What I wrote earlier is that currently you cannot decide on an order id when creating a bracket order as it will automatically use the next available order id.

If the previous order was 500, then the next bracket order will use 501-503. If this is your first order sent, the bracket order will use 1-3.

If you don't mind me asking... is there a specific reason you need the bracket order to use 501-503? Why do you care what the Order ID is?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ranaroussi/ezibpy/issues/2#issuecomment-254550060, or mute the thread https://github.com/notifications/unsubscribe-auth/AVtWyxP84zxAC4trcGKpjsjLeinTwcOCks5q1OnBgaJpZM4KX4pg .

rossdem699 commented 7 years ago

Ran, I have some great news, i think i figured out the issue - I added some time.sleep(1) to code and the bracket order is placed correctly and the order ID's are also incrementing. I will post code below as it might help others. Thank you for your efforts and i love this ezIBPY wrapper - makes programming for a novice like me so much easier. Happy trading and i look forward to your future work.

import ezibpy import time

initialize ezIBpy

ibConn = ezibpy.ezIBpy() ibConn.connect(clientId=100, host="localhost", port=7496)

create a contract

contract = ibConn.createStockContract("TSLA")

time.sleep(1)#this just fixed it auto increment orderID's!!!!

submit a bracket order (entry=0 = MKT order)

order = ibConn.createBracketOrder(contract,quantity=10,entry=200.00,target=230.00,stop=150.00,targetType=None,trailingStop=None, group=None,tif="DAY",fillorkill=False,iceberg=False,rth=False,stop_limit=False)

time.sleep(1)#this seems to make it all work? and at 1 sec works fine.

orderId = ibConn.placeOrder(contract,order,orderId=510)

orderId = ibConn.placeOrder(contract,order)

let order fill

time.sleep(1)

see the positions

print("Positions") print(ibConn.positions) print(orderId) print(order)

disconnect

ibConn.disconnect()