hyperquant 1.32__tar.gz → 1.34__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 (44) hide show
  1. {hyperquant-1.32 → hyperquant-1.34}/PKG-INFO +1 -1
  2. {hyperquant-1.32 → hyperquant-1.34}/pyproject.toml +1 -1
  3. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/polymarket.py +5 -1
  4. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/polymarket.py +208 -5
  5. {hyperquant-1.32 → hyperquant-1.34}/uv.lock +1 -1
  6. {hyperquant-1.32 → hyperquant-1.34}/.gitignore +0 -0
  7. {hyperquant-1.32 → hyperquant-1.34}/README.md +0 -0
  8. {hyperquant-1.32 → hyperquant-1.34}/requirements-dev.lock +0 -0
  9. {hyperquant-1.32 → hyperquant-1.34}/requirements.lock +0 -0
  10. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/__init__.py +0 -0
  11. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/auth.py +0 -0
  12. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/bitget.py +0 -0
  13. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/bitmart.py +0 -0
  14. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/coinw.py +0 -0
  15. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/deepcoin.py +0 -0
  16. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/edgex.py +0 -0
  17. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/hyperliquid.py +0 -0
  18. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lbank.py +0 -0
  19. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
  20. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lib/hpstore.py +0 -0
  21. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lib/hyper_types.py +0 -0
  22. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lib/util.py +0 -0
  23. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/lighter.py +0 -0
  24. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/apexpro.py +0 -0
  25. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/bitget.py +0 -0
  26. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/bitmart.py +0 -0
  27. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/coinw.py +0 -0
  28. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/deepcoin.py +0 -0
  29. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/edgex.py +0 -0
  30. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/hyperliquid.py +0 -0
  31. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/lbank.py +0 -0
  32. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/lighter.py +0 -0
  33. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/models/ourbit.py +0 -0
  34. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/ourbit.py +0 -0
  35. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/broker/ws.py +0 -0
  36. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/core.py +0 -0
  37. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/datavison/_util.py +0 -0
  38. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/datavison/binance.py +0 -0
  39. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/datavison/coinglass.py +0 -0
  40. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/datavison/okx.py +0 -0
  41. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/db.py +0 -0
  42. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/draw.py +0 -0
  43. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/logkit.py +0 -0
  44. {hyperquant-1.32 → hyperquant-1.34}/src/hyperquant/notikit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 1.32
3
+ Version: 1.34
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 = "1.32"
3
+ version = "1.34"
4
4
  description = "A minimal yet hyper-efficient backtesting framework for quantitative trading"
5
5
  authors = [
6
6
  { name = "MissinA", email = "1421329142@qq.com" }
@@ -292,7 +292,7 @@ class Detail(DataStore):
292
292
 
293
293
  @staticmethod
294
294
  def _normalize_entry(market: dict[str, Any], token: dict[str, Any]) -> dict[str, Any]:
295
- slug = market.get("market_slug") or market.get("question") or market.get("id")
295
+ slug = market.get("slug")
296
296
  outcome = token.get("outcome")
297
297
  alias = slug if outcome is None else f"{slug}:{outcome}"
298
298
 
@@ -364,10 +364,14 @@ class Detail(DataStore):
364
364
 
365
365
  for token in tokens:
366
366
  normalized = self._normalize_entry(market, token)
367
+ slug: str = market.get("slug")
368
+ # 取最后一个'-'之前部分
369
+ base_slug = slug.rsplit("-", 1)[0] if slug else slug
367
370
  # Add or update additional fields from market
368
371
  normalized.update({
369
372
  "condition_id": market.get("conditionId"),
370
373
  "slug": market.get("slug"),
374
+ "base_slug": base_slug,
371
375
  "end_date": market.get("endDate"),
372
376
  "start_date": market.get("startDate"),
373
377
  "icon": market.get("icon"),
@@ -498,7 +498,7 @@ class Polymarket:
498
498
  side: str,
499
499
  price: float,
500
500
  size: float,
501
- order_type: str = "GTC",
501
+ order_type: Literal["GTC", 'FOK'] = "GTC",
502
502
  tick_size: str | float | None = None,
503
503
  fee_rate_bps: int | None = None,
504
504
  expiration: int | None = None,
@@ -523,6 +523,9 @@ class Polymarket:
523
523
  - nonce: onchain nonce, default 0
524
524
  """
525
525
 
526
+ if price <= 0:
527
+ raise ValueError("price must be positive; use place_market_order for market orders")
528
+
526
529
  # Ensure L2 creds exist
527
530
  if not self._api_creds():
528
531
  raise RuntimeError("Polymarket API credentials missing; call create_or_derive_api_creds first")
@@ -552,6 +555,117 @@ class Polymarket:
552
555
  }
553
556
  return await self._signed_request_via_session("POST", "/order", payload)
554
557
 
558
+ async def place_market_order(
559
+ self,
560
+ *,
561
+ token_id: str,
562
+ side: str,
563
+ amount: float,
564
+ order_type: Literal["FOK", "GTC", "FAK", "GTD"] = "FOK",
565
+ price: float | None = None,
566
+ tick_size: str | float | None = None,
567
+ fee_rate_bps: int | None = None,
568
+ taker: str = ZERO_ADDRESS,
569
+ neg_risk: bool = False,
570
+ owner: str | None = None,
571
+ nonce: int | None = None,
572
+ ) -> Any:
573
+ """Create, sign and submit a market order similar to ``py_clob_client``.
574
+
575
+ BUY orders treat ``amount`` as collateral (USDC); SELL orders treat it as shares.
576
+ """
577
+
578
+ if amount <= 0:
579
+ raise ValueError("amount must be greater than 0 for market orders")
580
+
581
+ if not self._api_creds():
582
+ raise RuntimeError("Polymarket API credentials missing; call create_or_derive_api_creds first")
583
+
584
+ private_key, maker_addr, signer_addr = self._get_signing_context()
585
+ owner_key = self._owner_key(owner)
586
+ order_type_str = (order_type or "FOK").upper()
587
+
588
+ if price is None or price <= 0:
589
+ price = await self._calculate_market_price(
590
+ token_id=token_id,
591
+ side=side,
592
+ amount=amount,
593
+ order_type=order_type_str,
594
+ )
595
+
596
+ signed_dict = await self._build_signed_market_order(
597
+ private_key=private_key,
598
+ maker_addr=maker_addr,
599
+ signer_addr=signer_addr,
600
+ token_id=token_id,
601
+ side=side,
602
+ amount=amount,
603
+ price=price,
604
+ tick_size=tick_size,
605
+ fee_rate_bps=fee_rate_bps,
606
+ taker=taker,
607
+ neg_risk=neg_risk,
608
+ nonce=nonce,
609
+ )
610
+
611
+ payload = {
612
+ "order": signed_dict,
613
+ "owner": owner_key,
614
+ "orderType": order_type_str,
615
+ }
616
+ return await self._signed_request_via_session("POST", "/order", payload)
617
+
618
+ async def _calculate_market_price(
619
+ self,
620
+ *,
621
+ token_id: str,
622
+ side: str,
623
+ amount: float,
624
+ order_type: str,
625
+ ) -> float:
626
+ side_flag = side.upper()
627
+ if side_flag not in {"BUY", "SELL"}:
628
+ raise ValueError("side must be 'BUY' or 'SELL'")
629
+ if amount <= 0:
630
+ raise ValueError("amount must be greater than 0 for market pricing")
631
+
632
+ book = await self.get_order_book(token_id)
633
+ if not isinstance(book, Mapping):
634
+ raise RuntimeError("Polymarket order book unavailable for market order")
635
+
636
+ key = "asks" if side_flag == "BUY" else "bids"
637
+ raw_levels = book.get(key) or []
638
+ levels: list[tuple[float, float]] = []
639
+ for lvl in raw_levels:
640
+ try:
641
+ price = float(lvl.get("price"))
642
+ size = float(lvl.get("size"))
643
+ except (TypeError, ValueError):
644
+ continue
645
+ if price is None or size is None:
646
+ continue
647
+ levels.append((price, size))
648
+
649
+ if not levels:
650
+ raise RuntimeError(f"Polymarket market order has no {key} liquidity")
651
+
652
+ total = 0.0
653
+ if side_flag == "BUY":
654
+ for price, size in reversed(levels):
655
+ total += price * size
656
+ if total >= amount:
657
+ return price
658
+ else:
659
+ for price, size in reversed(levels):
660
+ total += size
661
+ if total >= amount:
662
+ return price
663
+
664
+ if (order_type or "FOK").upper() == "FOK":
665
+ raise RuntimeError("Polymarket market order exceeds available liquidity")
666
+
667
+ return levels[0][0]
668
+
555
669
  async def _signed_request_via_session(
556
670
  self, method: str, path: str, body: Mapping[str, Any] | list[Any] | None
557
671
  ) -> Any:
@@ -686,6 +800,76 @@ class Polymarket:
686
800
  },
687
801
  )
688
802
 
803
+ async def _build_signed_market_order(
804
+ self,
805
+ *,
806
+ private_key: str,
807
+ maker_addr: str,
808
+ signer_addr: str,
809
+ token_id: str,
810
+ side: str,
811
+ amount: float,
812
+ price: float,
813
+ tick_size: str | float | None,
814
+ fee_rate_bps: int | None,
815
+ taker: str,
816
+ neg_risk: bool,
817
+ nonce: int | None,
818
+ ) -> dict[str, Any]:
819
+ side = side.upper()
820
+ tick = await self._resolve_tick_size(token_id, tick_size)
821
+ fee_bps = await self._resolve_fee_rate(token_id, fee_rate_bps)
822
+
823
+ price_d, size_d, amt_d = self._rounding_for_tick(tick)
824
+ price = float(self._round_normal(price, price_d))
825
+ if price <= 0:
826
+ raise ValueError("market price must be positive")
827
+
828
+ amt = float(amount)
829
+ if amt <= 0:
830
+ raise ValueError("amount must be greater than 0")
831
+
832
+ maker_amt_raw = self._round_down(amt, size_d)
833
+ if maker_amt_raw <= 0:
834
+ raise ValueError("amount too small for current tick size")
835
+
836
+ if side == "BUY":
837
+ taker_amt_raw = maker_amt_raw / price
838
+ elif side == "SELL":
839
+ taker_amt_raw = maker_amt_raw * price
840
+ else:
841
+ raise ValueError("side must be 'BUY' or 'SELL'")
842
+
843
+ if self._decimal_places(taker_amt_raw) > amt_d:
844
+ tmp = self._round_up(taker_amt_raw, amt_d + 4)
845
+ taker_amt_raw = tmp if self._decimal_places(tmp) <= amt_d else self._round_down(tmp, amt_d)
846
+
847
+ maker_amount = self._to_token_decimals(maker_amt_raw)
848
+ taker_amount = self._to_token_decimals(taker_amt_raw)
849
+
850
+ contract = self._contracts(self.chain_id, neg_risk)
851
+ side_flag = 0 if side == "BUY" else 1
852
+ sig_type = int(self.signature_type)
853
+
854
+ return Auth.sign_polymarket_order(
855
+ private_key=private_key,
856
+ chain_id=self.chain_id,
857
+ exchange_address=contract["exchange"],
858
+ order={
859
+ "maker": maker_addr,
860
+ "signer": signer_addr,
861
+ "taker": taker or ZERO_ADDRESS,
862
+ "tokenId": str(token_id),
863
+ "makerAmount": int(maker_amount),
864
+ "takerAmount": int(taker_amount),
865
+ "expiration": 0,
866
+ "nonce": int(nonce or 0),
867
+ "feeRateBps": int(fee_bps or 0),
868
+ "side": side_flag,
869
+ "signatureType": sig_type,
870
+ },
871
+ )
872
+
689
873
  async def _resolve_tick_size(self, token_id: str, tick_size: str | float | None) -> str:
690
874
  if tick_size is not None:
691
875
  return str(tick_size)
@@ -878,6 +1062,7 @@ class Polymarket:
878
1062
 
879
1063
  async def get_trades(self, params: Mapping[str, Any] | None = None) -> list[Any]:
880
1064
  return await self._paginate("/data/trades", params)
1065
+
881
1066
 
882
1067
  async def get_notifications(self, signature_type: int | None = None) -> Any:
883
1068
  sig = signature_type if signature_type is not None else self.signature_type
@@ -889,12 +1074,30 @@ class Polymarket:
889
1074
  return await self._rest("DELETE", "/notifications", params=params)
890
1075
 
891
1076
  async def get_balance_allowance(self, **params: Any) -> Any:
892
- return await self._rest("GET", "/balance-allowance", params=params or None)
1077
+ query = dict(params or {})
1078
+ query.setdefault("signature_type", self.signature_type)
1079
+ return await self._rest("GET", "/balance-allowance", params=query or None)
893
1080
 
894
1081
  async def update_balance_allowance(self, **params: Any) -> Any:
895
- return await self._rest("POST", "/balance-allowance/update", json=params or None)
896
-
897
- async def get_usdc(
1082
+ body = dict(params or {})
1083
+ body.setdefault("signature_type", self.signature_type)
1084
+ return await self._rest("POST", "/balance-allowance/update", json=body or None)
1085
+
1086
+ async def get_usdc(self):
1087
+ data = await self.get_balance_allowance(asset_type='COLLATERAL')
1088
+ balance = float(data.get('balance', 0.0))
1089
+ if balance > 0:
1090
+ balance = balance / 1e6
1091
+ return balance
1092
+
1093
+ async def get_position(self, token_id: str) -> Any:
1094
+ data = await self.get_balance_allowance(asset_type='CONDITIONAL', token_id=token_id)
1095
+ position = float(data.get('balance', 0.0))
1096
+ if position > 0:
1097
+ position = position / 1e6
1098
+ return position
1099
+
1100
+ async def get_usdc_web3(
898
1101
  self,
899
1102
  wallet: str = None,
900
1103
  rpc_urls: Sequence[str] | None = None,
@@ -945,7 +945,7 @@ wheels = [
945
945
 
946
946
  [[package]]
947
947
  name = "hyperquant"
948
- version = "1.31"
948
+ version = "1.33"
949
949
  source = { editable = "." }
950
950
  dependencies = [
951
951
  { name = "aiohttp" },
File without changes
File without changes
File without changes