IBC message "The contract description is ambiguous"


I’m writing code to to place buy orders and to automatically update sell STP and LMT orders that are placed with TWS using the IB Controller. I have no problems with all of my current positions, except for two: MSFT and GDX. For these two positions, I get the error message

CloseLongOrder: Last Error 200. The contract description specified for GDX is ambiguous.

The code is

childId1 = ibc.PlaceOrder( symbol, "SELL", quantity, "LMT", exitLimitPrice, 0, orderTime,
     isTransmit, 100, "", 0, ocaGroup );
ibc.Sleep( 200 );
errMessage = ibc.GetLastError(childId1);
_TRACE("CloseLongOrder: Last Error " + errMessage);

I have also tried using suffix “-SMART-STK”, and it makes no difference:

childId1 = ibc.PlaceOrder( symbol+"-SMART-STK", "SELL", quantity, "LMT", exitLimitPrice,
     0, orderTime, isTransmit, 100, "", 0, ocaGroup );

Strange it is only a problem for some symbols, and not for others. For GDX, I’ve checked the symbol definition on TWS:

Underlying GDX
Security Type STK
Currency USD
Exchange SMART
Primary Exchange ARCA
Symbol GDX
Issuer Country US
Stock type ETF


I think it’s the currency your missing off the end.

See: http://www.amibroker.com/kb/2014/12/02/how-to-find-correct-symbol-for-interactive-brokers-data/

The reason it’s only an issue for some symbols is related to the symbol’s uniqueness or otherwise in the IB ecosystem, across all markets and exchanges.

Hello HelixTrader.
I had seen that.
I also tried the suffix -SMART-STK-USD, and it still doesn’t work.
For example MSFT–SMART-STK-USD still gives the same error message

It may be to do with using SMART as the exchange. Have you tried using NASDAQ as in the contract description?



You have to specify primary exchange in IBDictionary.txt file of AmiBroker main directory for symbols traded on multiple exchanges. If you have not such file in there re-install most recent final AmiBroker!

If you want to add primary exchange of a symbol into that file it goes likes this (one line per symbol):

InputSymbol,OutputSymbol, comment (optional)

So for Microsoft


If multiple symbols


more info

1 Like

Adding SMART-STK makes no sense because it is added already by default.

The thing is that if you don’t specify exchange then “SMART” is used. If you don’t specify currency “USD” is used, if you don’t specify type “STK” is used by default so your GDX automatically becomes:


Trouble is that Interactive Brokers does not know which exchange to pick if symbol is traded on multiple exchanges using same currency. If you do symbol search on IB site: https://www.interactivebrokers.com/en/index.php?f=463 you will find that GDX is traded in multiple currencies but even in USD the GDX stock is traded on multiple exchanges such as LSE and ARCA. So you can’t use “SMART” because IB does not know what you want. You need to specify the exchange to uniquely identify the symbol traded on given exchange to enter the trade. For example:


You may wonder why SMART works for getting quotes - it is because SMART gives you combination feed from multiple sources as you may not care that much from which source you get quotes from, but when it comes to actually entering the trade SMART can become ambiguous and you need to pick the exchange.

1 Like

Here’s a cool resource somewhat on topic…

fxshrat & Tomasz,

The file IBDictionary.txt is present for my AB installation directory, v6.20.1. The symbol for MSFT is already present in the file. I added an entry for GDX:


It seems that the file is being ignored. When I manually change the code to explicitly use the exchange, it works

childId1 = ibc.PlaceOrder( "GDX-ARCA", "SELL", quantity, "LMT", exitLimitPrice, 0, orderTime, 
              isTransmit, 100, "", 0, ocaGroup );

I’m using v1.3.8 of IBC. Is this the latest version?

You should just follow my advice which is correct, i.e. use GDX-ARCA symbol (you can put in into “Alias” field and use it instead of Name() ).

IBDictionary.txt file is NOT used by IBController, it is used by IB DATA plugin (for RT DATA only).


Ok Tomasz, I understand now. It can’t be used when using EOD data with IB.

What do you mean by “alias”? There is no alias field for ibc.PlaceOrder().

Another solution is to search for error code 200 after calling ibc.PlaceOrder() and retry with


Again many thanks,

and this

Hello Tomasz,

Sorry for the long delay in responding. I added MSFT-NASDAQ" as an alias for MSFT, and I now get an error message
200. No security definition has been found for the request

To make it work, I had to modify the method CWrapper::TickerToContract() to fill in primaryExchange with the exchange value extracted from the alias:

void CWrapper::TickerToContract(LPCTSTR pszTicker, Contract &contract)
	// Added Paul Moore
	CString tmpExchange;

		AfxExtractSubString( oTicker, pszTicker, 0, '-' );
		// Modified Paul Moore
		AfxExtractSubString( tmpExchange, pszTicker, 1, '-');
		//AfxExtractSubString( oExchange, pszTicker, 1, '-');
		AfxExtractSubString( oType, pszTicker, 2, '-');
		AfxExtractSubString( oCurrency, pszTicker, 3, '-');

	// Added Paul Moore
	if( !tmpExchange.IsEmpty() )
		if( tmpExchange[0] == '!' )
			// Remove leading '!', if present
			AfxExtractSubString( oPrimaryExchange, tmpExchange, 1, '!');
			oPrimaryExchange = tmpExchange;

	// Modified Paul Moore
	contract.primaryExchange = oPrimaryExchange; //oExchange == "SMART" ? "" : oExchange;
	//contract.primaryExchange = ""; //oExchange == "SMART" ? "" : oExchange;


This is an old post but I am dealing with these types of errors now and want to share what I have found, in case it can help someone else. Yes, only adding the exchange gives problems. I tried with "ABNB-ARCA" and it didn't work. It is necessary to route to: "ABNB-ARCA-STK". Then, it works.

I don't think it is necessary to change the method CWrapper. Following Tomasz suggestion I used the alias and it works fine. Only, that I use Norgate database and the alias is emptied the following day so I need to store it in permanent static vars. This is the code that works to fix the problem "the contract description is ambiguous":

function get_ticker(symbol)
	if ( StaticVarGetText(symbol + "alias") == "" ) 	//normal case, no alias
		ticker = symbol;
		ticker = StaticVarGetText(symbol + "alias");	//ambiguous case, we use alias i.e. "ABNB-ARCA-STK"		

	return ticker;


//Store the alias in a permanent static var for another day (supports Norgate update):
StaticVarSetText( Name() + "alias", GetFnData("Alias"), True );

//usage (in a trade loop):
OrderID = ibc.PlaceOrder( get_ticker(trade.Symbol) , "BUY", trade.Shares, "MKT", 0, 0, "OPG", True );

1 Like

You can use GetFnDataForeign

This way you can directly retrive alias field for specified symbol, without need to use static variables at all

sym_alias = GetFnDataForeign( "Alias", trade.Symbol );
1 Like

Thank you. That simplifies the code. However, If I am not mistaken I still need to store the alias in permanent static vars anyway, since the following day Norgate has deleted the alias of yesterday. With this code I force to use yesterday's value if not empty and avoid filling the alias every day:

//if no alias from yesterday then store todays' alias. If there is alias do nothing
if( StaticVarGetText( Name() + "alias") == "")
	StaticVarSetText( Name() + "alias", GetFnData("Alias"), True );

Ask Norgate NOT to (over)write "Alias" field. This field should not be used / touched by 3rd party data sources.

1 Like