hyperquant 0.45__tar.gz → 0.46__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.
Files changed (30) hide show
  1. {hyperquant-0.45 → hyperquant-0.46}/PKG-INFO +1 -1
  2. {hyperquant-0.45 → hyperquant-0.46}/pyproject.toml +1 -1
  3. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/models/ourbit.py +60 -35
  4. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/ourbit.py +13 -9
  5. {hyperquant-0.45 → hyperquant-0.46}/tmp.py +5 -1
  6. {hyperquant-0.45 → hyperquant-0.46}/uv.lock +1 -1
  7. {hyperquant-0.45 → hyperquant-0.46}/.gitignore +0 -0
  8. {hyperquant-0.45 → hyperquant-0.46}/.python-version +0 -0
  9. {hyperquant-0.45 → hyperquant-0.46}/README.md +0 -0
  10. {hyperquant-0.45 → hyperquant-0.46}/data/logs/notikit.log +0 -0
  11. {hyperquant-0.45 → hyperquant-0.46}/pub.sh +0 -0
  12. {hyperquant-0.45 → hyperquant-0.46}/requirements-dev.lock +0 -0
  13. {hyperquant-0.45 → hyperquant-0.46}/requirements.lock +0 -0
  14. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/__init__.py +0 -0
  15. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/auth.py +0 -0
  16. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/hyperliquid.py +0 -0
  17. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/lib/hpstore.py +0 -0
  18. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/lib/hyper_types.py +0 -0
  19. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/models/hyperliquid.py +0 -0
  20. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/broker/ws.py +0 -0
  21. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/core.py +0 -0
  22. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/datavison/_util.py +0 -0
  23. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/datavison/binance.py +0 -0
  24. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/datavison/coinglass.py +0 -0
  25. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/datavison/okx.py +0 -0
  26. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/db.py +0 -0
  27. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/draw.py +0 -0
  28. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/logkit.py +0 -0
  29. {hyperquant-0.45 → hyperquant-0.46}/src/hyperquant/notikit.py +0 -0
  30. {hyperquant-0.45 → hyperquant-0.46}/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 0.45
3
+ Version: 0.46
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hyperquant"
3
- version = "0.45"
3
+ version = "0.46"
4
4
  description = "A minimal yet hyper-efficient backtesting framework for quantitative trading"
5
5
  authors = [
6
6
  { name = "MissinA", email = "1421329142@qq.com" }
@@ -697,8 +697,9 @@ class SpotBook(DataStore):
697
697
  # super().__init__()
698
698
  self._time: int | None = None
699
699
  self.limit = 1
700
- self.loss = True
701
- self.version = None
700
+ self.loss = {} # 改为字典,按symbol跟踪
701
+ self.versions = {}
702
+ self.cache = []
702
703
 
703
704
  def _onresponse(self, data: dict[str, Any]):
704
705
  data = data.get("data")
@@ -706,18 +707,22 @@ class SpotBook(DataStore):
706
707
  book_data = data.get("data")
707
708
  asks = book_data.get("asks", [])
708
709
  bids = book_data.get("bids", [])
709
- version = int(data.get("version", 0))
710
+ version = int(data.get("version", None))
711
+
710
712
 
711
713
  # 保存当前快照版本
712
- self.version = version
713
-
714
- # 应用缓存的增量(只保留连续的部分)
715
- items: list = self.find({"s": symbol})
714
+ self.versions[symbol] = version
715
+
716
+ # # 应用缓存的增量(只保留连续的部分)
717
+ # items: list = self.find({"s": symbol})
718
+ # items.sort(key=lambda x: x.get("fv", 0)) # 按 fromVersion 排序
719
+ # self._find_and_delete({"s": symbol})
720
+
721
+ # 处理缓存
722
+ items = [item for item in self.cache if item.get("s") == symbol]
716
723
  items.sort(key=lambda x: x.get("fv", 0)) # 按 fromVersion 排序
724
+ self.cache = [item for item in self.cache if item.get("s") != symbol]
717
725
 
718
- # 清空旧数据,插入快照
719
- self._find_and_delete({"s": symbol})
720
-
721
726
  for side, S in ((asks, "a"), (bids, "b")):
722
727
  for item in side:
723
728
  self._insert([{"s": symbol, "S": S, "p": item["p"], "q": item["q"]}])
@@ -725,57 +730,77 @@ class SpotBook(DataStore):
725
730
  if items:
726
731
  min_version = min(item.get("fv", 0) for item in items)
727
732
  max_version = max(item.get("tv", 0) for item in items)
728
- self.version = max_version
733
+ # self.version = max_version
734
+ self.versions[symbol] = max_version
729
735
 
730
- if not (min_version <= self.version <= max_version):
731
- self.loss = True
736
+ # if max_version == 0:
737
+ # print('vvv---')
738
+ # print(items)
739
+
740
+ if not (min_version <= self.versions[symbol] <= max_version):
741
+ self.loss[symbol] = True
732
742
  logger.warning(f"SpotBook: Snapshot version {self.version} out of range ({min_version}, {max_version}) for symbol={symbol} (丢补丁)")
733
743
  return
734
-
735
- self.loss = False
744
+
745
+ # 处理过往msg内容
746
+ self.loss[symbol] = False
736
747
  for item in items:
737
748
  fv, tv = item.get("fv", 0), item.get("tv", 0)
738
- if self.version <= tv and self.version >= fv:
739
- self._insert([{ "s": symbol, "S": item["S"], "p": item["p"], "q": item["q"]}])
749
+ if self.versions[symbol] <= tv and self.versions[symbol] >= fv:
750
+ if float(item["q"]) == 0.0:
751
+ self._find_and_delete({"s": symbol, "S": item["S"], "p": item["p"]})
752
+ else:
753
+ self._insert([{ "s": symbol, "S": item["S"], "p": item["p"], "q": item["q"]}])
754
+
755
+ sort_data = self.sorted({'s': symbol}, self.limit)
756
+ asks = sort_data.get('a', [])
757
+ bids = sort_data.get('b', [])
758
+ self._find_and_delete({'s': symbol})
759
+ self._update(asks + bids)
760
+
740
761
  else:
741
- self.loss = False
762
+ self.loss[symbol] = False
742
763
 
743
764
 
744
765
  def _on_message(self, msg: dict[str, Any]) -> None:
745
766
 
746
- ts = time.time() * 1000 # 预留时间戳(如需记录可用)
767
+ # ts = time.time() * 1000 # 预留时间戳(如需记录可用)
747
768
  data = msg.get("d", {}) or {}
748
769
  symbol = msg.get("s")
749
770
  fv = int(data.get("fromVersion"))
750
771
  tv = int(data.get("toVersion"))
772
+ if fv == 0 or tv == 0:
773
+ # print(f'发现fv或tv为0, msg:\n {msg}')
774
+ return
775
+
751
776
  asks: list = data.get("asks", []) or []
752
777
  bids: list = data.get("bids", []) or []
753
778
 
779
+ now_version = self.versions.get(symbol, None)
780
+
754
781
  # 以下几张情况都会被认为正常
755
782
  check_con = (
756
- self.version is None or
757
- fv <= self.version <= tv or
758
- self.version + 1 == fv
783
+ now_version is None or
784
+ fv <= now_version <= tv or
785
+ now_version + 1 == fv
759
786
  )
760
787
 
761
788
  if not check_con:
762
- logger.warning(f"(丢补丁) version:{self.version} fv:{fv} tv:{tv} msg:\n {msg}")
763
- # self.loss = True # 暂时不这样做
764
- return
765
-
766
- self.version = tv
789
+ logger.warning(f"(丢补丁) version:{now_version} fv:{fv} tv:{tv} ")
790
+ self.loss[symbol] = True # 暂时不这样做
791
+
792
+
767
793
 
768
- if self.loss:
794
+ if self.loss.get(symbol, True):
769
795
  for item in asks:
770
- self._insert(
771
- [{"s": symbol, "S": "a", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv}]
772
- )
796
+ self.cache.append({"s": symbol, "S": "a", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv})
773
797
  for item in bids:
774
- self._insert(
775
- [{"s": symbol, "S": "b", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv}]
776
- )
798
+ self.cache.append({"s": symbol, "S": "b", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv})
777
799
  return
778
800
 
801
+ self.versions[symbol] = tv
802
+
803
+
779
804
  to_delete, to_update = [], []
780
805
  for side, S in ((asks, "a"), (bids, "b")):
781
806
  for item in side:
@@ -793,7 +818,7 @@ class SpotBook(DataStore):
793
818
  self._find_and_delete({'s': symbol})
794
819
  self._update(asks + bids)
795
820
 
796
- print(f'处理耗时: {time.time()*1000 - ts:.2f} ms')
821
+ # print(f'处理耗时: {time.time()*1000 - ts:.2f} ms')
797
822
 
798
823
 
799
824
 
@@ -413,7 +413,7 @@ class OurbitSpot:
413
413
  )
414
414
  await wsapp._event.wait()
415
415
 
416
- # await asyncio.sleep(2) # 等待ws连接稳定
416
+ # await asyncio.sleep(1) # 等待ws连接稳定
417
417
 
418
418
  # 并发获取每个交易对的初始深度数据
419
419
  tasks = [
@@ -428,14 +428,18 @@ class OurbitSpot:
428
428
  for idx, response in enumerate(responses):
429
429
  symbol = symbols[idx]
430
430
  self.store.book._onresponse(response.data)
431
- # Check if initialization failed (loss is False), retry if so
432
- retry_count = 0
433
- while self.store.book.loss is True:
434
- logger.warning(f"Orderbook initialization failed for {symbol}, refetching depth snapshot (retry {retry_count+1})")
435
- await asyncio.sleep(0.1)
436
- response_retry = await self.client.fetch('GET', f"{self.api_url}/api/platform/spot/market/depth?symbol={symbol}")
437
- self.store.book._onresponse(response_retry.data)
438
- retry_count += 1
431
+
432
+ async def check_loss():
433
+ await asyncio.sleep(1)
434
+ while True:
435
+ loss = self.store.book.loss
436
+ for symbol, is_loss in loss.items():
437
+ if is_loss:
438
+ resp = await self.client.fetch('GET', f"{self.api_url}/api/platform/spot/market/depth?symbol={symbol}")
439
+ self.store.book._onresponse(resp.data)
440
+ await asyncio.sleep(1)
441
+
442
+ asyncio.create_task(check_loss())
439
443
 
440
444
 
441
445
  async def place_order(
@@ -146,7 +146,11 @@ async def test_orderbook():
146
146
  }) as client:
147
147
  ob_spot = OurbitSpot(client)
148
148
  await ob_spot.__aenter__()
149
- await ob_spot.sub_orderbook(['XRP_USDT'])
149
+ await ob_spot.update('ticker')
150
+ # symbols = [d['symbol'] for d in ob_spot.store.ticker.find()][:30]
151
+ symbols = ['ETC_USDT']
152
+
153
+ await ob_spot.sub_orderbook(symbols)
150
154
  while True:
151
155
  await ob_spot.store.book.wait()
152
156
  print(ob_spot.store.book.find())
@@ -530,7 +530,7 @@ wheels = [
530
530
 
531
531
  [[package]]
532
532
  name = "hyperquant"
533
- version = "0.44"
533
+ version = "0.45"
534
534
  source = { editable = "." }
535
535
  dependencies = [
536
536
  { name = "aiohttp" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes