¿ªÔÆÌåÓý

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

Re: updateMktDepthL2 missing data points

 

On Sat, Oct 28, 2023 at 08:05 PM, John wrote:

or maybe better use a semaphore or lock to do things properly, as copying the list won't prevent another potential conflict when resetting the list to list()

Yes, I'm not sure if a deep copy alone will suffice. But... this is what I meant by "make the smallest possible (but complete) standalone unit test". The test should focus on experimentally confirming your uncertain suspicions; it's a judgement call. Naturally there's no need to confirm what you already know.


Re: updateMktDepthL2 missing data points

 

or maybe better use a semaphore or lock to do things properly, as copying the list won't prevent another potential conflict when resetting the list to list()


Re: updateMktDepthL2 missing data points

 

Thank you both.

So, I'd try to make the smallest possible (but complete)?standalone unit test?in order to really isolate the issue.
@Buddy, these code snippets are pretty self explanatory and stand alone really, put the depth bars in a tuple, append the tuple to a list, put the list in a dataframe and save it to a parquet file. Even using a small toy example below with the same logic, there's clearly no way this code flow can fail on its own even if the input is trash. However you might be correct that it could come from an unfortunate thread concurrency, i.e. a huge amount of data being unequally added to the tuple/list at the exact time the dataframe is created, so I might simply need to hard copy the list before converting that copy to a dataframe instead of the list itself. I'll try that next week and keep the group posted.

from time import time
import pandas as pd

a = list()
a.append((time(), '1', '2', '2'))
a.append((time(), '1', 0, '3'))
a.append((time(), '1', '1'))
a.append(( 0, 0, None))

df = pd.DataFrame(a, columns=['time', 'col1', 'col2', 'col3', ])
print(df)

output
:
? ? ? ? ? ?time col1? col2? col3
0? 1.698522e+09? ? 1? ? ?2? ? ?2
1? 1.698522e+09? ? 1? ? ?0? ? ?3
2? 1.698522e+09? ? 1? ? ?1? None
3? 0.000000e+00? ? 0? None? None

anyway, in this case, i would even wonder what is the real value of market depth data on forex market.
@ fordfrog, well that's precisely what I am trying to find out! :) but for this I first need to extract and save a substantial amount of data in order to study it.


Re: updateMktDepthL2 missing data points

 

BTW, since you mention this:

On Fri, Oct 27, 2023 at 02:54 PM, John wrote:

separately I have a running thread in charge of saving once in a while

I'd like to emphasize that the following is an order of magnitude more important:

On Sat, Oct 28, 2023 at 05:38 PM, buddy wrote:

code interactions can get quite complicated, copying around snippets that are surrounded by ellipsis will only go so far


Re: updateMktDepthL2 missing data points

 

when i implemented support for market depth myself, i recall i also had some issues with processing the incoming data. i kept just the book and updated it with the incoming data, but iirc the issue was that sometimes i had to delete an item with index that did not exist. i wasn't sure whether the issue was in my app or the sequence was really broken back then... anyway, in this case, i would even wonder what is the real value of market depth data on forex market.


Re: updateMktDepthL2 missing data points

 

On Sat, Oct 28, 2023 at 08:20 AM, John wrote:

Essentially if price=0 and size=0 it implies operation=2, and with regards to insert or update, it doesn't make any difference to the analysis I am performing. Considering the amount of data to be stored on multiple FX pairs, I would rather not have a redundant operation column even if only uint8.

The other thing is, if it was related to the operation field, then we would not have any discrepancy between "bid" and "position", but we have bid/size 2151 825 and?position 2151 830 which is rather confusing.

I won't comment as to whether or not your deduction here is correct or not.

But, I will say that it seems you may be relying on too many assumptions. After all, it's been said that "premature optimization is the root of all evil (or at least most of it) in programming".

Therefore, I would suggest you try two things... 1) make your implementation as "correct" as possible according to the API specification & documentation without taking any shortcuts based on assumptions and 2) continue to use ib_insync as a comparison to see if you can reproduce the problem there.

Finally, since code interactions can get quite complicated, copying around snippets that are surrounded by ellipsis will only go so far. So, I'd try to make the smallest possible (but complete) standalone unit test in order to really isolate the issue.

Having that will also make it easy to present an argument to support people. They can then confirm the existence of bug(s) for themselves. Unlike the justice system, I think any application that exhibits "strange behavior" is presumed guilty until proven innocent (instead of the other way around).

Once this is done it should become very clear where the problem lies. And, you'll be able to go back and optimize more systematically.


Placing an order using the Gateway API to the demo account results in 401 Unauthorised

 

Following is what I did:
  1. Start the local Gateway API Java server
  2. Open ?and login with DEMO account.
  3. Check??to see the session is good.
  4. Check ?and I get the following
{
"authenticated": false,
"competing": false,
"connected": true,
"message": "",
"MAC": "XX:XX:XX:XX:XX:XX",
"serverInfo": {
"serverName": null,
"serverVersion": null
},
"fail": ""
}

5. Try to place an order to ?and I get 401 Unauthorized error.

What concerns me is when I look at the iserver's auth status, it says "authenticated": false.
How do I get myself authenticated and authorised to start placing orders to the demo account?
I am currently testing on Saturday over the weekend, and I am not sure if IB having maintenance has anything to do with it. So far, I can get access to the /trsrv endpoints to get contract information. Not sure if the iserver is up right now.

If there is some steps I am missing prior to placing orders to the demo account, please let me know.


Re: How do you test the IB Gateway REST API in demo account?

 

Hi Jurgen,

Yes, you are right. The demo login wasn't working, but I tried it just now, and it worked. I think it was the server maintenance that stopped me from logging in.
Thanks for helping me out.


Re: updateMktDepthL2 missing data points

 

Looking at Ewald's ib_insync implementation below, it does essentially the same thing,
which is put all info in a tuple, and append that tuple to a list, so I am surprised that no one has encountered this issue,
but I am even more surprised that this issue even exists in the first place, as it should work, always, no matter what.


? ? def updateMktDepthL2(
? ? ? ? ? ? self, reqId: int, position: int, marketMaker: str, operation: int,
? ? ? ? ? ? side: int, price: float, size: float, isSmartDepth: bool = False):
? ? ? ? # operation: 0 = insert, 1 = update, 2 = delete
? ? ? ? # side: 0 = ask, 1 = bid
? ? ? ? ticker = self.reqId2Ticker[reqId]
?
? ? ? ? dom = ticker.domBids if side else ticker.domAsks
? ? ? ? if operation == 0:
? ? ? ? ? ? dom.insert(position, DOMLevel(price, size, marketMaker))
? ? ? ? elif operation == 1:
? ? ? ? ? ? dom[position] = DOMLevel(price, size, marketMaker)
? ? ? ? elif operation == 2:
? ? ? ? ? ? if position < len(dom):
? ? ? ? ? ? ? ? level = dom.pop(position)
? ? ? ? ? ? ? ? price = level.price
? ? ? ? ? ? ? ? size = 0
?
? ? ? ? tick = MktDepthData(
? ? ? ? ? ? self.lastTime, position, marketMaker, operation, side, price, size)
? ? ? ? ticker.domTicks.append(tick)
? ? ? ? self.pendingTickers.add(ticker)


class MktDepthData(NamedTuple):
? ? time: datetime
? ? position: int
? ? marketMaker: str
? ? operation: int
? ? side: int
? ? price: float
? ? size: float


domTicks: List[MktDepthData] = field(default_factory=list)




Re: How to download 100 tickers data of 1 minute bar for 1 day

 

You need to take a look at the discussion of pacing violations in the TWS API Guide section on , HHC. While IBKR has relaxed the pacing rules for bars that are wider than 30 secs, a few rules still exist.

I just ran a quick test and grabbed 1min bars for the S&P 500 stocks for today (Friday):
  • I received between 630 and 960 bars for each stock (I ran with rthOnly = false).
  • Requesting and receiving data for 500 instruments took 26 seconds (an average of 52ms per instrument).
  • It might take a little longer in the middle of a heavy trading day but you should be able to get data for 100 instruments in less than 10 seconds.
We use the Java version of TWS API, but you should be able to get similar results in Python. Your application must be entirely event driven to get the full speed, and you might need to use a "three-thread" design that is standard for the Java TWS API (take a look at the bottom of this post for a Python discussion):
  • Thread 1 is the main application thread that manages and makes all requests
  • Thread 2 is the EReader thread that reads bytes from the socket connection with TWS/IBGW, assembles them into messages, and puts the messages into a queue. Each of these messages will eventually become an API callback. This thread is created automatically by TWS API.
  • Many Python examples use only these two threads so that the Thread 1 executes the EClient code, reads the messages, and makes the required callbacks itself. In Java and some of the other languages, EClient code runs in a third thread so that API callbacks are made in parallel to any application code or API requests.

In such a three-thread design, your program would basically do this:
  • After connecting with TWS/IBGW, the main thread works down the list of instruments it needs to request data for, creates a synchronization object (more below) and calls
  • Once it reaches a certain number of outstanding requests (say 25) it waits (not sleep!) until one or more of the outstanding requests are complete. It immediately makes a request for an additional instrument for each completed one.
  • Eventually, requests have been made for all instruments and the main thread waits (again not sleep!) for all still remaining requests to complete.

In Java we use make and return to the main thread one for each outstanding request. Each outstanding request proceeds at its own pace, collects the data it received through a series of callbacks in a list for that instrument. Once the callback arrives for an instruments, the for that instrument is marked "complete" and the list of bars is sent via the to the main thread.

In case the request for an instrument receives an error callback, the is marked completeExceptionally with the cause of the error.

The main thread uses the function to wait for outstanding requests to complete and instantaneously sends additional requests until all data has been received.

In Python you would use a synchronization feature from the asyncio package, such as (that are modeled after the Java Future class) to inform the main thread about completed requests.

Hope this helps,

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


On Fri, Oct 27, 2023 at 10:16 PM, <hhchenfx@...> wrote:

Hi Everyone,

At a given point in a trading day, I want to download 1 minute bar for 1 day for about 100 ticker.
I run a for loop in python to do so but Python stop when about data loaded for about 50 tickers.?
Can you suggest how can I overcome this limit?

I wonder if creating 2 or 3 ClientID to do the download simultaneously solve the problem? But do I get double or triple charge on my account?

Thank you,
HHC


Re: updateMktDepthL2 missing data points

 

Thanks Gordon for your reply.

Yes bid is side, side doesn't mean anything to me, but "bid"==1 clearly means we are talking about bid side.
Quantity is size, because size is used in many other things in python and I would rather avoid any name overlap.

Essentially if price=0 and size=0 it implies operation=2, and with regards to insert or update, it doesn't make any difference to the analysis I am performing.
Considering the amount of data to be stored on multiple FX pairs, I would rather not have a redundant operation column even if only uint8.

The other thing is, if it was related to the operation field, then we would not have any discrepancy between "bid" and "position",
but we have bid/size 2151825 and?position 2151830 which is rather confusing.

Also, how can price and quantity/size have a higher count 2151876 than time 2151751??


Re: How do you test the IB Gateway REST API in demo account?

 

Glad this helped and you are getting closer.

Pointing a browser to and logging in with your paper account credentials should work. At least it does for me Have you tried to log into the Client Portal or TWS/IBW with the paper account credentials?

When did you try this? IBKR is doing some major system maintenance this weekend and we had some outages already during the Friday night maintenance window. I have seen the error message "Invalid username password combination" for legitimate credentials in the past during times when IBKR maintains or resets the main servers.

Whatever works for your live account should work for the paper account/

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



On Sat, Oct 28, 2023 at 01:10 AM, Jimin Park wrote:
Hi Jurgen,

Thanks for the tip. You answered exactly what I wanted to know. I wanted to connect to a paper trading account so I can start placing orders to it and test my algorithmic trading system working.

I logged into my IB live account on their web app, went to Settings > Paper Trading Account and got this screen.

1. I reset my password there for my paper trading account.
2. I went to ?to try to log into the paper trading account for my Gateway server.

However the Gateway tells me "Invalid username password combination".

So how do I create a session to the paper trading account (not the live account) for my Gateway server to start placing orders? I've tested all the REST API endpoints with the live accounts such as fetching contract details and historical marketdata. Everything is working... and now I just want to test placing orders.


Re: How do you test the IB Gateway REST API in demo account?

 

Hi Jurgen,

Thanks for the tip. You answered exactly what I wanted to know. I wanted to connect to a paper trading account so I can start placing orders to it and test my algorithmic trading system working.

I logged into my IB live account on their web app, went to Settings > Paper Trading Account and got this screen.



1. I reset my password there for my paper trading account.
2. I went to ?to try to log into the paper trading account for my Gateway server.

However the Gateway tells me "Invalid username password combination".

So how do I create a session to the paper trading account (not the live account) for my Gateway server to start placing orders? I've tested all the REST API endpoints with the live accounts such as fetching contract details and historical marketdata. Everything is working... and now I just want to test placing orders.


How to download 100 tickers data of 1 minute bar for 1 day

 

Hi Everyone,

At a given point in a trading day, I want to download 1 minute bar for 1 day for about 100 ticker.
I run a for loop in python to do so but Python stop when about data loaded for about 50 tickers.?
Can you suggest how can I overcome this limit?

I wonder if creating 2 or 3 ClientID to do the download simultaneously solve the problem? But do I get double or triple charge on my account?

Thank you,
HHC


Re: updateMktDepthL2 missing data points

 

Can you add 'operation' in your csv ?
I assume your 'bid' = IB 'side', correct ?


It is MANDATORY to use operation? to manage and ensure the integrity of your entries, otherwise you might very well end up receiving request to update a row you didn't inserted. Or insertion or a row you never removed (duplicate), doesn't explain your figures but area to consider
because what is surprising is to see entries with price =0 and volume = 0.


Re: updateMktDepthL2 missing data points

 
Edited

For supporting data, during debugging of another session with the same bug, I managed to extract and save the list into a csv file, using the below code.
Nothing looks wrong in the csv though.

np.savetxt("series_output_1.csv", app.series[reqId], delimiter=",", fmt='%s')


Re: How do you test the IB Gateway REST API in demo account?

 

I have only limited hands-on experience with the Client Portal API (it does not yet add anything that we can't do via TWS API already), but I think you have mixed up a couple things. If you have not done so yet, take a look at the and the explorer.

Any request you send to a URL that starts with "https://localhost:5000/" is handled by the Client Portal API Java gateway that ships with the Client Portal API installation. The gateway handles two kinds of requests:
  • REST requests through one of several API endpoints. All endpoint URLs start with "https://localhost:5000/v1/api/"
  • Requests for WebApps that you develop and install in the folder "root/webapps". URLs for WebApps start with "https://localhost:5000" followed by the WebApp name. The gateway simply serves those files to your browser.

The API ships with one WebApp called "demo". It consists of two files and is, consequently, installed under "root/webapps/demo"
  • root/webapps/demo/index.html
  • root/webapps/demo/gateway.demo.js

The message you get indicates that the gateway is ready to server the WebApp "demo". You start it by pointing your browser to "https://localhost:5000/demo", but the gateway has to be logged into an IBKR account for it to work. In case you have a funded live account at IBKR, you can create a companion "paper" account to try out your strategies.

I do not think that it is possible to connect a WebApp through the Client Portal API gateway to what the TWS application calls a "demo" account. The kind off account you can reach through the TWS application login screen where it says "No username? Try the demo".

Hope that helps,

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




On Fri, Oct 27, 2023 at 11:02 AM, Jimin Park wrote:
When I start the Gateway Java server locally I get this message saying demo app is available at

I tried sending REST API requests to ?and it doesn't work.

I want to test my algorithmic trading system against the demo account placing orders in real time and seeing it work before risking real money.

Could someone point me to an online documentation or anything I can read up on to learn how to do this?


Re: How do you test the IB Gateway REST API in demo account?

 

No intent to be pedantic but when you say "doesn't work" , you can guess that some people are able to make it working, so why don't tell us a little bit more ?
what did you do ? what did you expect ? what happens ?, etc ...

Did you read this one ?
and this one ?
A clue, a typical area of concern for the REST API that need a work/trial? investment: The authentication method.
It require great care for very legit reason, this is the REST API I know which are able to handle potentially the biggest amount of money I ever seen


How do you test the IB Gateway REST API in demo account?

 

When I start the Gateway Java server locally I get this message saying demo app is available at

I tried sending REST API requests to ?and it doesn't work.

I want to test my algorithmic trading system against the demo account placing orders in real time and seeing it work before risking real money.

Could someone point me to an online documentation or anything I can read up on to learn how to do this?


updateMktDepthL2 missing data points

 

Hello,

Trying to source market depth data on FX pairs, USD JPY in the below case.
In the below code,?self.series[reqId]?is just a python list that I append new ticks to.

def updateMktDepthL2(self, reqId, position, marketMaker, operation, side, price, size, isSmartDepth):
self.series[reqId].append((time(), side, position, price, size))

Then separately I have a running thread in charge of saving once in a while to a parquet file and resetting the list.

...
if
len(app.series[reqId]) >= number_of_rows_threshold:
print('saving')
try:
df = pd.DataFrame(app.series[reqId], columns=['time', 'bid', 'position', 'price', 'quantity'])
app.series[reqId] = list()
except ValueError as e:
print('Value Error', e)
...
df.to_parquet(parquet_file_name, compression='gzip')

The above code works fine most of the time, however once in a while, I get an exception:
Length of values (112071) does not match length of index (112105)

Trying to debug the Exception, and putting each column into a separate frame I get the below row count per column:
  • time 2151751
  • bid 2151825
  • position 2151830
  • price 2151876
  • quantity 2151876

How is that even possible?

Note the numbers are different between the exception?112071 and investigation?2151751+,
I believe because data kept arriving between the exception catch and during the debugging I performed.