Keyboard Shortcuts
Likes
Search
Timestamp is missing milliseconds in tickByTickAllLast
I am trying to request real-time tick by tick data, but data arrives with timestamp missing milliseconds. Here is my code:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.ticktype import TickTypeEnum
import time
from datetime import datetime
import threading
?
?
class TestApp(EWrapper, EClient):
? ? def __init__(self):
? ? ? ? EClient.__init__(self, self)
? ? ? ? self.last_price_list = []
?
? ? def error(self, reqId, errorCode, errorString):
? ? ? ? print("Error: ", reqId, " ", errorCode, " ", errorString)
?
? ? def tickByTickAllLast(self, reqId, tickType, time, price, size, tickAtrribLast, exchange, specialConditions):
? ? ? ? print("Tick Price. Ticker Id:", reqId, "tickType:", TickTypeEnum.to_str(tickType),?
? ? ? ? ? ? ? "Price:", price, "\n",
? ? ? ? ? ? ? "market_time_unix:", time, "\n",
? ? ? ? ? ? ? "market_time:", datetime.fromtimestamp(time).strftime("%Y-%m-%d %H:%M:%S.%f'"), "\n",
? ? ? ? ? ? ? "serve_time :", datetime.now())
? ? ? ? print("_______________________")
? ??
?
? ? app = TestApp()
?
app.connect("127.0.0.1", 4002, 0)
? ??
? ? # allow time to connect to server
time.sleep(1)
? ??
contract = Contract()
contract.symbol = "SPY"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
contract.primaryExchange = "ARCA"
?
#app.reqMarketDataType(4)? # switch to delayed-frozen data if live is not available
app.reqTickByTickData(1 ,contract, "Last", 0, True)
#app.reqMktData(1, contract, "", False, False, [])
?
api_thread = threading.Thread(target=app.run)
api_thread.start()
Here is output: Error:? -1? ?2104? ?Market data farm connection is OK:usfarm
Error:? -1? ?2106? ?HMDS data farm connection is OK:ushmds
Error:? -1? ?2158? ?Sec-def data farm connection is OK:secdefil
Tick Price. Ticker Id: 1 tickType: BID Price: 414.37?
?market_time_unix: 1659545243?
?market_time: 2022-08-03 16:47:23.000000'?
?server_time : 2022-08-03 16:47:23.880814
_______________________
Tick Price. Ticker Id: 1 tickType: BID Price: 414.37?
?market_time_unix: 1659545243?
?market_time: 2022-08-03 16:47:23.000000'?
?server_time : 2022-08-03 16:47:23.881391
_______________________
Tick Price. Ticker Id: 1 tickType: BID Price: 414.37?
?market_time_unix: 1659545243?
?market_time: 2022-08-03 16:47:23.000000'?
?server_time : 2022-08-03 16:47:23.881610
Is there way to get milliseconds/microseconds? |
Timestamps within the IBKR API are generally "Epoch Seconds" and there is nothing you can do to get actual? higher resolution time stamps. We work around that by recording high-resolution arrival time stamps (Java Instant, nanosecond resolution) in addition to the "Epoch Second" plus an index that maintains temporal order of all arriving data times. 闯ü谤驳别苍 On Wed, Aug 3, 2022 at 11:54 AM, <alexsviridov@...> wrote:
I am trying to request real-time tick by tick data, but data arrives with timestamp missing milliseconds. Here is my code: |
That's a good question. Let me share what this looks like for our specific setup, but there are so many variables that your results (and those for everyone else) will vary greatly.? But maybe our approach helps you make your own measurements. So we are looking for the order of magnitude of the time it takes for the information about a trade or order book update to travel from the exchange to our application when using IBKR TickByTick data feeds. Here is our setup:
With that long disclaimer, we get for IBKR TickByTick data feeds for CBOE/CME futures:
By coincidence we have a (real) server in a tier 1 data center just north of the CBOE/CME Aurora/IL data center (as in hiking distance). The server is not trading related, but we use is for latency monitoring of IBKR and our own applications. That server has an average round-trip latency to IBKR's cdc1.ibllc.com of only 3.0ms (one way flight time of 1.5ms) and the delay between IBKR and CBOE/CME will probably be in the same order of magnitude or slightly less. We could probably shave about 12ms off the delay numbers mentioned above if we were to move TWS and our client applications to the Chicago server. Similar measurements for other "busy seconds" through the day confirm delay figures for CBOE/CME futures related TickByTick feeds in the same order of magnitude. Hope this helps. 闯ü谤驳别苍 On Wed, Aug 3, 2022 at 12:18 PM, <alexsviridov@...> wrote:
Thank you so much!? |
开云体育闯ü谤驳别苍 ? I was fascinated by your write-up abut ‘correcting’ the tick timestamps, but I can’t help wondering why you think this is worth doing at all. What benefit does it provide? ? I can see that if, for example, you’re building , say, 1-minute bars, then without this correction your bar that ends at 08:01:00 is incorrect because it doesn’t contain the final 36ms of data that the correct bar would contain. But does this matter? And if you do make the correction, the bar is correct but you don’t get it until 08:01:00.036, so any trading decision you make based on it is just as invalid as using the uncorrected timestamps. ? Of course many trading strategies don’t make any use of periodic bars, or volume bars or range-based bars, but that’s really irrelevant. Whatever generates your trading decisions, knowing that you should have made the decision 36ms ago doesn’t do anything to make the decisions better. ? About the only use I can think of is if you want to compare your data with someone else’s that also uses high-res timestamps, but even for that it won’t really help, because they’ll have a different set of sources of error, delays etc. So while the overall data series might be more closely aligned, individual ticks will still have a range of differences. ? Am I missing something? ? Richard |
We are not correcting tick timestamps, Richard. We simply have exact arrival timestamps (Java class Instant) for all kinds of events, including for when TWS API callbacks take place. More background on that below. These high-resolution time stamps are not used for any trade decision making. But we do occasionally use them for response time and latency monitoring such as estimating Tick-by-Tick data streams event delays. In other words, how much times does it take for the information about a trade or order book update at the exchange to arrive in our client in the form of Tick-By-Tick callbacks? When you look at the IBKR one-second resolution time stamp of a Tick-by-Tick object you generally don’t know whether that event took place towards the start of that second (say a few micro seconds into the second) or towards the end (nearly 1,000ms later). But for VIX and ES futures, for example, the first data we receive after market open at 17:00 Central and the start of the liquid trading hours at 08:30 Central almost certainly took place at the exchange very close to 17:00:00.00000000 and 08:30:00.00000000. Therefore, the difference between that timestamp and our high resolution Tick-by-Tick callback arrival timestamp gives us a good feel for the order of magnitude for that delay. For our setup the median delay (over a a few years) is 27ms. And while that is an eternity for a HFT system, for what we are doing it means that we have a very timely real-time view of what is happening at the exchange when we monitor Tick-By-Tick data streams. So, why do we even have these high resolution timestamps. The fancy term would probably be “orthodoxies”, or in plain words “old dogs, their habits, and their tricks”. You may recall that my background is not in finance or trading but rather in computer systems architecture (general purpose, fault tolerant, embedded, distributed), operating kernel internals (Unix, Linux, WindowsNT), and large scale real-time and signal processing systems. So when I stumbled over the TWS API and started exploring what I could use that for, I had a rich set of tools, libraries, and frameworks at my disposal to base our framework on. And these were all oriented around streams, events, messages, reactive systems, and asynchronous processing. The TWS API has shortcomings, but the asynchronous and non-blocking nature fits right into what I had. And then there was this other blast from the past, called Six Sigma, that encourages you to measure and record everything you can afford to. You may not know exactly what to do with the data right away, but there will be questions in the future where that extra data and context suddenly becomes crucial. So for us, everything is an event, events lead to streams (or flows) and streams can be distributed, shared, persisted, split, combined, filtered, aggregated, processed sequentially or in parallel, and manipulated in all kinds of creative ways. Whether that is a Tick-by-Tick data object or an execution report we receive from IBKR or a trading decision, an order placement or anything else. That view of the world is greatly supported by a development practice we had acquired over the years that favors smaller classes where virtually all instantiated objects are immutable (e.g. all fields are “final” and no object state changes after construction). These immutable objects can now freely enter into parallel streams and can be processed without any risk of undesirable side effects. For the most part, making an application consists of orchestrating the kinds of event input streams the application needs, the ones it generates, and the various required processing steps. When an object turns into an event it gets a high-resolution timestamp (the Java Instant) as well as a unique identifier that allows us to remember the temporal order of these events even if they take different paths through the streams, are aggregated, or come back together later. And the best part of this system is an EventLogger that can consume any and all of these streams, serialize events and related objects into Json streams (even if it has no idea what these objects are) and persist them to files. The logger rolls and compresses these files every 15 minutes (configurable) so that we have compact records of everything that took place during those times. We can go back to these records later for analysis or, due to the high resolution time stamps, combine them with other data or events. We can also replay these logs with extreme fidelity in case we make changes or want to try different configurations. For example, our trading strategies are not aware of whether they actually communicate over the TWS API or whether they operate on stream replays. or in simulations. And finally, the EventLogger has eliminated most of the traditional application logging. Application code (or stream processing modules) generate events that are logged along with all other events and objects and, in case of the need for debugging, a rich set of hints and real objects exist to go back to. So when the Tick-by-Tick data delay question came up, we had enough “context” recorded over long periods of times to quickly come up with a good estimate. Hope that helps and makes sense, 闯ü谤驳别苍
|
开云体育闯ü谤驳别苍 ? Sorry, I read more into your use of timestamps than was actually there! ? I also use high-res timestamps in my platform. Windows provides timestamps in units of 100 nanoseconds, and every tick received is recorded with its own timestamp, which stays with it whether the data is recorded to file, or to a database, or simply passed to a client application. ? In my platform, all knowledge of the TWS API is confined to two components: one is my own implementation of the TWSAPI, essentially a replacement for the original ActiveX implementation. The other is a wrapper that maps the TWS API concepts to and from the concepts employed by my platform, which is designed to be broker-independent, using configurable service providers to provide access to data, orders, contracts etc from different sources. The thirty-plus other components know nothing about the TWS API – they work entirely within the platform’s own conceptual framework. Consequently the source of the data is completely hidden from the applications: they can be working against live data from IB or recorded data in a text file or an SQL database. ? This structure enables me, for example, to run a trading client that is playing back multiple streams of recorded data, simultaneously, with all events correctly timed, and to display charts, place simulated orders etc. This is a great tool for learning trading skills, rather like using IB’s paper trading system but with historical data, so it can be done at any time. I got this working in its multi-stream mode back in 2013, and I felt very pleased with myself when it was done, but actually I’ve hardly ever used it since then… (The basic single tick stream replay has been there right from the start in 2005.) ? The tick stream playback can also be run at full speed (rather than using the recorded inter-tick intervals) and this is used for testing trading strategies on large sets of historical data. Once again, a trading strategy isn’t aware of whether it’s running against live real-time data or processing historical data that is being replayed. ? I too have quite a sophisticated logging system, which took inspiration from java.util.logging but can log any type of data (which makes it more of a data distribution mechanism rather than just traditional text logging). The same timestamping is used for log events as for market data (and everything else that needs a timestamp). I don’t go to the same extremes of logging as you do – I don’t bother logging all API calls for example – as I tend to use logging mainly for diagnostic purposes, and I’ll frequently add new log events if I hit a tricky-to-solve bug. And I don’t make a lot of use of the ability to log non-text data, but it’s a nice capability to have on occasion (I tend to use a more targeted and efficient listener mechanism for such purposes). ? I had never heard of Six Sigma before you mentioned it. I certainly agree with the idea of measuring and recording as much data as you can, but when I started on my trading platform back in 2005 (after an initial prototype in 2003) one of the biggest constraints I faced was disk space. It seems almost absurd now, but the biggest disks I could afford then for my Dell PowerEdge 2400 server, with its two Pentium III processors running at 1.3GHz, were 18GB. Given the amount of market data I was collecting in both text files, and SQL Server, and MySQL this meant I had to do a number of things to minimise the likelihood of running out of disk space, and not doing unnecessary logging was one of them. Having said that, I still keep the log files created by my live and simulated trading strategies during those years, and they have occasionally been useful (mostly as a reminder of how rickety the IB API was back then!...). Now I have about a thousand times as much space, though everything is mirrored so it’s more like 500 times as much, but it’s still an issue (time to buy a new server really, but no funds!). ? (By the way, in case you’re wondering, note that I don’t use any of my platform components in the Contract Inspector – that’s a pure TWS API application. I certainly toy with the idea of switching it to use my platform, which would give many benefits, but there are quite a few reasons why I probably won’t.) ? Richard ? ? From: [email protected] <[email protected]> On Behalf Of 闯ü谤驳别苍 Reinold via groups.io
Sent: 05 August 2022 09:21 To: [email protected] Subject: Re: [TWS API] Timestamp is missing milliseconds in tickByTickAllLast ? We are not correcting tick timestamps, Richard. We simply have exact arrival timestamps (Java class Instant) for all kinds of events, including for when TWS API callbacks take place. More background on that below. These high-resolution time stamps are not used for any trade decision making. But we do occasionally use them for response time and latency monitoring such as estimating Tick-by-Tick data streams event delays. In other words, how much times does it take for the information about a trade or order book update at the exchange to arrive in our client in the form of Tick-By-Tick callbacks? When you look at the IBKR one-second resolution time stamp of a Tick-by-Tick object you generally don’t know whether that event took place towards the start of that second (say a few micro seconds into the second) or towards the end (nearly 1,000ms later). But for VIX and ES futures, for example, the first data we receive after market open at 17:00 Central and the start of the liquid trading hours at 08:30 Central almost certainly took place at the exchange very close to 17:00:00.00000000 and 08:30:00.00000000. Therefore, the difference between that timestamp and our high resolution Tick-by-Tick callback arrival timestamp gives us a good feel for the order of magnitude for that delay. For our setup the median delay (over a a few years) is 27ms. And while that is an eternity for a HFT system, for what we are doing it means that we have a very timely real-time view of what is happening at the exchange when we monitor Tick-By-Tick data streams. So, why do we even have these high resolution timestamps. The fancy term would probably be “orthodoxies”, or in plain words “old dogs, their habits, and their tricks”. You may recall that my background is not in finance or trading but rather in computer systems architecture (general purpose, fault tolerant, embedded, distributed), operating kernel internals (Unix, Linux, WindowsNT), and large scale real-time and signal processing systems. So when I stumbled over the TWS API and started exploring what I could use that for, I had a rich set of tools, libraries, and frameworks at my disposal to base our framework on. And these were all oriented around streams, events, messages, reactive systems, and asynchronous processing. The TWS API has shortcomings, but the asynchronous and non-blocking nature fits right into what I had. And then there was this other blast from the past, called Six Sigma, that encourages you to measure and record everything you can afford to. You may not know exactly what to do with the data right away, but there will be questions in the future where that extra data and context suddenly becomes crucial. So for us, everything is an event, events lead to streams (or flows) and streams can be distributed, shared, persisted, split, combined, filtered, aggregated, processed sequentially or in parallel, and manipulated in all kinds of creative ways. Whether that is a Tick-by-Tick data object or an execution report we receive from IBKR or a trading decision, an order placement or anything else. That view of the world is greatly supported by a development practice we had acquired over the years that favors smaller classes where virtually all instantiated objects are immutable (e.g. all fields are “final” and no object state changes after construction). These immutable objects can now freely enter into parallel streams and can be processed without any risk of undesirable side effects. For the most part, making an application consists of orchestrating the kinds of event input streams the application needs, the ones it generates, and the various required processing steps. When an object turns into an event it gets a high-resolution timestamp (the Java Instant) as well as a unique identifier that allows us to remember the temporal order of these events even if they take different paths through the streams, are aggregated, or come back together later. And the best part of this system is an EventLogger that can consume any and all of these streams, serialize events and related objects into Json streams (even if it has no idea what these objects are) and persist them to files. The logger rolls and compresses these files every 15 minutes (configurable) so that we have compact records of everything that took place during those times. We can go back to these records later for analysis or, due to the high resolution time stamps, combine them with other data or events. We can also replay these logs with extreme fidelity in case we make changes or want to try different configurations. For example, our trading strategies are not aware of whether they actually communicate over the TWS API or whether they operate on stream replays. or in simulations. And finally, the EventLogger has eliminated most of the traditional application logging. Application code (or stream processing modules) generate events that are logged along with all other events and objects and, in case of the need for debugging, a rich set of hints and real objects exist to go back to. So when the Tick-by-Tick data delay question came up, we had enough “context” recorded over long periods of times to quickly come up with a good estimate. Hope that helps and makes sense, 闯ü谤驳别苍 |
IB's timestamps are likely generated from IB's server and not the exchange's timestamp.? I've watched IB server time via reqCurrentTime() and usually observe the server time drifting slower over the course of 4-5 minutes until its about 1 sec behind.? Then it resets back to the correct time and the process repeats.?
While not tick-by-tick, reqMktData will return a timestamp with milliseconds but it has the same time drift problem.? Millisecond precision isn't very useful if the accuracy is only 1000 ms. |
I'm comparing the ms timestamp that IB sends in RT_TRD_VOLUME (presumably exchange time) to the time my computer receives that message from the API.? IB's timestamp is always earlier than my computer's time but the difference varies systematically from approx 50ms to 1000ms, which makes me very suspicious of the accuracy of that timestamp.
Here's an example of some typical timing observations from this evening Local=21:53:14.690? RT_TRD_VOLUME=21:53:14.569? Delay=0.121 sec
Local=21:53:37.439? RT_TRD_VOLUME=21:53:37.310? Delay=0.130 sec
Local=21:53:55.157? RT_TRD_VOLUME=21:53:54.935? Delay=0.223 sec
Local=21:54:32.918? RT_TRD_VOLUME=21:54:32.598? Delay=0.321 sec
Local=21:55:12.783? RT_TRD_VOLUME=21:55:12.355? Delay=0.429 sec
Local=21:55:44.538? RT_TRD_VOLUME=21:55:44.003? Delay=0.536 sec
Local=21:56:33.214? RT_TRD_VOLUME=21:56:32.559? Delay=0.655 sec
Local=21:56:33.222? RT_TRD_VOLUME=21:56:32.559? Delay=0.663 sec
Local=21:57:17.301? RT_TRD_VOLUME=21:57:16.536? Delay=0.765 sec
Local=21:57:53.561? RT_TRD_VOLUME=21:57:52.696? Delay=0.865 sec
Local=21:58:52.949? RT_TRD_VOLUME=21:58:51.983? Delay=0.966 sec
Local=21:59:10.079? RT_TRD_VOLUME=21:59:09.106? Delay=0.973 sec?
Local=21:59:44.829? RT_TRD_VOLUME=21:59:44.753? Delay=0.076 sec? <-- resets back to 76ms
Local=21:59:51.043? RT_TRD_VOLUME=21:59:50.963? Delay=0.080 sec
Local=21:59:59.960? RT_TRD_VOLUME=21:59:59.779? Delay=0.181 sec
Local=22:00:04.979? RT_TRD_VOLUME=22:00:04.789? Delay=0.190 sec
Local=22:00:21.766? RT_TRD_VOLUME=22:00:21.517? Delay=0.249 sec |
It does take a bit of time for the server to take a snapshot of the time to the closest millisecond, compose the message, send it down the pipe to your computer. By the time is does all of this, time has passed by.
On Wednesday, August 10, 2022 at 07:37:25 p.m. PDT, Millie Joyner <mdavis00@...> wrote:
I'm comparing the ms timestamp that IB sends in RT_TRD_VOLUME (presumably exchange time) to the time my computer receives that message from the API.? IB's timestamp is always earlier than my computer's time but the difference varies systematically from approx 50ms to 1000ms, which makes me very suspicious of the accuracy of that timestamp. Here's an example of some typical timing observations from this evening Local=21:53:14.690? RT_TRD_VOLUME=21:53:14.569? Delay=0.121 sec
Local=21:53:37.439? RT_TRD_VOLUME=21:53:37.310? Delay=0.130 sec
Local=21:53:55.157? RT_TRD_VOLUME=21:53:54.935? Delay=0.223 sec
Local=21:54:32.918? RT_TRD_VOLUME=21:54:32.598? Delay=0.321 sec
Local=21:55:12.783? RT_TRD_VOLUME=21:55:12.355? Delay=0.429 sec
Local=21:55:44.538? RT_TRD_VOLUME=21:55:44.003? Delay=0.536 sec
Local=21:56:33.214? RT_TRD_VOLUME=21:56:32.559? Delay=0.655 sec
Local=21:56:33.222? RT_TRD_VOLUME=21:56:32.559? Delay=0.663 sec
Local=21:57:17.301? RT_TRD_VOLUME=21:57:16.536? Delay=0.765 sec
Local=21:57:53.561? RT_TRD_VOLUME=21:57:52.696? Delay=0.865 sec
Local=21:58:52.949? RT_TRD_VOLUME=21:58:51.983? Delay=0.966 sec
Local=21:59:10.079? RT_TRD_VOLUME=21:59:09.106? Delay=0.973 sec?
Local=21:59:44.829? RT_TRD_VOLUME=21:59:44.753? Delay=0.076 sec? <-- resets back to 76ms
Local=21:59:51.043? RT_TRD_VOLUME=21:59:50.963? Delay=0.080 sec
Local=21:59:59.960? RT_TRD_VOLUME=21:59:59.779? Delay=0.181 sec
Local=22:00:04.979? RT_TRD_VOLUME=22:00:04.789? Delay=0.190 sec
Local=22:00:21.766? RT_TRD_VOLUME=22:00:21.517? Delay=0.249 sec |