| 150 |
150 |
assert r.status_code == 400 and r.json()["error"]["code"] == "INVALID_PARAMETER" |
| 151 |
151 |
|
| 152 |
152 |
|
| 153 |
|
−def test_cursor_pagination(client, backfilled): |
| 154 |
|
− r1 = client.get("/v1/futures/contract/ESH25/bars?interval=5m&limit=7") |
|
153 |
+def test_cursor_pagination(client_hu, backfilled): |
|
154 |
+ r1 = client_hu.get("/v1/futures/contract/ESH25/bars?interval=5m&limit=7") |
| 155 |
155 |
b1 = r1.json() |
| 156 |
156 |
assert len(b1["data"]) == 7 and b1["meta"]["next_cursor"] |
| 157 |
|
− r2 = client.get(f"/v1/futures/contract/ESH25/bars?interval=5m&limit=7&cursor={b1['meta']['next_cursor']}") |
|
157 |
+ r2 = client_hu.get(f"/v1/futures/contract/ESH25/bars?interval=5m&limit=7&cursor={b1['meta']['next_cursor']}") |
| 158 |
158 |
b2 = r2.json() |
| 159 |
159 |
assert len(b2["data"]) == 7 and b2["data"][0]["datetime"] > b1["data"][-1]["datetime"] |
| 160 |
|
− full = client.get("/v1/futures/contract/ESH25/bars?interval=5m&limit=14").json()["data"] |
|
160 |
+ full = client_hu.get("/v1/futures/contract/ESH25/bars?interval=5m&limit=14").json()["data"] |
| 161 |
161 |
assert [x["datetime"] for x in b1["data"] + b2["data"]] == [x["datetime"] for x in full] |
| 162 |
|
− last = client.get("/v1/futures/contract/ESH25/bars?interval=1d&limit=100000").json() |
|
162 |
+ last = client_hu.get("/v1/futures/contract/ESH25/bars?interval=1d&limit=100000").json() |
| 163 |
163 |
assert last["meta"]["next_cursor"] is None |
| 164 |
|
− assert client.get("/v1/futures/contract/ESH25/bars?cursor=%%%").json()["error"]["code"] == "INVALID_PARAMETER" |
| 165 |
|
− assert client.get("/v1/futures/contract/ESH25/bars?limit=0").json()["error"]["code"] == "INVALID_PARAMETER" |
|
164 |
+ assert client_hu.get("/v1/futures/contract/ESH25/bars?cursor=%%%").json()["error"]["code"] == "INVALID_PARAMETER" |
|
165 |
+ assert client_hu.get("/v1/futures/contract/ESH25/bars?limit=0").json()["error"]["code"] == "INVALID_PARAMETER" |
| 166 |
166 |
|
| 167 |
167 |
|
| 168 |
168 |
def test_bars_csv_and_parquet(client, backfilled): |
| 178 |
178 |
assert len(df) == 50 and str(df["datetime"].dtype).endswith("UTC]") and list(df.columns)[:2] == ["symbol", "datetime"] |
| 179 |
179 |
|
| 180 |
180 |
|
| 181 |
|
−def test_bars_merge_archive_and_update_dedup(client, backfilled): |
|
181 |
+def test_bars_merge_archive_and_update_dedup(client_hu, backfilled): |
| 182 |
182 |
"""ESH25 exists in both buckets (archive ≤ 2024-12-31, update full): no duplicate dates.""" |
| 183 |
|
− d = client.get("/v1/futures/contract/ESH25/bars?interval=1d&limit=100000").json()["data"] |
|
183 |
+ d = client_hu.get("/v1/futures/contract/ESH25/bars?interval=1d&limit=100000").json()["data"] |
| 184 |
184 |
dates = [x["datetime"] for x in d] |
| 185 |
185 |
assert len(dates) == len(set(dates)) and dates[0] < "2024-12-31" < dates[-1] |
| 186 |
186 |
|
| 290 |
290 |
assert client.get("/v1/futures/ES/continuous?depth=4").json()["error"]["code"] == "INVALID_PARAMETER" |
| 291 |
291 |
|
| 292 |
292 |
|
| 293 |
|
−def test_continuous_intraday_applies_daily_schedule(client, backfilled): |
| 294 |
|
− r = client.get("/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100000") |
|
293 |
+def test_continuous_intraday_applies_daily_schedule(client_hu, backfilled): |
|
294 |
+ r = client_hu.get("/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100000") |
| 295 |
295 |
assert r.status_code == 200 |
| 296 |
296 |
body = r.json() |
| 297 |
297 |
syms = [x["symbol"] for x in body["data"]] |
| 300 |
300 |
assert ts == sorted(ts) and all(t.endswith("Z") for t in ts) and ts[0] >= "2025-06-10T13:30:00Z" |
| 301 |
301 |
assert len(body["meta"]["roll_dates"]) == 1 and body["meta"]["roll_dates"][0]["to_symbol"] == "ESU25" |
| 302 |
302 |
assert "open_interest" not in body["data"][0] |
| 303 |
|
− page = client.get("/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100").json() |
| 304 |
|
− nxt = client.get(f"/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100&cursor={page['meta']['next_cursor']}").json() |
|
303 |
+ page = client_hu.get("/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100").json() |
|
304 |
+ nxt = client_hu.get(f"/v1/futures/ES/continuous?interval=1m&roll=volume&from=2025-06-10&to=2025-06-25&session=rth&limit=100&cursor={page['meta']['next_cursor']}").json() |
| 305 |
305 |
assert nxt["data"][0]["datetime"] > page["data"][-1]["datetime"] |
| 306 |
|
− r = client.get("/v1/futures/ES/continuous?interval=1m&from=2025-06-10&to=2025-06-12&format=parquet") |
|
306 |
+ r = client_hu.get("/v1/futures/ES/continuous?interval=1m&from=2025-06-10&to=2025-06-12&format=parquet") |
| 307 |
307 |
assert r.status_code == 200 and int(r.headers["X-Row-Count"]) > 0 |
| 308 |
|
− r = client.get("/v1/futures/ES/continuous?from=2025-06-10&to=2025-06-12&format=csv") |
|
308 |
+ r = client_hu.get("/v1/futures/ES/continuous?from=2025-06-10&to=2025-06-12&format=csv") |
| 309 |
309 |
assert r.text.splitlines()[0].startswith("symbol,datetime") |
| 310 |
310 |
|
| 311 |
311 |
|