Launching IB controller and sending an order as a user dependent array?

I'm still very much experimenting and trying to learn how to use the programme properly.

I am going wrong with this script though. I am trying to learn how to write a script that opens the IB controller if 'something happens' (as specified elsewhere in the script) and then take an order from an array. A variation on this would be to take the value of the order from a user variable (In real life, I probably wouldn't do it exactly that way, but I'm tying to play with user specified parameters so that I could have that usability as I think that would be beneficial in the future when I start to involve my partner in the trading.

I'm new to afl and pretty new to coding.

Here's my try;

// Define the boolean user input variable.
launchIB = ParamToggle(" Launch IB Controller? ","No|Yes",0);

// Define ibc array as a function
ibc=GetTradingInterface("IB");
NaN = 0;
// Function to Launch IB controller if user selects yes
IIf(launchIB == 1, ibc, NaN);

//Allow the user to specify if they would like to set an order
setorder = ParamToggle(" Set an order? ","No|Yes",0);

//Define price array to use in the order
price = Param("Price to Buy",100, 0,500,1);


order = ibc.PlaceOrder("MSFT","Buy",101,"LMT",price,0,"GTD 20220916, 19:00:00 GMT", True); //define what order is
IIf(setorder =="Yes",order,NaN);// Trigger 'order' if boolean 'setorder' is true and therefore ==Yes

When I execute this code, the trading interface is launched and an order is sent to TWS, which is very exciting, because I made it do something, but very frustrating, because it is not doing the thing I want it to.

I have read the reference and my understanding is that the resulting value from both 'launchIB' and 'setorder' should be arrays?

I'm getting;
Error 1. Operation not allowed. operator/operand type mismatch
and
Error 5. 2nd argument of the IIf() call has incorrect type. The function expected a number here but found a string.

So, I'm a little lost. I know what a string is (so here I am guessing it is picking up "MSFT","Buy"... etc) but if I have set an array (e.g

ibc=GetTradingInterface("IB");

and

order = ibc.PlaceOrder("MSFT","Buy",101,"LMT",price,0,"GTD 20220916, 19:00:00 GMT", True);

then my thinking is that AmiBroker would return the array 'order' and that would launch IB controller and place an order if those arrays are returned.

Any advice on what I might not be understanding and how to achieve what I am trying to achieve?

Thanks

PlaceOrder() returns a string with the orderID, or it returns the number zero if the call failed. It doesn't return an array.

Your code has multiple issues and you were calling the ibc object and sending the order with every chart refresh. Since you only want to call PlaceOrder when the user clicks a button, you should have used If() and not IIf() which is a totally different function.

Also you used ParamToggle() but should have used ParamTrigger() for what you were trying to do. And you have to put the PlaceOrder() call inside of the If() code.

The reference code for AT is on this page:
https://www.amibroker.com/at/

Here's the reference code. Read it multiple times so you can learn how it works, and then you can adapt it. From: IBController 1.3.8 READ ME

// Param block
TriggerOrder= ParamTrigger("Place order","Click here to place order");
Mode=ParamToggle("Mode","Modify existing|Always place new order");
ACT = ParamList("Action", "BUY|SELL|SSHORT");
OT = ParamList("Order Type", "MKT|LMT|STP");
TIF = ParamList("Time In Force", "DAY|GTC|IOC");
Ticker = ParamStr("Ticker",Name());
NumShares = Param("Number of Shares",10,10,100,10);
LimitPrice = LastValue(C) + Param("Limit Price offset",0,-0.1,0.1,0.01);
StopPrice = LastValue(C) + Param("Stop price offset",0,-0.1,0.1,0.01);
Transmit = ParamToggle("Transmit","Do NOT transmit|Transmit",0);
TriggerCancel = ParamTrigger("Cancel Order","Click here to Cancel order");

Msg = ""; // this variable stores error message text

// create instance of trading interface
ibc = GetTradingInterface("IB");

// retrieve orderID from previous run, will be empty if no order was placed before
OrderID = StaticVarGetText("OrderID"+Ticker);

if( TriggerOrder )
{
// check if we are connected OK
if( ibc.IsConnected() )
{
   if( Mode == 1 ) OrderID = ""; // if mode set to 'always new' then clear orderid

   // place orders only if we do not have already open position on this symbol
   // place or modify the order - don't transmit yet
   OrderID = ibc.ModifyOrder( OrderID, Ticker,
         ACT, NumShares, OT, LimitPrice, StopPrice, TIF, Transmit);
  

   // store orderID for next run so we know which order to modify

   StaticVarSetText("OrderID"+Ticker, OrderID);
  
   if( Mode == 1 )
       Msg = "New order has been placed with ID = ";
   else
       Msg = "Order placed/modified with ID = ";

   Msg = Msg + OrderID + " on " + Now();
}
else
{
   Msg = "Placing order failed because of no connection to TWS";
}
}

if( TriggerCancel )
{
  if( OrderId != "" )
   {
    if( ibc.CancelOrder( OrderId ) )
       Msg = "Request to cancel order " + OrderID + " sent successfully";
    else
       Msg = "Request to cancel order " + OrderID + " failed.";
   }
  else
     Msg = "Can not cancel order becase OrderID is empty";

}

execlist = ibc.GetExecList(0,""); // all

execinfo = "";
for( i = 0; ( OId = StrExtract( execlist, i ) ) != ""; i++ )
{
   execinfo = execinfo + OID + " Symbol: " + ibc.GetExecInfo( OID, "Symbol" ) +
             " Filled: " + ibc.GetExecInfo( OID, "Filled" ) +
             " Avg. price: " + ibc.GetExecInfo( OID, "Avg. price" ) + "\n";

}

References:
https://www.amibroker.com/at/
https://www.amibroker.com/guide/a_language.html
https://www.amibroker.com/guide/afl/paramtrigger.html
https://www.amibroker.com/guide/afl/iif.html
https://www.amibroker.com/guide/a_mistakes.html
https://www.amibroker.com/guide/afl/_trace.html

1 Like

Perfect. That makes Perfect sense. Thanks.