¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

eroor 322 errorMsg "Error processing request.-'bW' : cause - Duplicate ticker id"


 

Hello

I am getting an duplicate ticker id error, however I already have a unique id for each request,

I have uploaded a screenshot of my snippet of code

when I comment out this code it works fine, I have tried commenting out contract.conid and using contract.tradingclass instead of contract.symbol but these did not solve the problem, the full message in debug shows?


? ? ? ? ? ? ? foreach (var strike in strikes)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?foreach (var expire in expirations)
? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?Contract contract = new Contract();

? ? ? ? ? ? ? ? ? ?contract.ConId = underlyingConId;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? contract.TradingClass = tradingClass;
? ? ? ? ? ? ? ? ? ? contract.Exchange = "SMART";
? ? ? ? ? ? ? ? ? ?contract.Currency = "USD";
? ? ? ? ? ? ? ? ? ?contract.SecType = "OPT";
? ? ? ? ? ? ? ? ? ?contract.Right = "CALL";
? ? ? ? ? ? ? ? ? ?contract.Multiplier = "100";

? ? ? ? ? ? ? ? ? ? contract.Strike = strike;
??
? ? ? ? ? ? ? ? ? ? ? ?contract.LastTradeDateOrContractMonth = expire;
? ? ? ? ? ? ? ? ? ? ? ?// Create a new TagValue List object (for API version 9.71)
? ? ? ? ? ? ? ? ? ? ? ?List<TagValue> mktDataOptions = new List<TagValue>();
? ? ? ? ? ? ? ? ? ?clientSocket.reqMarketDataType(3);
? ? ? ? ? ? ? ?clientSocket.reqMktData(reqId + counter, contract, "", false, false, mktDataOptions);?

? ? ? ? ? ? ? ? ? ? ? ?counter = counter + 1;
? ? ? ? ? ? ? ? ? ?}


 

Hi Liu,

The "counter" variable is initialized at a higher scope (not within the for-each loop).
This means that multiple parallel for-each executions are working against the same instance of that variable.
Depending on race conditions, this might lead to incorrect functioning of your logic.

Cheers,
Dmitry

On Thu, Jan 26, 2023 at 6:26 AM H Liu <liuhervey@...> wrote:
Hello

I am getting an duplicate ticker id error, however I already have a unique id for each request,

I have uploaded a screenshot of my snippet of code

when I comment out this code it works fine, I have tried commenting out contract.conid and using contract.tradingclass instead of contract.symbol but these did not solve the problem, the full message in debug shows?


? ? ? ? ? ? ? foreach (var strike in strikes)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?foreach (var expire in expirations)
? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?Contract contract = new Contract();

? ? ? ? ? ? ? ? ? ?contract.ConId = underlyingConId;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? contract.TradingClass = tradingClass;
? ? ? ? ? ? ? ? ? ? contract.Exchange = "SMART";
? ? ? ? ? ? ? ? ? ?contract.Currency = "USD";
? ? ? ? ? ? ? ? ? ?contract.SecType = "OPT";
? ? ? ? ? ? ? ? ? ?contract.Right = "CALL";
? ? ? ? ? ? ? ? ? ?contract.Multiplier = "100";

? ? ? ? ? ? ? ? ? ? contract.Strike = strike;
??
? ? ? ? ? ? ? ? ? ? ? ?contract.LastTradeDateOrContractMonth = expire;
? ? ? ? ? ? ? ? ? ? ? ?// Create a new TagValue List object (for API version 9.71)
? ? ? ? ? ? ? ? ? ? ? ?List<TagValue> mktDataOptions = new List<TagValue>();
? ? ? ? ? ? ? ? ? ?clientSocket.reqMarketDataType(3);
? ? ? ? ? ? ? ?clientSocket.reqMktData(reqId + counter, contract, "", false, false, mktDataOptions);?

? ? ? ? ? ? ? ? ? ? ? ?counter = counter + 1;
? ? ? ? ? ? ? ? ? ?}


 

On Thu, Jan 26, 2023 at 09:39 AM, Dmitry Shevkoplyas wrote:
multiple parallel for-each
sorry but i am not sure what you mean,?

I have??int counter = 1; outside the foreach loop

and I put a breakpoint at the end of foreach loop and ran it

I see in the debug each request of reqmktdata has a unique request id, unique strike and expire.

how? therefore is it possible that there is multiple foreach executions using the same variable?


 

Well, somewhere in your program an API request is made with a duplicate requestId or tickerId. The error callback should give you the exact id at fault.

"reqId + counter" is a bad idea. You should have a function, such as nextRequestId(), that provides a new and unique Id every time the function is called. It is sufficient that the function simply returns the value of an incremented variable such as (pseudo language):

private integer _nextRestId = 10000000;
funtion integer nextRequestId()
{
??? return _nextRequestId++;
}


We found it helpful to start request Ids at a high number so that they cannot be confused with orderIds.? But "_nextRestId? = 1" will work just fine.

Now, every API request (not just reqMktData) gets a unique Id by a call to nextRequestId().

´³¨¹°ù²µ±ð²Ô


 

Hi Liu,

The "foreach" execute nested code block concurrently.
Your code has "counter" incremented in one line and then used in another line.
The "counter" variable is shared across all you (many) code blocks expected in parallel, which means that between incrementing and later using your 'counter" another similar block (working in parallel) might sometimes be lucky to increment the same shared "counter" one more time, thus both blocks of code will send the request with the same Id.

When you're trying to debug this with breakpoints?and step-by-stem?execution it is millions time slower and it is completely different run-mode, thus you have close to zero chances?to witness that particular behaviour.

Unfortunately ´³¨¹°ù²µ±ð²Ô's suggestion to move counter increment into the separate f-n won't change anything - you'll still get duplicates from time to?time.

Cheers,
Dmitry

On Fri, Jan 27, 2023 at 8:40 PM ´³¨¹°ù²µ±ð²Ô Reinold via <TwsApiOnGroupsIo=[email protected]> wrote:

Well, somewhere in your program an API request is made with a duplicate requestId or tickerId. The error callback should give you the exact id at fault.

"reqId + counter" is a bad idea. You should have a function, such as nextRequestId(), that provides a new and unique Id every time the function is called. It is sufficient that the function simply returns the value of an incremented variable such as (pseudo language):

private integer _nextRestId = 10000000;
funtion integer nextRequestId()
{
??? return _nextRequestId++;
}


We found it helpful to start request Ids at a high number so that they cannot be confused with orderIds.? But "_nextRestId? = 1" will work just fine.

Now, every API request (not just reqMktData) gets a unique Id by a call to nextRequestId().

´³¨¹°ù²µ±ð²Ô


 
Edited

I don't understand your comment, Dmitry, why centralizing the ID generation still can get duplicate IDs.

I presented a pseudo language example but every language has concepts that make nextRequestId() a strictly monotonically increasing function. In other words, each call returns a number this is higher than all other numbers returned before and no number will ever be returned again. And that is guaranteed regardless of how many threads and loops execute in parallel.

In Java, for example, you can simply declare the function as public synchronized or use an AtomicInteger instead of simply int. For many years we run applications with many parallel threads on systems with several processors and have never seen error 322.

Now, the real solution here is an application architecture that completely removes request Ids (and other API details) from the business logic. Such as wrapping a thin controller layer around TWS API calls so that these implementation details are completely hidden from client code. A good example is the ApiController class that is part of the TWS API Java version. So, instead of calling the TWS API method

reqMktData( int tickerId, Contract contract, String genericTickList, boolean snapshot, boolean regulatorySnapshot, List<TagValue> mktDataOptions )

and having to manage request ids and having to implement routing code for returned data by requestId to your appropriate logic you simply call

reqTopMktData( Contract contract, String genericTickList, boolean snapshot, boolean regulatorySnapshot, ITopMktDataHandler handler )

and the controller automatically routes the data stream directly to your handler function.

Or look at Ewald de Wit's very well architected ib_insync Python library, and you receive the subscribed data streams via asynchronous events whenever they arrive.

´³¨¹°ù²µ±ð²Ô


On Sun, Jan 29, 2023 at 10:49 AM, Dmitry Shevkoplyas wrote:

Hi Liu,
?
The "foreach" execute nested code block concurrently.
Your code has "counter" incremented in one line and then used in another line.
The "counter" variable is shared across all you (many) code blocks expected in parallel, which means that between incrementing and later using your 'counter" another similar block (working in parallel) might sometimes be lucky to increment the same shared "counter" one more time, thus both blocks of code will send the request with the same Id.
?
When you're trying to debug this with breakpoints?and step-by-stem?execution it is millions time slower and it is completely different run-mode, thus you have close to zero chances?to witness that particular behaviour.
?
Unfortunately ´³¨¹°ù²µ±ð²Ô's suggestion to move counter increment into the separate f-n won't change anything - you'll still get duplicates from time to?time.
?
Cheers,
Dmitry

On Fri, Jan 27, 2023 at 8:40 PM ´³¨¹°ù²µ±ð²Ô Reinold via <TwsApiOnGroupsIo=[email protected]> wrote:

Well, somewhere in your program an API request is made with a duplicate requestId or tickerId. The error callback should give you the exact id at fault.

"reqId + counter" is a bad idea. You should have a function, such as nextRequestId(), that provides a new and unique Id every time the function is called. It is sufficient that the function simply returns the value of an incremented variable such as (pseudo language):

private integer _nextRestId = 10000000;
funtion integer nextRequestId()
{
??? return _nextRequestId++;
}


We found it helpful to start request Ids at a high number so that they cannot be confused with orderIds.? But "_nextRestId? = 1" will work just fine.

Now, every API request (not just reqMktData) gets a unique Id by a call to nextRequestId().

´³¨¹°ù²µ±ð²Ô

?

?


 

?I understand now. Yes I moved it outside to the main class and set counter as private so now it works fine


On Sun, Jan 29, 2023, 11:49 AM Dmitry Shevkoplyas <shevkoplyas@...> wrote:
Hi Liu,

The "foreach" execute nested code block concurrently.
Your code has "counter" incremented in one line and then used in another line.
The "counter" variable is shared across all you (many) code blocks expected in parallel, which means that between incrementing and later using your 'counter" another similar block (working in parallel) might sometimes be lucky to increment the same shared "counter" one more time, thus both blocks of code will send the request with the same Id.

When you're trying to debug this with breakpoints?and step-by-stem?execution it is millions time slower and it is completely different run-mode, thus you have close to zero chances?to witness that particular behaviour.

Unfortunately ´³¨¹°ù²µ±ð²Ô's suggestion to move counter increment into the separate f-n won't change anything - you'll still get duplicates from time to?time.

Cheers,
Dmitry

On Fri, Jan 27, 2023 at 8:40 PM ´³¨¹°ù²µ±ð²Ô Reinold via <TwsApiOnGroupsIo=[email protected]> wrote:

Well, somewhere in your program an API request is made with a duplicate requestId or tickerId. The error callback should give you the exact id at fault.

"reqId + counter" is a bad idea. You should have a function, such as nextRequestId(), that provides a new and unique Id every time the function is called. It is sufficient that the function simply returns the value of an incremented variable such as (pseudo language):

private integer _nextRestId = 10000000;
funtion integer nextRequestId()
{
??? return _nextRequestId++;
}


We found it helpful to start request Ids at a high number so that they cannot be confused with orderIds.? But "_nextRestId? = 1" will work just fine.

Now, every API request (not just reqMktData) gets a unique Id by a call to nextRequestId().

´³¨¹°ù²µ±ð²Ô