databento 0.76.0__tar.gz → 0.78.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {databento-0.76.0 → databento-0.78.0}/PKG-INFO +3 -3
- {databento-0.76.0 → databento-0.78.0}/README.md +1 -1
- {databento-0.76.0 → databento-0.78.0}/databento/common/bentologging.py +3 -2
- {databento-0.76.0 → databento-0.78.0}/databento/common/dbnstore.py +20 -14
- {databento-0.76.0 → databento-0.78.0}/databento/common/enums.py +7 -2
- {databento-0.76.0 → databento-0.78.0}/databento/common/parsing.py +9 -6
- {databento-0.76.0 → databento-0.78.0}/databento/common/publishers.py +31 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/symbology.py +3 -2
- {databento-0.76.0 → databento-0.78.0}/databento/common/types.py +6 -4
- {databento-0.76.0 → databento-0.78.0}/databento/common/validation.py +3 -2
- {databento-0.76.0 → databento-0.78.0}/databento/historical/api/batch.py +3 -2
- {databento-0.76.0 → databento-0.78.0}/databento/live/client.py +21 -14
- {databento-0.76.0 → databento-0.78.0}/databento/live/gateway.py +6 -4
- {databento-0.76.0 → databento-0.78.0}/databento/live/protocol.py +11 -9
- {databento-0.76.0 → databento-0.78.0}/databento/live/session.py +57 -9
- databento-0.78.0/databento/version.py +1 -0
- {databento-0.76.0 → databento-0.78.0}/pyproject.toml +2 -2
- databento-0.76.0/databento/version.py +0 -1
- {databento-0.76.0 → databento-0.78.0}/LICENSE +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/constants.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/cram.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/error.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/http.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/iterator.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/common/system.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/api/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/api/metadata.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/api/symbology.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/api/timeseries.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/historical/client.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/live/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/py.typed +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/api/__init__.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/api/adjustment.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/api/corporate.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/api/security.py +0 -0
- {databento-0.76.0 → databento-0.78.0}/databento/reference/client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: databento
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.78.0
|
|
4
4
|
Summary: Official Python client library for Databento
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -21,7 +21,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Requires-Dist: aiohttp (>=3.8.3,<4.0.0) ; python_version < "3.12"
|
|
23
23
|
Requires-Dist: aiohttp (>=3.9.0,<4.0.0) ; python_version >= "3.12"
|
|
24
|
-
Requires-Dist: databento-dbn (>=0.
|
|
24
|
+
Requires-Dist: databento-dbn (>=0.58.0,<0.59.0)
|
|
25
25
|
Requires-Dist: numpy (>=1.23.5) ; python_version < "3.12"
|
|
26
26
|
Requires-Dist: numpy (>=1.26.0) ; python_version >= "3.12"
|
|
27
27
|
Requires-Dist: pandas (>=1.5.3,<4.0.0)
|
|
@@ -69,7 +69,7 @@ The library is fully compatible with distributions of Anaconda 2023.x and above.
|
|
|
69
69
|
The minimum dependencies as found in the `pyproject.toml` are also listed below:
|
|
70
70
|
- python = "^3.10"
|
|
71
71
|
- aiohttp = "^3.8.3"
|
|
72
|
-
- databento-dbn = "~0.
|
|
72
|
+
- databento-dbn = "~0.58.0"
|
|
73
73
|
- numpy = ">=1.23.5"
|
|
74
74
|
- pandas = ">=1.5.3"
|
|
75
75
|
- pip-system-certs = ">=4.0" (Windows only)
|
|
@@ -32,7 +32,7 @@ The library is fully compatible with distributions of Anaconda 2023.x and above.
|
|
|
32
32
|
The minimum dependencies as found in the `pyproject.toml` are also listed below:
|
|
33
33
|
- python = "^3.10"
|
|
34
34
|
- aiohttp = "^3.8.3"
|
|
35
|
-
- databento-dbn = "~0.
|
|
35
|
+
- databento-dbn = "~0.58.0"
|
|
36
36
|
- numpy = ">=1.23.5"
|
|
37
37
|
- pandas = ">=1.5.3"
|
|
38
38
|
- pip-system-certs = ">=4.0" (Windows only)
|
|
@@ -5,8 +5,9 @@ import logging
|
|
|
5
5
|
|
|
6
6
|
def enable_logging(level: int | str = logging.INFO) -> None:
|
|
7
7
|
"""
|
|
8
|
-
Enable logging for the Databento module.
|
|
9
|
-
|
|
8
|
+
Enable logging for the Databento module.
|
|
9
|
+
|
|
10
|
+
This function should be used for simple applications and examples. It is advisable to configure your own
|
|
10
11
|
logging for serious applications.
|
|
11
12
|
|
|
12
13
|
Parameters
|
|
@@ -244,8 +244,9 @@ class MemoryDataSource(DataSource):
|
|
|
244
244
|
@property
|
|
245
245
|
def name(self) -> str:
|
|
246
246
|
"""
|
|
247
|
-
Return the name of the source buffer.
|
|
248
|
-
|
|
247
|
+
Return the name of the source buffer.
|
|
248
|
+
|
|
249
|
+
Equivalent to `repr` of the input.
|
|
249
250
|
|
|
250
251
|
Returns
|
|
251
252
|
-------
|
|
@@ -269,8 +270,9 @@ class MemoryDataSource(DataSource):
|
|
|
269
270
|
@property
|
|
270
271
|
def reader(self) -> BytesIO:
|
|
271
272
|
"""
|
|
272
|
-
Return a reader for this buffer.
|
|
273
|
-
|
|
273
|
+
Return a reader for this buffer.
|
|
274
|
+
|
|
275
|
+
The reader beings at the start of the buffer.
|
|
274
276
|
|
|
275
277
|
Returns
|
|
276
278
|
-------
|
|
@@ -391,8 +393,7 @@ class DBNStore:
|
|
|
391
393
|
while True:
|
|
392
394
|
raw = reader.read(DBNStore.DBN_READ_SIZE)
|
|
393
395
|
if raw:
|
|
394
|
-
decoder.
|
|
395
|
-
records = decoder.decode()
|
|
396
|
+
records = decoder.write_and_decode(raw)
|
|
396
397
|
for record in records:
|
|
397
398
|
if isinstance(record, databento_dbn.Metadata):
|
|
398
399
|
continue
|
|
@@ -416,8 +417,9 @@ class DBNStore:
|
|
|
416
417
|
@property
|
|
417
418
|
def compression(self) -> Compression:
|
|
418
419
|
"""
|
|
419
|
-
Return the data compression format (if any).
|
|
420
|
-
|
|
420
|
+
Return the data compression format (if any).
|
|
421
|
+
|
|
422
|
+
This is determined by inspecting the data.
|
|
421
423
|
|
|
422
424
|
Returns
|
|
423
425
|
-------
|
|
@@ -441,8 +443,9 @@ class DBNStore:
|
|
|
441
443
|
@property
|
|
442
444
|
def end(self) -> pd.Timestamp | None:
|
|
443
445
|
"""
|
|
444
|
-
Return the query end for the data.
|
|
445
|
-
|
|
446
|
+
Return the query end for the data.
|
|
447
|
+
|
|
448
|
+
If None, the end time was not known when the data was generated.
|
|
446
449
|
|
|
447
450
|
Returns
|
|
448
451
|
-------
|
|
@@ -546,11 +549,13 @@ class DBNStore:
|
|
|
546
549
|
@property
|
|
547
550
|
def schema(self) -> Schema | None:
|
|
548
551
|
"""
|
|
549
|
-
Return the DBN record schema.
|
|
552
|
+
Return the DBN record schema.
|
|
553
|
+
|
|
554
|
+
If None, may contain one or more schemas.
|
|
550
555
|
|
|
551
556
|
Returns
|
|
552
557
|
-------
|
|
553
|
-
|
|
558
|
+
Schema or None
|
|
554
559
|
|
|
555
560
|
"""
|
|
556
561
|
schema = self._metadata.schema
|
|
@@ -577,8 +582,9 @@ class DBNStore:
|
|
|
577
582
|
@property
|
|
578
583
|
def stype_in(self) -> SType | None:
|
|
579
584
|
"""
|
|
580
|
-
Return the query input symbology type for the data.
|
|
581
|
-
|
|
585
|
+
Return the query input symbology type for the data.
|
|
586
|
+
|
|
587
|
+
If None, the records may contain mixed STypes.
|
|
582
588
|
|
|
583
589
|
Returns
|
|
584
590
|
-------
|
|
@@ -85,8 +85,10 @@ def coercible(enum_type: type[M]) -> type[M]:
|
|
|
85
85
|
|
|
86
86
|
class StringyMixin:
|
|
87
87
|
"""
|
|
88
|
-
Mixin class for overloading __str__ on Enum types.
|
|
89
|
-
|
|
88
|
+
Mixin class for overloading __str__ on Enum types.
|
|
89
|
+
|
|
90
|
+
This will use the Enumerations subclass, if any, to modify the
|
|
91
|
+
behavior of str().
|
|
90
92
|
|
|
91
93
|
For subclasses of enum.Flag a comma separated string of names is
|
|
92
94
|
returned. For integer enumerations, the lowercase member name is
|
|
@@ -134,6 +136,7 @@ class SplitDuration(StringyMixin, str, Enum):
|
|
|
134
136
|
DAY = "day"
|
|
135
137
|
WEEK = "week"
|
|
136
138
|
MONTH = "month"
|
|
139
|
+
YEAR = "year"
|
|
137
140
|
NONE = "none"
|
|
138
141
|
|
|
139
142
|
|
|
@@ -195,6 +198,8 @@ class RecordFlags(StringyMixin, IntFlag): # type: ignore
|
|
|
195
198
|
"""
|
|
196
199
|
Represents record flags.
|
|
197
200
|
|
|
201
|
+
Attributes
|
|
202
|
+
----------
|
|
198
203
|
F_LAST
|
|
199
204
|
Marks the last record in a single event for a given `instrument_id`.
|
|
200
205
|
F_TOB
|
|
@@ -168,8 +168,9 @@ def symbols_list_to_list(
|
|
|
168
168
|
@symbols_list_to_list.register(cls=Integral)
|
|
169
169
|
def _(symbols: Integral, stype_in: SType) -> list[str]:
|
|
170
170
|
"""
|
|
171
|
-
Dispatch method for optional_symbols_list_to_list.
|
|
172
|
-
|
|
171
|
+
Dispatch method for optional_symbols_list_to_list.
|
|
172
|
+
|
|
173
|
+
Handles integral types, alerting when an integer is given for STypes that expect strings.
|
|
173
174
|
|
|
174
175
|
See Also
|
|
175
176
|
--------
|
|
@@ -187,8 +188,9 @@ def _(symbols: Integral, stype_in: SType) -> list[str]:
|
|
|
187
188
|
@symbols_list_to_list.register(cls=str)
|
|
188
189
|
def _(symbols: str, stype_in: SType) -> list[str]:
|
|
189
190
|
"""
|
|
190
|
-
Dispatch method for optional_symbols_list_to_list.
|
|
191
|
-
|
|
191
|
+
Dispatch method for optional_symbols_list_to_list.
|
|
192
|
+
|
|
193
|
+
Handles str, splitting on commas and validating smart symbology.
|
|
192
194
|
|
|
193
195
|
See Also
|
|
194
196
|
--------
|
|
@@ -212,8 +214,9 @@ def _(symbols: str, stype_in: SType) -> list[str]:
|
|
|
212
214
|
@symbols_list_to_list.register(cls=Iterable)
|
|
213
215
|
def _(symbols: Iterable[Any], stype_in: SType) -> list[str]:
|
|
214
216
|
"""
|
|
215
|
-
Dispatch method for optional_symbols_list_to_list.
|
|
216
|
-
|
|
217
|
+
Dispatch method for optional_symbols_list_to_list.
|
|
218
|
+
|
|
219
|
+
Handles Iterables by dispatching the individual members.
|
|
217
220
|
|
|
218
221
|
See Also
|
|
219
222
|
--------
|
|
@@ -126,6 +126,8 @@ class Venue(StringyMixin, str, Enum):
|
|
|
126
126
|
MX2 Options.
|
|
127
127
|
IEXO
|
|
128
128
|
IEX Options LLC.
|
|
129
|
+
CGIF
|
|
130
|
+
Cboe Global Indices Feed.
|
|
129
131
|
|
|
130
132
|
"""
|
|
131
133
|
|
|
@@ -184,6 +186,7 @@ class Venue(StringyMixin, str, Enum):
|
|
|
184
186
|
OCEA = "OCEA"
|
|
185
187
|
MXTO = "MXTO"
|
|
186
188
|
IEXO = "IEXO"
|
|
189
|
+
CGIF = "CGIF"
|
|
187
190
|
|
|
188
191
|
@classmethod
|
|
189
192
|
def from_int(cls, value: int) -> Venue:
|
|
@@ -300,6 +303,8 @@ class Venue(StringyMixin, str, Enum):
|
|
|
300
303
|
return Venue.MXTO
|
|
301
304
|
if value == 55:
|
|
302
305
|
return Venue.IEXO
|
|
306
|
+
if value == 56:
|
|
307
|
+
return Venue.CGIF
|
|
303
308
|
raise ValueError(f"Integer value {value} does not correspond with any Venue variant")
|
|
304
309
|
|
|
305
310
|
def to_int(self) -> int:
|
|
@@ -416,6 +421,8 @@ class Venue(StringyMixin, str, Enum):
|
|
|
416
421
|
return 54
|
|
417
422
|
if self == Venue.IEXO:
|
|
418
423
|
return 55
|
|
424
|
+
if self == Venue.CGIF:
|
|
425
|
+
return 56
|
|
419
426
|
raise ValueError("Invalid Venue")
|
|
420
427
|
|
|
421
428
|
@property
|
|
@@ -533,6 +540,8 @@ class Venue(StringyMixin, str, Enum):
|
|
|
533
540
|
return "MX2 Options"
|
|
534
541
|
if self == Venue.IEXO:
|
|
535
542
|
return "IEX Options LLC"
|
|
543
|
+
if self == Venue.CGIF:
|
|
544
|
+
return "Cboe Global Indices Feed"
|
|
536
545
|
raise ValueError("Unexpected Venue value")
|
|
537
546
|
|
|
538
547
|
|
|
@@ -624,6 +633,8 @@ class Dataset(StringyMixin, str, Enum):
|
|
|
624
633
|
CFE Depth.
|
|
625
634
|
OCEA_MEMOIR
|
|
626
635
|
Blue Ocean ATS MEMOIR Depth.
|
|
636
|
+
CGIF_TITANIUM
|
|
637
|
+
Cboe Titanium Cboe Global Indices Feed.
|
|
627
638
|
|
|
628
639
|
"""
|
|
629
640
|
|
|
@@ -668,6 +679,7 @@ class Dataset(StringyMixin, str, Enum):
|
|
|
668
679
|
XEEE_EOBI = "XEEE.EOBI"
|
|
669
680
|
XCBF_PITCH = "XCBF.PITCH"
|
|
670
681
|
OCEA_MEMOIR = "OCEA.MEMOIR"
|
|
682
|
+
CGIF_TITANIUM = "CGIF.TITANIUM"
|
|
671
683
|
|
|
672
684
|
@classmethod
|
|
673
685
|
def from_int(cls, value: int) -> Dataset:
|
|
@@ -756,6 +768,8 @@ class Dataset(StringyMixin, str, Enum):
|
|
|
756
768
|
return Dataset.XCBF_PITCH
|
|
757
769
|
if value == 41:
|
|
758
770
|
return Dataset.OCEA_MEMOIR
|
|
771
|
+
if value == 42:
|
|
772
|
+
return Dataset.CGIF_TITANIUM
|
|
759
773
|
raise ValueError(f"Integer value {value} does not correspond with any Dataset variant")
|
|
760
774
|
|
|
761
775
|
def to_int(self) -> int:
|
|
@@ -844,6 +858,8 @@ class Dataset(StringyMixin, str, Enum):
|
|
|
844
858
|
return 40
|
|
845
859
|
if self == Dataset.OCEA_MEMOIR:
|
|
846
860
|
return 41
|
|
861
|
+
if self == Dataset.CGIF_TITANIUM:
|
|
862
|
+
return 42
|
|
847
863
|
raise ValueError("Invalid Dataset")
|
|
848
864
|
|
|
849
865
|
@property
|
|
@@ -933,6 +949,8 @@ class Dataset(StringyMixin, str, Enum):
|
|
|
933
949
|
return "CFE Depth"
|
|
934
950
|
if self == Dataset.OCEA_MEMOIR:
|
|
935
951
|
return "Blue Ocean ATS MEMOIR Depth"
|
|
952
|
+
if self == Dataset.CGIF_TITANIUM:
|
|
953
|
+
return "Cboe Titanium Cboe Global Indices Feed"
|
|
936
954
|
raise ValueError("Unexpected Dataset value")
|
|
937
955
|
|
|
938
956
|
|
|
@@ -1160,6 +1178,8 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
1160
1178
|
OPRA - MEMX MX2 Options.
|
|
1161
1179
|
OPRA_PILLAR_IEXO
|
|
1162
1180
|
OPRA - IEX Options LLC.
|
|
1181
|
+
CGIF_TITANIUM_CGIF
|
|
1182
|
+
Cboe Global Indices Feed.
|
|
1163
1183
|
|
|
1164
1184
|
"""
|
|
1165
1185
|
|
|
@@ -1272,6 +1292,7 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
1272
1292
|
OCEA_MEMOIR_OCEA = "OCEA.MEMOIR.OCEA"
|
|
1273
1293
|
OPRA_PILLAR_MXTO = "OPRA.PILLAR.MXTO"
|
|
1274
1294
|
OPRA_PILLAR_IEXO = "OPRA.PILLAR.IEXO"
|
|
1295
|
+
CGIF_TITANIUM_CGIF = "CGIF.TITANIUM.CGIF"
|
|
1275
1296
|
|
|
1276
1297
|
@classmethod
|
|
1277
1298
|
def from_int(cls, value: int) -> Publisher:
|
|
@@ -1496,6 +1517,8 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
1496
1517
|
return Publisher.OPRA_PILLAR_MXTO
|
|
1497
1518
|
if value == 109:
|
|
1498
1519
|
return Publisher.OPRA_PILLAR_IEXO
|
|
1520
|
+
if value == 110:
|
|
1521
|
+
return Publisher.CGIF_TITANIUM_CGIF
|
|
1499
1522
|
raise ValueError(f"Integer value {value} does not correspond with any Publisher variant")
|
|
1500
1523
|
|
|
1501
1524
|
def to_int(self) -> int:
|
|
@@ -1720,6 +1743,8 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
1720
1743
|
return 108
|
|
1721
1744
|
if self == Publisher.OPRA_PILLAR_IEXO:
|
|
1722
1745
|
return 109
|
|
1746
|
+
if self == Publisher.CGIF_TITANIUM_CGIF:
|
|
1747
|
+
return 110
|
|
1723
1748
|
raise ValueError("Invalid Publisher")
|
|
1724
1749
|
|
|
1725
1750
|
@property
|
|
@@ -1945,6 +1970,8 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
1945
1970
|
return Venue.MXTO
|
|
1946
1971
|
if self == Publisher.OPRA_PILLAR_IEXO:
|
|
1947
1972
|
return Venue.IEXO
|
|
1973
|
+
if self == Publisher.CGIF_TITANIUM_CGIF:
|
|
1974
|
+
return Venue.CGIF
|
|
1948
1975
|
raise ValueError("Unexpected Publisher value")
|
|
1949
1976
|
|
|
1950
1977
|
@property
|
|
@@ -2170,6 +2197,8 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
2170
2197
|
return Dataset.OPRA_PILLAR
|
|
2171
2198
|
if self == Publisher.OPRA_PILLAR_IEXO:
|
|
2172
2199
|
return Dataset.OPRA_PILLAR
|
|
2200
|
+
if self == Publisher.CGIF_TITANIUM_CGIF:
|
|
2201
|
+
return Dataset.CGIF_TITANIUM
|
|
2173
2202
|
raise ValueError("Unexpected Publisher value")
|
|
2174
2203
|
|
|
2175
2204
|
@property
|
|
@@ -2395,4 +2424,6 @@ class Publisher(StringyMixin, str, Enum):
|
|
|
2395
2424
|
return "OPRA - MEMX MX2 Options"
|
|
2396
2425
|
if self == Publisher.OPRA_PILLAR_IEXO:
|
|
2397
2426
|
return "OPRA - IEX Options LLC"
|
|
2427
|
+
if self == Publisher.CGIF_TITANIUM_CGIF:
|
|
2428
|
+
return "Cboe Global Indices Feed"
|
|
2398
2429
|
raise ValueError("Unexpected Publisher value")
|
|
@@ -645,8 +645,9 @@ class InstrumentMap:
|
|
|
645
645
|
|
|
646
646
|
def build_symbol_map(self) -> dict[int, list[tuple[dt.date, dt.date, str]]]:
|
|
647
647
|
"""
|
|
648
|
-
Build a simple symbol map.
|
|
649
|
-
|
|
648
|
+
Build a simple symbol map.
|
|
649
|
+
|
|
650
|
+
This is to interface with methods of databento-dbn.
|
|
650
651
|
|
|
651
652
|
Returns
|
|
652
653
|
-------
|
|
@@ -22,8 +22,9 @@ _T = TypeVar("_T")
|
|
|
22
22
|
|
|
23
23
|
class Default(Generic[_T]):
|
|
24
24
|
"""
|
|
25
|
-
A container for a default value.
|
|
26
|
-
|
|
25
|
+
A container for a default value.
|
|
26
|
+
|
|
27
|
+
This is to be used when a callable wants to detect if a default parameter value is being used.
|
|
27
28
|
|
|
28
29
|
Example
|
|
29
30
|
-------
|
|
@@ -152,8 +153,9 @@ class ClientStream:
|
|
|
152
153
|
|
|
153
154
|
def write(self, data: bytes) -> None:
|
|
154
155
|
"""
|
|
155
|
-
Write data to the underlying stream.
|
|
156
|
-
|
|
156
|
+
Write data to the underlying stream.
|
|
157
|
+
|
|
158
|
+
Any exceptions encountered will be dispatched to the exception callback, if defined.
|
|
157
159
|
|
|
158
160
|
Parameters
|
|
159
161
|
----------
|
|
@@ -20,8 +20,9 @@ E = TypeVar("E", bound=Enum)
|
|
|
20
20
|
|
|
21
21
|
def validate_path(value: PathLike[str] | str, param: str) -> Path:
|
|
22
22
|
"""
|
|
23
|
-
Validate whether the given value is a valid path.
|
|
24
|
-
|
|
23
|
+
Validate whether the given value is a valid path.
|
|
24
|
+
|
|
25
|
+
This also expands user directories to form valid paths.
|
|
25
26
|
|
|
26
27
|
Parameters
|
|
27
28
|
----------
|
|
@@ -122,7 +122,7 @@ class BatchHttpAPI(BentoHttpAPI):
|
|
|
122
122
|
`dbn`.
|
|
123
123
|
split_symbols : bool, default False
|
|
124
124
|
If files should be split by raw symbol. Cannot be requested with `'ALL_SYMBOLS'`.
|
|
125
|
-
split_duration : SplitDuration or str {'day', 'week', 'month', 'none'}, default 'day'
|
|
125
|
+
split_duration : SplitDuration or str {'day', 'week', 'month', 'year', 'none'}, default 'day'
|
|
126
126
|
The maximum time duration before batched data is split into multiple files.
|
|
127
127
|
A week starts on Sunday UTC.
|
|
128
128
|
split_size : int, optional
|
|
@@ -588,7 +588,8 @@ class _BatchJob:
|
|
|
588
588
|
"""
|
|
589
589
|
Helper class for downloading multiple batch files from a job.
|
|
590
590
|
|
|
591
|
-
Supports sync and async downloads using a shared
|
|
591
|
+
Supports sync and async downloads using a shared
|
|
592
|
+
`ThreadPoolExecutor`.
|
|
592
593
|
|
|
593
594
|
"""
|
|
594
595
|
|
|
@@ -159,8 +159,9 @@ class Live:
|
|
|
159
159
|
@property
|
|
160
160
|
def dataset(self) -> str:
|
|
161
161
|
"""
|
|
162
|
-
Return the dataset for this live client.
|
|
163
|
-
|
|
162
|
+
Return the dataset for this live client.
|
|
163
|
+
|
|
164
|
+
If no subscriptions have been made an empty string will be returned.
|
|
164
165
|
|
|
165
166
|
Returns
|
|
166
167
|
-------
|
|
@@ -234,8 +235,9 @@ class Live:
|
|
|
234
235
|
@property
|
|
235
236
|
def session_id(self) -> str | None:
|
|
236
237
|
"""
|
|
237
|
-
Return the session ID for the current session.
|
|
238
|
-
|
|
238
|
+
Return the session ID for the current session.
|
|
239
|
+
|
|
240
|
+
If `None`, the client is not connected.
|
|
239
241
|
|
|
240
242
|
Returns
|
|
241
243
|
-------
|
|
@@ -279,8 +281,9 @@ class Live:
|
|
|
279
281
|
@property
|
|
280
282
|
def symbology_map(self) -> dict[int, str | int]:
|
|
281
283
|
"""
|
|
282
|
-
Return the symbology map for this client session.
|
|
283
|
-
|
|
284
|
+
Return the symbology map for this client session.
|
|
285
|
+
|
|
286
|
+
A symbol mapping is added when the client receives a SymbolMappingMsg.
|
|
284
287
|
|
|
285
288
|
This can be used to transform an `instrument_id` in a DBN record
|
|
286
289
|
to the input symbology.
|
|
@@ -398,8 +401,9 @@ class Live:
|
|
|
398
401
|
exception_callback: ExceptionCallback | None = None,
|
|
399
402
|
) -> None:
|
|
400
403
|
"""
|
|
401
|
-
Add a callback for handling client reconnection events.
|
|
402
|
-
|
|
404
|
+
Add a callback for handling client reconnection events.
|
|
405
|
+
|
|
406
|
+
This will only be called when using a reconnection policy other than
|
|
403
407
|
`ReconnectPolicy.NONE` and if the session has been started with
|
|
404
408
|
`Live.start`.
|
|
405
409
|
|
|
@@ -614,8 +618,9 @@ class Live:
|
|
|
614
618
|
timeout: float | None = None,
|
|
615
619
|
) -> None:
|
|
616
620
|
"""
|
|
617
|
-
Block until the session closes or a timeout is reached.
|
|
618
|
-
|
|
621
|
+
Block until the session closes or a timeout is reached.
|
|
622
|
+
|
|
623
|
+
A session will close after the remote gateway disconnects, or after `Live.stop` or
|
|
619
624
|
`Live.terminate` are called.
|
|
620
625
|
|
|
621
626
|
If a `timeout` is specified, `Live.terminate` will be called when the
|
|
@@ -661,8 +666,9 @@ class Live:
|
|
|
661
666
|
timeout: float | None = None,
|
|
662
667
|
) -> None:
|
|
663
668
|
"""
|
|
664
|
-
Coroutine to wait until the session closes or a timeout is reached.
|
|
665
|
-
|
|
669
|
+
Coroutine to wait until the session closes or a timeout is reached.
|
|
670
|
+
|
|
671
|
+
A session will close when the remote gateway disconnects, or after
|
|
666
672
|
`Live.stop` or `Live.terminate` are called.
|
|
667
673
|
|
|
668
674
|
If a `timeout` is specified, `Live.terminate` will be called when the
|
|
@@ -718,8 +724,9 @@ class Live:
|
|
|
718
724
|
|
|
719
725
|
class LiveIterator:
|
|
720
726
|
"""
|
|
721
|
-
Iterator class for the `Live` client.
|
|
722
|
-
|
|
727
|
+
Iterator class for the `Live` client.
|
|
728
|
+
|
|
729
|
+
Automatically starts the client when created and will stop it when destroyed. This provides context-manager-like
|
|
723
730
|
behavior to for loops.
|
|
724
731
|
|
|
725
732
|
Parameters
|
|
@@ -194,8 +194,9 @@ class GatewayDecoder:
|
|
|
194
194
|
|
|
195
195
|
def write(self, data: bytes) -> None:
|
|
196
196
|
"""
|
|
197
|
-
Write data to the decoder's buffer.
|
|
198
|
-
|
|
197
|
+
Write data to the decoder's buffer.
|
|
198
|
+
|
|
199
|
+
This will make the data available for decoding.
|
|
199
200
|
|
|
200
201
|
Parameters
|
|
201
202
|
----------
|
|
@@ -208,8 +209,9 @@ class GatewayDecoder:
|
|
|
208
209
|
|
|
209
210
|
def decode(self) -> list[GatewayControl]:
|
|
210
211
|
"""
|
|
211
|
-
Decode messages from the decoder's buffer.
|
|
212
|
-
|
|
212
|
+
Decode messages from the decoder's buffer.
|
|
213
|
+
|
|
214
|
+
This will consume decoded data from the buffer.
|
|
213
215
|
|
|
214
216
|
Returns
|
|
215
217
|
-------
|
|
@@ -150,8 +150,9 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
|
|
|
150
150
|
@property
|
|
151
151
|
def is_streaming(self) -> bool:
|
|
152
152
|
"""
|
|
153
|
-
True if the session has started streaming.
|
|
154
|
-
|
|
153
|
+
True if the session has started streaming.
|
|
154
|
+
|
|
155
|
+
This occurs when the SessionStart message is sent to the gateway.
|
|
155
156
|
|
|
156
157
|
Returns
|
|
157
158
|
-------
|
|
@@ -255,7 +256,7 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
|
|
|
255
256
|
|
|
256
257
|
"""
|
|
257
258
|
logger.debug("read %d bytes from remote gateway", nbytes)
|
|
258
|
-
data = self.__buffer[:nbytes]
|
|
259
|
+
data = bytes(memoryview(self.__buffer)[:nbytes])
|
|
259
260
|
|
|
260
261
|
if self.authenticated.done():
|
|
261
262
|
self._process_dbn(data)
|
|
@@ -266,8 +267,9 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
|
|
|
266
267
|
|
|
267
268
|
def received_metadata(self, metadata: databento_dbn.Metadata) -> None:
|
|
268
269
|
"""
|
|
269
|
-
Call when the protocol receives a Metadata header.
|
|
270
|
-
|
|
270
|
+
Call when the protocol receives a Metadata header.
|
|
271
|
+
|
|
272
|
+
This is always sent by the gateway before any data records.
|
|
271
273
|
|
|
272
274
|
Parameters
|
|
273
275
|
----------
|
|
@@ -297,8 +299,9 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
|
|
|
297
299
|
subscription_id: int | None = None,
|
|
298
300
|
) -> list[SubscriptionRequest]:
|
|
299
301
|
"""
|
|
300
|
-
Send a SubscriptionRequest to the gateway.
|
|
301
|
-
|
|
302
|
+
Send a SubscriptionRequest to the gateway.
|
|
303
|
+
|
|
304
|
+
Returns a list of all subscription requests sent to the gateway.
|
|
302
305
|
|
|
303
306
|
Parameters
|
|
304
307
|
----------
|
|
@@ -375,8 +378,7 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
|
|
|
375
378
|
raise ValueError("not connected")
|
|
376
379
|
|
|
377
380
|
try:
|
|
378
|
-
self._dbn_decoder.
|
|
379
|
-
records = self._dbn_decoder.decode()
|
|
381
|
+
records = self._dbn_decoder.write_and_decode(data)
|
|
380
382
|
except Exception:
|
|
381
383
|
logger.exception("error decoding DBN record")
|
|
382
384
|
self.__transport.close()
|
|
@@ -36,6 +36,9 @@ logger = logging.getLogger(__name__)
|
|
|
36
36
|
AUTH_TIMEOUT_SECONDS: Final = 30.0
|
|
37
37
|
CONNECT_TIMEOUT_SECONDS: Final = 10.0
|
|
38
38
|
DBN_QUEUE_CAPACITY: Final = 2**20
|
|
39
|
+
DBN_QUEUE_LAG_THRESHOLD: Final = 128
|
|
40
|
+
DBN_QUEUE_MAX_LAG_NS: Final = 1_000_000_000
|
|
41
|
+
DBN_QUEUE_FULL_WARNING_INTERVAL_S: Final = 60.0
|
|
39
42
|
DEFAULT_REMOTE_PORT: Final = 13000
|
|
40
43
|
CLIENT_TIMEOUT_MARGIN_SECONDS: Final = 10
|
|
41
44
|
|
|
@@ -48,6 +51,8 @@ class DBNQueue(queue.SimpleQueue): # type: ignore [type-arg]
|
|
|
48
51
|
def __init__(self) -> None:
|
|
49
52
|
super().__init__()
|
|
50
53
|
self._enabled = threading.Event()
|
|
54
|
+
self._front_ts_index: int | None = None
|
|
55
|
+
self._back_ts_index: int | None = None
|
|
51
56
|
|
|
52
57
|
def is_enabled(self) -> bool:
|
|
53
58
|
"""
|
|
@@ -62,7 +67,16 @@ class DBNQueue(queue.SimpleQueue): # type: ignore [type-arg]
|
|
|
62
67
|
"""
|
|
63
68
|
Return True when the queue has reached capacity; False otherwise.
|
|
64
69
|
"""
|
|
65
|
-
|
|
70
|
+
if self.qsize() > DBN_QUEUE_CAPACITY:
|
|
71
|
+
return True
|
|
72
|
+
if (
|
|
73
|
+
self.qsize() > DBN_QUEUE_LAG_THRESHOLD
|
|
74
|
+
and self._front_ts_index is not None
|
|
75
|
+
and self._back_ts_index is not None
|
|
76
|
+
and self._back_ts_index - self._front_ts_index > DBN_QUEUE_MAX_LAG_NS
|
|
77
|
+
):
|
|
78
|
+
return True
|
|
79
|
+
return False
|
|
66
80
|
|
|
67
81
|
def enable(self) -> None:
|
|
68
82
|
"""
|
|
@@ -106,6 +120,9 @@ class DBNQueue(queue.SimpleQueue): # type: ignore [type-arg]
|
|
|
106
120
|
|
|
107
121
|
"""
|
|
108
122
|
if self._enabled.wait(timeout):
|
|
123
|
+
if self._front_ts_index is None:
|
|
124
|
+
self._front_ts_index = item.ts_index
|
|
125
|
+
self._back_ts_index = item.ts_index
|
|
109
126
|
return super().put(item, block, timeout)
|
|
110
127
|
if timeout is not None:
|
|
111
128
|
raise BentoError(f"queue is not enabled after {timeout} second(s)")
|
|
@@ -131,9 +148,34 @@ class DBNQueue(queue.SimpleQueue): # type: ignore [type-arg]
|
|
|
131
148
|
|
|
132
149
|
"""
|
|
133
150
|
if self.is_enabled():
|
|
151
|
+
if self._front_ts_index is None:
|
|
152
|
+
self._front_ts_index = item.ts_index
|
|
153
|
+
self._back_ts_index = item.ts_index
|
|
134
154
|
return super().put_nowait(item)
|
|
135
155
|
raise BentoError("queue is not enabled")
|
|
136
156
|
|
|
157
|
+
def get(
|
|
158
|
+
self,
|
|
159
|
+
block: bool = True,
|
|
160
|
+
timeout: float | None = None,
|
|
161
|
+
) -> DBNRecord:
|
|
162
|
+
record = super().get(block, timeout)
|
|
163
|
+
if self.empty():
|
|
164
|
+
self._front_ts_index = None
|
|
165
|
+
self._back_ts_index = None
|
|
166
|
+
else:
|
|
167
|
+
self._front_ts_index = record.ts_index
|
|
168
|
+
return record
|
|
169
|
+
|
|
170
|
+
def get_nowait(self) -> DBNRecord:
|
|
171
|
+
record = super().get_nowait()
|
|
172
|
+
if self.empty():
|
|
173
|
+
self._front_ts_index = None
|
|
174
|
+
self._back_ts_index = None
|
|
175
|
+
else:
|
|
176
|
+
self._front_ts_index = record.ts_index
|
|
177
|
+
return record
|
|
178
|
+
|
|
137
179
|
|
|
138
180
|
@dataclasses.dataclass
|
|
139
181
|
class SessionMetadata:
|
|
@@ -160,8 +202,9 @@ class SessionMetadata:
|
|
|
160
202
|
|
|
161
203
|
def check(self, other: databento_dbn.Metadata) -> None:
|
|
162
204
|
"""
|
|
163
|
-
Verify the Metadata is compatible with another Metadata message.
|
|
164
|
-
|
|
205
|
+
Verify the Metadata is compatible with another Metadata message.
|
|
206
|
+
|
|
207
|
+
This is used to ensure DBN streams are compatible with one another.
|
|
165
208
|
|
|
166
209
|
Parameters
|
|
167
210
|
----------
|
|
@@ -225,6 +268,7 @@ class _SessionProtocol(DatabentoLiveProtocol):
|
|
|
225
268
|
self._user_streams = user_streams
|
|
226
269
|
self._last_ts_event: int | None = None
|
|
227
270
|
self._last_msg_loop_time: float = math.inf
|
|
271
|
+
self._last_queue_full_warning_t: float = -math.inf
|
|
228
272
|
|
|
229
273
|
def received_metadata(self, metadata: databento_dbn.Metadata) -> None:
|
|
230
274
|
if self._metadata:
|
|
@@ -282,10 +326,13 @@ class _SessionProtocol(DatabentoLiveProtocol):
|
|
|
282
326
|
self._dbn_queue.put(record)
|
|
283
327
|
# DBNQueue has no max size; so check if it's above capacity, and if so, pause reading
|
|
284
328
|
if self._dbn_queue.is_full():
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
329
|
+
now = self._loop.time()
|
|
330
|
+
if now - self._last_queue_full_warning_t >= DBN_QUEUE_FULL_WARNING_INTERVAL_S:
|
|
331
|
+
logger.warning(
|
|
332
|
+
"record queue is full; %d record(s) to be processed",
|
|
333
|
+
self._dbn_queue.qsize(),
|
|
334
|
+
)
|
|
335
|
+
self._last_queue_full_warning_t = now
|
|
289
336
|
self.transport.pause_reading()
|
|
290
337
|
|
|
291
338
|
|
|
@@ -485,8 +532,9 @@ class LiveSession:
|
|
|
485
532
|
snapshot: bool = False,
|
|
486
533
|
) -> int:
|
|
487
534
|
"""
|
|
488
|
-
Send a subscription request on the current connection.
|
|
489
|
-
|
|
535
|
+
Send a subscription request on the current connection.
|
|
536
|
+
|
|
537
|
+
This will create a new connection if there is no active connection to the gateway.
|
|
490
538
|
|
|
491
539
|
Parameters
|
|
492
540
|
----------
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.78.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "databento"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.78.0"
|
|
4
4
|
description = "Official Python client library for Databento"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -10,7 +10,7 @@ dynamic = [ "classifiers" ]
|
|
|
10
10
|
dependencies = [
|
|
11
11
|
"aiohttp>=3.8.3,<4.0.0; python_version < '3.12'",
|
|
12
12
|
"aiohttp>=3.9.0,<4.0.0; python_version >= '3.12'",
|
|
13
|
-
"databento-dbn~=0.
|
|
13
|
+
"databento-dbn~=0.58.0",
|
|
14
14
|
"numpy>=1.23.5; python_version < '3.12'",
|
|
15
15
|
"numpy>=1.26.0; python_version >= '3.12'",
|
|
16
16
|
"pandas>=1.5.3,<4.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.76.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|