hyperquant 1.36__tar.gz → 1.37__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.
- {hyperquant-1.36 → hyperquant-1.37}/PKG-INFO +1 -1
- {hyperquant-1.36 → hyperquant-1.37}/pyproject.toml +1 -1
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/polymarket.py +49 -13
- {hyperquant-1.36 → hyperquant-1.37}/uv.lock +1 -1
- {hyperquant-1.36 → hyperquant-1.37}/.gitignore +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/README.md +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/requirements-dev.lock +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/requirements.lock +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/__init__.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/auth.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/bitget.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/bitmart.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/coinw.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/deepcoin.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/edgex.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/hyperliquid.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lbank.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lib/hpstore.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lib/hyper_types.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lib/util.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/lighter.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/apexpro.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/bitget.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/bitmart.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/coinw.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/deepcoin.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/edgex.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/hyperliquid.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/lbank.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/lighter.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/ourbit.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/models/polymarket.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/ourbit.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/broker/ws.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/core.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/datavison/_util.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/datavison/binance.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/datavison/coinglass.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/datavison/okx.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/db.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/draw.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/logkit.py +0 -0
- {hyperquant-1.36 → hyperquant-1.37}/src/hyperquant/notikit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperquant
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.37
|
|
4
4
|
Summary: A minimal yet hyper-efficient backtesting framework for quantitative trading
|
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/hyperquant
|
|
6
6
|
Project-URL: Issues, https://github.com/yourusername/hyperquant/issues
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from contextlib import suppress
|
|
5
|
-
from datetime import UTC, datetime
|
|
5
|
+
from datetime import UTC, datetime, timedelta
|
|
6
6
|
from functools import lru_cache
|
|
7
7
|
import os
|
|
8
8
|
from typing import Any, Iterable, Iterator, Literal, Mapping, Sequence
|
|
@@ -12,6 +12,7 @@ import json
|
|
|
12
12
|
import aiohttp
|
|
13
13
|
import pybotters
|
|
14
14
|
import pybotters.ws
|
|
15
|
+
import pytz
|
|
15
16
|
|
|
16
17
|
from .models.polymarket import PolymarketDataStore
|
|
17
18
|
from .auth import Auth
|
|
@@ -22,6 +23,7 @@ GAMMA_EVENTS_API = "https://gamma-api.polymarket.com/events"
|
|
|
22
23
|
DEFAULT_DATA_ENDPOINT = "https://data-api.polymarket.com"
|
|
23
24
|
RTS_DATA_ENDPOINT = "wss://ws-live-data.polymarket.com/"
|
|
24
25
|
DEFAULT_BASE_SLUG = "btc-updown-15m"
|
|
26
|
+
HOURLY_BITCOIN_BASE_SLUG = "bitcoin-up-or-down"
|
|
25
27
|
DEFAULT_INTERVAL = 15 * 60
|
|
26
28
|
DEFAULT_WINDOW = 8
|
|
27
29
|
API_NAME = "polymarket"
|
|
@@ -38,6 +40,7 @@ DEFAULT_POLYGON_RPCS = (
|
|
|
38
40
|
"https://polygon-rpc.com",
|
|
39
41
|
"https://rpc.ankr.com/polygon",
|
|
40
42
|
)
|
|
43
|
+
_EASTERN_TZ = pytz.timezone("US/Eastern")
|
|
41
44
|
|
|
42
45
|
def parse_field(value):
|
|
43
46
|
"""尝试将字符串 JSON 转为对象,否则原样返回"""
|
|
@@ -73,6 +76,21 @@ def _accepting_orders(market: Mapping[str, Any]) -> bool:
|
|
|
73
76
|
return bool(accepting)
|
|
74
77
|
|
|
75
78
|
|
|
79
|
+
def _compose_hourly_slug(base_slug: str, *, now: datetime | None = None) -> str:
|
|
80
|
+
tz_now = now or datetime.now(_EASTERN_TZ)
|
|
81
|
+
if tz_now.tzinfo is None:
|
|
82
|
+
tz_now = _EASTERN_TZ.localize(tz_now)
|
|
83
|
+
else:
|
|
84
|
+
tz_now = tz_now.astimezone(_EASTERN_TZ)
|
|
85
|
+
|
|
86
|
+
tz_now = (tz_now + timedelta(seconds=5)).replace(minute=0, second=0, microsecond=0)
|
|
87
|
+
month_str = tz_now.strftime("%B").lower()
|
|
88
|
+
day = tz_now.day
|
|
89
|
+
hour_12 = tz_now.strftime("%I").lstrip("0") or "0"
|
|
90
|
+
am_pm = tz_now.strftime("%p").lower()
|
|
91
|
+
return f"{base_slug}-{month_str}-{day}-{hour_12}{am_pm}-et"
|
|
92
|
+
|
|
93
|
+
|
|
76
94
|
class Polymarket:
|
|
77
95
|
"""Polymarket CLOB client with REST helpers, stores and WS subscriptions."""
|
|
78
96
|
|
|
@@ -1171,6 +1189,33 @@ class Polymarket:
|
|
|
1171
1189
|
https://docs.polymarket.com/api-reference/markets/get-market-by-id
|
|
1172
1190
|
"""
|
|
1173
1191
|
|
|
1192
|
+
async def _try_slug(slug: str | None) -> tuple[str, dict, dict] | None:
|
|
1193
|
+
if not slug:
|
|
1194
|
+
return None
|
|
1195
|
+
event = await self._fetch_event(slug)
|
|
1196
|
+
if not event:
|
|
1197
|
+
return None
|
|
1198
|
+
|
|
1199
|
+
event = {k: parse_field(v) for k, v in event.items()}
|
|
1200
|
+
for market in event.get("markets", []):
|
|
1201
|
+
if not _accepting_orders(market):
|
|
1202
|
+
continue
|
|
1203
|
+
market = {k: parse_field(v) for k, v in market.items()}
|
|
1204
|
+
return slug, event, market
|
|
1205
|
+
return None
|
|
1206
|
+
|
|
1207
|
+
if base_slug == HOURLY_BITCOIN_BASE_SLUG:
|
|
1208
|
+
hourly_slug = _compose_hourly_slug(base_slug)
|
|
1209
|
+
hourly_match = await _try_slug(hourly_slug)
|
|
1210
|
+
if hourly_match:
|
|
1211
|
+
return hourly_match
|
|
1212
|
+
|
|
1213
|
+
# 1小时市场等特殊 slug(比如 bitcoin-up-or-down-november-18-10am-et)
|
|
1214
|
+
# 直接传入完整 slug 即可,不再拼接时间戳
|
|
1215
|
+
direct_match = await _try_slug(base_slug)
|
|
1216
|
+
if direct_match:
|
|
1217
|
+
return direct_match
|
|
1218
|
+
|
|
1174
1219
|
now_ts = int(datetime.now(UTC).timestamp())
|
|
1175
1220
|
base_ts = (now_ts // interval) * interval
|
|
1176
1221
|
|
|
@@ -1179,18 +1224,9 @@ class Polymarket:
|
|
|
1179
1224
|
if ts < 0:
|
|
1180
1225
|
continue
|
|
1181
1226
|
slug = f"{base_slug}-{ts}"
|
|
1182
|
-
|
|
1183
|
-
if
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
event = {k: parse_field(v) for k, v in event.items()}
|
|
1189
|
-
|
|
1190
|
-
for market in event.get("markets", []):
|
|
1191
|
-
if _accepting_orders(market):
|
|
1192
|
-
market = {k: parse_field(v) for k, v in market.items()}
|
|
1193
|
-
return slug, event, market
|
|
1227
|
+
result = await _try_slug(slug)
|
|
1228
|
+
if result:
|
|
1229
|
+
return result
|
|
1194
1230
|
|
|
1195
1231
|
raise RuntimeError(
|
|
1196
1232
|
f"未在 {base_slug} 的 +/-{window} 个区间内找到可交易的市场"
|
|
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
|
|
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
|