TWSLink for linking your Application to TWS

Discussion in 'Trading Software' started by maxchinaski, Apr 24, 2007.

  1. Sorry, i didn't see your post.
    well amibroker support:

    they write:
    "the AmiBroker Developlent Kit (ADK) is a package for C/C++ developers allowing to develop own indicator and/or data plugin DLLs. The self-extracting executable contains documentation, headers and working examples for several real-world plugins."


    so they speak about plugin DLLs. TWSLink is a DLL, so i assume it can be used within AmiBroker. Perhaps i will provide a Sample for using it within AmiBroker.
     
    #11     May 11, 2007
  2. Retief

    Retief

    Thanks for the reply. I would certainly appreciate a sample for use with Amibroker. Presently, Amibroker links to the TWS using IB controller. Your application, however, looks like it's much more capable than IBcontroller and can take advantage of more features.
     
    #12     May 11, 2007
  3. Hello all,
    just recognized when testing with AmiBroker that installation routine of new Version forgot Registration for COM.
    That effects e.g. Wealth-Lab, Excel and AmiBroker Users. The new package (which only differs by COM-Registration during Installation).


    Sample lines for those using AmiBroker:
    Open a Chart an attach an .afl File (script,
    e.g. bollinger band). than modify script or make new by these lines to simply place a Buy Limit Order for MSFT.
    (or use file attached)

    // Create a TWSLink instance
    TWSLink = CreateStaticObject("twslink.comif");
    // init the DLL (Optional)
    TWSLink.INITDLL(2,"twslink.log",6,3,3,4000);
    // register microsoft Contract for trading
    ID_MSFT = TWSLink.REGISTER_CONTRACT("MSFT", "STK","USD","SMART","","","",0.0,"",0);
    // connect to TWS
    TWSLink.CONNECT("127.0.0.1", 7496, 4, 5000);
    // place order and transmit to IB
    OidID = TWSLink.BUY_LMT(ID_MSFT, 0,20.77, 100, "GTC", 1);
    // just wait one second to demonstrate the impact
    TWSLink.WAITDLL(1000);
    // modify order (here prior returned OidID provided) and transmit to IB
    OidID = TWSLink.BUY_LMT(ID_MSFT, OidID ,21.77, 100, "GTC", 1);
     
    #13     May 11, 2007
  4. Retief

    Retief

    Thanks. I just tried this with Amibroker and it worked. Looks very promising. I'll have to read your documentation in more detail and check out all of features of TradeCommander in more detail.
     
    #14     May 11, 2007
  5. Retief

    Retief

    maxchinaski, how do I get the average cost for an order that has been executed? I've been using TradeCommander and it's been working pretty well, but I can't figure out how to get average cost because I get an error with GET_CONTRACT_VAL. To get average cost, I've been using IBcontroller and TradeCommander together, but I would like to have a setup where the code only needs to access TradeCommander.

    I also get one other strange error, where I can't transmit the order to the IB TWS. This goes away if I submit the order twice. The code I've been using in Amibroker is below:

     
    #15     May 18, 2007
  6. hello retief,
    please repeat the script with dllloglevel
    set to 1 and send me the logfile.
    otherwise i can't say what is going wrong.

    some general words:

    - function TRANSMIT:
    this function transmits all affected orders to IB.
    using.
    TWSLink.TRANSMIT(OrderUID,ContractUID,"accountlist");
    (accountlist only useful for fa accounts)

    order transmission flag value:
    -1 don't transmit to TWS
    0 transmit to TWS
    1 transmit to IB

    so the lines
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,BuyOrderID,"","",0);
    ostatus = TWSLink.WAIT_FOR_ORDER_STATUS_RNG( StopOrderID,5,8,3000,12) ;

    must lead to a timeout because the order can't have any of the submitted states at this point (transmission flag 0).

    why using additional oca ? i think this could confuse TWS because TWS creates an oca group implicitly if you attach parent orders.


    look at here:


    //Create buy order
    BuyOrderID = TWSLink.Place_Order(ID, 0,"BUY","LMT",LastValue(Shares),LastValue(LimitPrice),0.0,"Day",0,0,"","", 0);

    //Create a STOP ORDER. Create on TWS Side only.
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,BuyOrderID,"","",0);

    //Create the PROFIT ORDER. Create on TWS Side only.
    TargetOrderID = TWSLink.Place_ORder(ID,0,"SELL","LMT",LastValue(Shares),LastValue(Target),0,"GTC",1,BuyOrderID,"","",0);

    // wait until submitted status confirmed by TWS
    ostatus TWSLink.WAIT_FOR_ORDER_STATUS_RNG( TargetOrderID,5,8,3000,12) ;




    this should exactly doing that you want. try to cancel one of the SELL orders. this will cancel all sell orders.
    try cancel Buy Order, this will cancel all Orders.
     
    #16     May 18, 2007
  7. sorry, i forgot, that should retrieve average costs:

    TWSLink.GET_CONTRACT_VAL(ID,13,"","")
     
    #17     May 18, 2007
  8. refill:
    attaching order <-> oca discussion.
    as i said, attaching orders (that is by providing parent order id for function place_order) makes TWS to create an oca group implicitly. you can easily check out this in TWS -> open Order Ticket.

    so what happens if you do it like here:

    //Create buy order
    BuyOrderID = TWSLink.Place_Order(ID, 0,"BUY","LMT",LastValue(Shares),LastValue(LimitPrice),0.0,"Day",0,0,"","", 0);

    //Create a STOP ORDER. Create on TWS Side only.
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,BuyOrderID,"","",0);

    //Create the PROFIT ORDER. Create on TWS Side only.
    TargetOrderID = TWSLink.Place_ORder(ID,0,"SELL","LMT",LastValue(Shares),LastValue(Target),0,"GTC",0,BuyOrderID,"","",0);

    // THIS OVERWRITES OCA group and is no good idea. check oca field in TWS of stop and target order before executing lines below.
    bret = TWSLink.SET_ORDERVAL (TargetOrderID,19,OCA,0);
    bret = TWSLink.SET_ORDERVAL (StopOrderID,19,OCA,0);


    How to do correctly:
    --------------------

    [1] Don't attach, use oca only for SELL orders:
    (cancel one of the sell orders will cancel the other sell order. cancel buy order will ONLY cancel buy order (because buy order in no oca group))

    //Create buy order
    BuyOrderID = TWSLink.Place_Order(ID, 0,"BUY","LMT",LastValue(Shares),LastValue(LimitPrice),0.0,"Day",1,0,"","", 0);

    //Create a STOP ORDER. Create on TWS Side only.
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,0,"","",0);

    //Create the PROFIT ORDER. Create on TWS Side only.
    TargetOrderID = TWSLink.Place_ORder(ID,0,"SELL","LMT",LastValue(Shares),LastValue(Target),0,"GTC",0,0,"","",0);

    // set target and stop in oca (cancelling buy would here not affect stop and target)
    bret = TWSLink.SET_ORDERVAL (TargetOrderID,19,OCA,1);
    bret = TWSLink.SET_ORDERVAL (StopOrderID,19,OCA,1);
    ostatus = TWSLink.WAIT_FOR_ORDER_STATUS_RNG( TargetOrderID,5,8,3000,12) ;


    [2] Don't attach, use oca for all orders:
    (cancel any order will cancel all other orders)

    //Create buy order
    BuyOrderID = TWSLink.Place_Order(ID, 0,"BUY","LMT",LastValue(Shares),LastValue(LimitPrice),0.0,"Day",0,0,"","", 0);

    //Create a STOP ORDER. Create on TWS Side only.
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,0,"","",0);

    //Create the PROFIT ORDER. Create on TWS Side only.
    TargetOrderID = TWSLink.Place_ORder(ID,0,"SELL","LMT",LastValue(Shares),LastValue(Target),0,"GTC",0,0,"","",0);

    // set target and stop in oca (cancelling buy would here not affect stop and target)
    bret = TWSLink.SET_ORDERVAL (BuyOrderID,19,OCA,1);
    bret = TWSLink.SET_ORDERVAL (TargetOrderID,19,OCA,1);
    bret = TWSLink.SET_ORDERVAL (StopOrderID,19,OCA,1);
    ostatus = TWSLink.WAIT_FOR_ORDER_STATUS_RNG( TargetOrderID,5,8,3000,12) ;


    [3] Attach , don't use oca:
    (cancel one of the sell orders will cancel the other sell order;
    cancel buy order cancels all orders)

    //Create buy order
    BuyOrderID = TWSLink.Place_Order(ID, 0,"BUY","LMT",LastValue(Shares),LastValue(LimitPrice),0.0,"Day",0,0,"","", 0);

    //Create a STOP ORDER. Create on TWS Side only.
    StopOrderID = TWSLink.Place_Order(ID,0,"SELL","STP",LastValue(Shares),0.0,LastValue(Stop),"GTC",0,BuyOrderID,"","",0);

    //Create the PROFIT ORDER. Create on TWS Side only.
    // NOTE: the paramvalue after "GTC" is 1, what means transmit to IB. this will transmit all orders of implicit oca group
    // as well.
    TargetOrderID = TWSLink.Place_ORder(ID,0,"SELL","LMT",LastValue(Shares),LastValue(Target),0,"GTC",1,BuyOrderID,"","",0);
    ostatus = TWSLink.WAIT_FOR_ORDER_STATUS_RNG( TargetOrderID,5,8,3000,12) ;





    depending on what you want, use attachments or oca.
     
    #18     May 18, 2007
  9. Retief

    Retief

    maxchinaski,

    With respect to a log file, I used this line: TWSLink.INITDLL(2,"twslink.log",6,1,3,4000);

    However, I searched for twslink.log on my computer drives and could not find the file after executing the Amibroker script.

    Concerning the stop and profit orders, I need option (3) that you described (cancel one of the sell orders will cancel the other sell order; cancel buy order cancels all orders).

    I'm not sure if the buy order will be executed because it's a limit order and so I want the sell orders to be active only if the buy order is executed. Notwithstanding, I don't like the OCA group ID that the TWS assigns by default because it's a long number and so I overwrite the default OCA with a shorter identifier in the Amibroker script.

    I like a shorter OCA identifier because I sometimes close out a position manually when I don't think the profit target will be met. In this situation, I manually enter a tight trailing stop order and type in the OCA identifier. That way, if the trailing stop is executed, it will automatically cancel the other sell orders in a group. If the OCA identifier is too long, it increases the likelihood that I will incorrectly type in the OCA identifier for the trailing stop, which is why I like a shorter OCA identifier than the TWS default.

    The avg cost function seems to be working correctly now. Previously, I was missing one parameter and that was creating an error.

    Thanks for the help.
     
    #19     May 18, 2007
  10. hello retief,
    try TWSLink.INITDLL(2,"c:\\twslink.log",6,1,3,4000);
    or TWSLink.INITDLL(2,"c:\twslink.log",6,1,3,4000);
    instead the next time
     
    #20     May 19, 2007