Autotrading script not always working when started from batch scheduler

Hello guys,

I'm totally clueless... it all seems to work as it should but when called from a batch file and the scheduler my orders are not always transmitted to IB Gateway.

I run a few different batches files each morning:

  • update norgate DB at 08:45
  • check TWS or IB Gateway is running at 08:55 and 09:05
  • clean daily persistent variables at 09:10
  • the autotrading script at 09:15

Somehow, sometimes the last script will NOT generate orders when called from the batch file by the scheduler... but running that batch file manually will work...

I know the scheduler does run the script (it sends an email saying so) but the orders are not sent reliably to IB...

Here is the autotrading part of the script:

	// AUTOTRADING
	ibc = GetTradingInterface("IB");
	if( ibc.IsConnected() AND LastValue(Buy) AND LastValue(rank <= MaxPositions)) // check if connection to IB was successfull
	{	
		// Prepating Contracts : SYMBOL-EXCHANGE-TYPE-CURRENCY
		//StockMarketName = StrToUpper( MarketID(1) );
		//StockMarketName = WriteIf(StockMarketName=="NASDAQ","ISLAND",StockMarketName);
		//StockMarketName = WriteIf(StockMarketName=="NYSE","SMART",StockMarketName);
		StockMarketName = "SMART";
		ContractFullName = Name() + "-" + StockMarketName + "-STK-USD";
		ContractSmartName = Name() + "-SMART-STK-USD";
		
		// retrieve BUYSTP_OrdID from previous run of THIS strategy, will be empty if no order was placed before  
		BUYSTP_OrdID = StaticVarGetText(StrategyName+"BUYSTP_OrdID_"+Name());
		_TRACE("###BUYSTP_OrdID = StaticVarGetText:" + BUYSTP_OrdID);
		
		// Create Order if it's before 10:00 AND the order ID is empty
		if( Now(4) < 154000 AND BUYSTP_OrdID=="")
		{
			// It's not too late to place the order
			BUYSTP_OrdID = ibc.ModifyOrder(BUYSTP_OrdID, ContractFullName, "BUY", LastValue(BuyQuantity), "STP", 0, LastValue(LimitPrice), "DAY", True ); // place order but do not transmit yet

			// Error handling
			BUYSTP_Error = ibc.GetLastError(BUYSTP_OrdID);
			if (BUYSTP_Error != "")
			{
				SendEmail(StrategyName+"-ERROR-BUYSTP for Ticker: "+Name()+" Name: "+FullName(), BUYSTP_Error);
				Say("Error with Ticker "+Name()+" Name "+FullName()+" API Error Message is "+BUYSTP_Error);
				// Pushover
				messageurl = url + "Error BUYSTP with Ticker "+Name()+" API Error Message is "+BUYSTP_Error;
				internetconnection = InternetOpenURL(messageurl);
				InternetClose(internetconnection);
			}
			else
			{
				SendEmail(StrategyName+"-SUCCESS-BUYSTP for Ticker: "+Name()+" Name: "+FullName(),"Sent Buy Order for "+LastValue(BuyQuantity)+" of :"+Name());
				Say("Sent "+LastValue(BuyQuantity)+" "+Name());
				// Pushover
				messageurl = url + "Sent order for: "+LastValue(BuyQuantity)+" "+Name();
				internetconnection = InternetOpenURL(messageurl);
				InternetClose(internetconnection);
			}
			
			MOC_OrdID = StaticVarGetText(StrategyName+"MOC_OrdID_"+Name());
			_TRACE("###MOC_OrdID = StaticVarGetText:" + MOC_OrdID);
			
			MOC_OrdID = ibc.ModifyOrder(MOC_OrdID, ContractFullName, "SELL", LastValue(BuyQuantity), "MOC", 0, 0, "DAY", True, 100, "", BUYSTP_OrdID );
			
			// Error handling
			MOC_Error = ibc.GetLastError(MOC_OrdID);
			if (MOC_Error != "")
			{
				SendEmail(StrategyName+"-ERROR-MOC for Ticker: "+Name()+" Name: "+FullName(), MOC_Error);
				Say("Error with Ticker "+Name()+" Name "+FullName()+" API Error Message is "+MOC_Error);
				// Pushover
				messageurl = url + "Error MOC with Ticker "+Name()+" API Error Message is "+MOC_Error;
				internetconnection = InternetOpenURL(messageurl);
				InternetClose(internetconnection);
			}			
			
			// store BUYSTP_OrdID for next run so we know which order to modify, set as Persistent to be available when the script
			// is called later in the day to generate MOC orders
			StaticVarSetText(StrategyName+"BUYSTP_OrdID_"+Name(), BUYSTP_OrdID, True);
			StaticVarSetText(StrategyName+"MOC_OrdID_"+Name(), MOC_OrdID, True);
		}		
		
		
	}

As you guess the persistent variables "cleaning" done every morning is deleting the variables from the previous day (it's a daily MOO and MOC strategy).

From what I can see, the only plausible problem could be that ibc.IsConnected is NOT TRUE at the time the script is run... which would be super annoying since I'm checking that 10 and 20 minutes before running the script...

Amibroker is running on a VPS so I would expect the connection to IB to be a lot more reliable than from my home wifi (where I get IB TWS saying disconnected/reconnected a few times a day).

Anybody has an idea of what could be going wrong ?

Have you had the problem of intermitent ibc.IsConnected "deconnections" ?

Thanks a lot for any idea,

You should ammend your formula so it provides some logging for example in case like this:

ibc = GetTradingInterface("IB");

if( ibc )
{
    if( ibc.IsConnected() )
    {
       ... your existing code 
    }
    else
    {
       _TRACE("Ibc is NOT CONNECTED");
     }
}
else
{
   _TRACE("Ibc is NOT INSTANTIATED");
}

Then run with DebugView turned on and you will see what happens.

1 Like

Thanks @Tomasz

OK so as I was suspecting the IsConnected is returning 3... despite IB Gateway being open (autorestarted by itself).

Question : in this thread here you say, concerning return code 3:

Code 3 means "connected BUT error messages are present" and you should check ERROR list to find out if you got log-off.

=> What "ERROR list" are you referring to ? Where is that displayed or available ?

Thanks,

@BenA I suppose it is this one on the InteractiveBrokers online documentation for their API.

1 Like

Thanks @beppe but that's the explanations of the code, not the place where I should find the error codes when running the script.

I suppose it should be in the IB controller > Message tab (?)

Anyway I have discovered the problem:

  1. After the autorestart of IB Gateway if you call ibc.IsConnected you will receive a 0. Actually right before calling ibc you'll see that the IB gateway info window has "client API" status row shown as "red".

  2. Right after the first "call" to ibc you'll see that "client API" status shown as "green" and subsequent calls will return ibc.IsConnected as 2

So it looks like I would need to call ibc TWICE after the IB Gateway restart !!! The first one being some kind of dummy call to "wakeup" the connection to IB Gateway

Anyone has seen that before?

1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.