pfund-bybit 0.0.1__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. pfund_bybit-0.0.1/PKG-INFO +17 -0
  2. pfund_bybit-0.0.1/README.md +5 -0
  3. pfund_bybit-0.0.1/pyproject.toml +34 -0
  4. pfund_bybit-0.0.1/pyproject.toml.orig +31 -0
  5. pfund_bybit-0.0.1/src/pfund_bybit/__init__.py +5 -0
  6. pfund_bybit-0.0.1/src/pfund_bybit/adapter.py +143 -0
  7. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/__init__.py +8 -0
  8. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/__init__.py +12 -0
  9. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_base.py +473 -0
  10. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_inverse.py +21 -0
  11. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_linear.py +21 -0
  12. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_option.py +23 -0
  13. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_spot.py +23 -0
  14. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/account.py +23 -0
  15. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/adapter.py +73 -0
  16. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/balance.py +5 -0
  17. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/config.py +5 -0
  18. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/market.py +6 -0
  19. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/order.py +43 -0
  20. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/position.py +5 -0
  21. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/product.py +90 -0
  22. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/rest_api.py +193 -0
  23. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/signer.py +67 -0
  24. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/venue.py +500 -0
  25. pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/ws_api.py +139 -0
  26. pfund_bybit-0.0.1/src/pfund_bybit/parser.py +177 -0
  27. pfund_bybit-0.0.1/src/pfund_bybit/rest_api.py +56 -0
  28. pfund_bybit-0.0.1/src/pfund_bybit/typing.py +10 -0
  29. pfund_bybit-0.0.1/src/pfund_bybit/venue.py +54 -0
  30. pfund_bybit-0.0.1/src/pfund_bybit/ws_api.py +234 -0
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.3
2
+ Name: pfund-bybit
3
+ Version: 0.0.1
4
+ Summary: Official Bybit trading venue plugin for `pfund`, can be used as a standalone Bybit trading API client built on pfund-blocks.
5
+ Author: softwareentrepreneer
6
+ Author-email: softwareentrepreneer <softwareentrepreneer+pfund-bybit@gmail.com>
7
+ Requires-Dist: pfund-blocks>=0.0.3
8
+ Requires-Dist: httpx2[http2]>=2.16.0
9
+ Requires-Dist: websockets>=16.1.1 ; sys_platform != 'emscripten'
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+
13
+ [pfund]: https://github.com/PFund-Software-Ltd/pfund
14
+ [Bybit]: https://bybit.com/
15
+
16
+ # pfund-bybit
17
+ Official [Bybit] trading venue plugin for [pfund], can be used as a standalone Bybit trading API client built on pfund-blocks.
@@ -0,0 +1,5 @@
1
+ [pfund]: https://github.com/PFund-Software-Ltd/pfund
2
+ [Bybit]: https://bybit.com/
3
+
4
+ # pfund-bybit
5
+ Official [Bybit] trading venue plugin for [pfund], can be used as a standalone Bybit trading API client built on pfund-blocks.
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "pfund-bybit"
3
+ version = "0.0.1"
4
+ description = "Official Bybit trading venue plugin for `pfund`, can be used as a standalone Bybit trading API client built on pfund-blocks."
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "pfund-blocks>=0.0.3",
9
+ "httpx2[http2]>=2.16.0",
10
+ "websockets>=16.1.1 ; sys_platform != 'emscripten'",
11
+ ]
12
+
13
+ [[project.authors]]
14
+ name = "softwareentrepreneer"
15
+ email = "softwareentrepreneer+pfund-bybit@gmail.com"
16
+
17
+ [project.entry-points."pfund.venues"]
18
+ bybit = "pfund_bybit:Bybit"
19
+
20
+ [tool.uv]
21
+ exclude-newer = "0 days"
22
+
23
+ [tool.uv.exclude-newer-package]
24
+ uv_build = false
25
+ pfund-blocks = false
26
+
27
+ [tool.pytest]
28
+ strict_markers = true
29
+ addopts = ["--import-mode=importlib"]
30
+ testpaths = ["tests"]
31
+
32
+ [build-system]
33
+ requires = ["uv_build>=0.13.5,<0.14.0"]
34
+ build-backend = "uv_build"
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "pfund-bybit"
3
+ version = "0.0.1"
4
+ description = "Official Bybit trading venue plugin for `pfund`, can be used as a standalone Bybit trading API client built on pfund-blocks."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "softwareentrepreneer", email = "softwareentrepreneer+pfund-bybit@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "pfund-blocks>=0.0.3",
12
+ "httpx2[http2]>=2.16.0",
13
+ "websockets>=16.1.1 ; sys_platform != 'emscripten'",
14
+ ]
15
+
16
+ [project.entry-points."pfund.venues"]
17
+ bybit = "pfund_bybit:Bybit"
18
+
19
+ [tool.uv]
20
+ # FIXME: set it back to "14 days" when the package is stable
21
+ exclude-newer = "0 days"
22
+ exclude-newer-package = { uv_build = false, pfund-blocks = false }
23
+
24
+ [build-system]
25
+ requires = ["uv_build>=0.13.5,<0.14.0"]
26
+ build-backend = "uv_build"
27
+
28
+ [tool.pytest]
29
+ strict_markers = true
30
+ addopts = ["--import-mode=importlib"]
31
+ testpaths = ["tests"]
@@ -0,0 +1,5 @@
1
+ from pfund_bybit.venue import Bybit
2
+
3
+ __all__ = [
4
+ "Bybit",
5
+ ]
@@ -0,0 +1,143 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, cast
4
+
5
+ if TYPE_CHECKING:
6
+ from pfund_blocks.entities.products.future import FutureProduct
7
+ from pfund_blocks.entities.products.option import OptionProduct
8
+ from pfund_blocks.entities.products.product_base import BaseProduct
9
+
10
+ from pfund_blocks.adapters.adapter_base import ExternalValue
11
+ from pfund_blocks.adapters.adapter_venue import (
12
+ OrderStatusRepr,
13
+ VenueAdapter,
14
+ )
15
+ from pfund_blocks.entities.products.product_type import ProductType
16
+ from pfund_blocks.enums import (
17
+ Channel,
18
+ MarginMode,
19
+ OptionType,
20
+ OrderType,
21
+ Side,
22
+ )
23
+ from pfund_blocks.resolution import Resolution
24
+
25
+
26
+ # NOTE: the defaults are not validated by pydantic, so the keys are created as their types directly, e.g. ProductType, Resolution
27
+ # NOTE: pydantic copies mutable defaults per instance, ruff just doesn't see BybitAdapter as a pydantic model
28
+ class BybitAdapter(VenueAdapter):
29
+ """Maps pfund's internal values to Bybit's, and derives Bybit's product symbols and names.
30
+
31
+ Usage:
32
+ Product.model_validate({...}, context={"adapter": adapter}) # product with Bybit's symbol, e.g. BTCPERP
33
+ """
34
+
35
+ # from '/v5/market/instruments-info'
36
+ product_type: dict[ProductType, ExternalValue] = { # noqa: RUF012
37
+ ProductType.model_validate("PERPETUAL"): "LinearPerpetual",
38
+ ProductType.model_validate("INVERSE-PERPETUAL"): "InversePerpetual",
39
+ ProductType.model_validate("FUTURE"): "LinearFutures",
40
+ ProductType.model_validate("INVERSE-FUTURE"): "InverseFutures",
41
+ }
42
+ side: dict[Side, ExternalValue] = { # noqa: RUF012
43
+ Side.BUY: "Buy",
44
+ Side.SELL: "Sell",
45
+ }
46
+ margin_mode: dict[MarginMode, ExternalValue] = { # noqa: RUF012
47
+ MarginMode.ISOLATED: "ISOLATED_MARGIN",
48
+ MarginMode.CROSS: "REGULAR_MARGIN",
49
+ MarginMode.PORTFOLIO: "PORTFOLIO_MARGIN",
50
+ }
51
+ order_status: dict[OrderStatusRepr, ExternalValue] = { # noqa: RUF012
52
+ "S---": "Submitted",
53
+ "R---": "Rejected",
54
+ "A---": "New",
55
+ "AP--": "PartiallyFilled",
56
+ "CPC-": "PartiallyFilledCanceled",
57
+ "CF--": "Filled",
58
+ "C-C-": "Cancelled",
59
+ }
60
+ order_type: dict[OrderType, ExternalValue] = { # noqa: RUF012
61
+ OrderType.LIMIT: "Limit",
62
+ OrderType.MARKET: "Market",
63
+ }
64
+ option_type: dict[OptionType, ExternalValue] = { # noqa: RUF012
65
+ OptionType.CALL: "Call",
66
+ OptionType.PUT: "Put",
67
+ }
68
+ channel: dict[Channel, ExternalValue] = { # noqa: RUF012
69
+ Channel.orderbook: "orderbook",
70
+ Channel.tradebook: "publicTrade",
71
+ Channel.candlestick: "kline",
72
+ Channel.balance: "wallet",
73
+ Channel.position: "position",
74
+ Channel.order: "order",
75
+ Channel.trade: "execution",
76
+ }
77
+ channel_resolution: dict[Resolution, ExternalValue] = { # noqa: RUF012
78
+ Resolution("1m"): "1",
79
+ Resolution("3m"): "3",
80
+ Resolution("5m"): "5",
81
+ Resolution("15m"): "15",
82
+ Resolution("30m"): "30",
83
+ Resolution("60m"): "60",
84
+ Resolution("120m"): "120",
85
+ Resolution("240m"): "240",
86
+ Resolution("360m"): "360",
87
+ Resolution("720m"): "720",
88
+ Resolution("1d"): "D",
89
+ Resolution("1w"): "W",
90
+ Resolution("1mo"): "M",
91
+ }
92
+
93
+ def create_symbol(self, product: BaseProduct) -> str:
94
+ # e = external, i.e. Bybit's
95
+ ebase_asset = self.to_source(product.base_asset, group="asset")
96
+ equote_asset = self.to_source(product.quote_asset, group="asset")
97
+ # e.g. BTCUSDT
98
+ if product.is_crypto_spot():
99
+ return ebase_asset + equote_asset
100
+ if product.is_perpetual():
101
+ # e.g. BTCUSD
102
+ if product.is_inverse():
103
+ self._require_quote_asset_as_usd(product, equote_asset)
104
+ return ebase_asset + equote_asset
105
+ # e.g. BTCPERP for USDC, BTCUSDT for USDT
106
+ if equote_asset == "USDC":
107
+ return ebase_asset + "PERP"
108
+ return ebase_asset + equote_asset
109
+ if product.is_future():
110
+ future = cast("FutureProduct", product)
111
+ # e.g. BTCUSDH25
112
+ if product.is_inverse():
113
+ self._require_quote_asset_as_usd(product, equote_asset)
114
+ return ebase_asset + equote_asset + future.contract_code
115
+ expiration = f"{future.expiration:%d%b%y}".upper()
116
+ # e.g. BTC-13DEC24
117
+ if equote_asset == "USDC":
118
+ return f"{ebase_asset}-{expiration}"
119
+ # e.g. BTCUSDT-22AUG25
120
+ if equote_asset == "USDT":
121
+ return f"{ebase_asset}{equote_asset}-{expiration}"
122
+ raise ValueError(
123
+ f"only USDC and USDT futures are supported, not {equote_asset} in {product.basis}"
124
+ )
125
+ if product.is_option():
126
+ option = cast("OptionProduct", product)
127
+ # e.g. BTC-4NOV26-77000-P-USDT, the day has no leading zero
128
+ expiration = f"{option.expiration.day}{option.expiration:%b%y}".upper()
129
+ return f"{ebase_asset}-{expiration}-{option.strike_price}-{option.option_type[0]}-{equote_asset}"
130
+ raise ValueError(f"{product.basis} is not supported by Bybit")
131
+
132
+ @staticmethod
133
+ def _require_quote_asset_as_usd(product: BaseProduct, equote_asset: str) -> None:
134
+ if equote_asset != "USD":
135
+ raise ValueError(
136
+ f"only USD-denominated inverse contracts are supported, did you mean {product.base_asset}_USD_{product.product_type}?"
137
+ )
138
+
139
+ def create_name(self, product: BaseProduct) -> str:
140
+ # NOTE: spots and perpetuals share symbols (e.g. BTCUSDT), so the basis is used to make their names unique
141
+ if product.is_crypto_spot() or product.is_perpetual():
142
+ return f"{product.source}_{product.basis}"
143
+ return super().create_name(product)
@@ -0,0 +1,8 @@
1
+ from pfund.venues.bybit.venue import Bybit
2
+ from pfund.venues.bybit.config import BybitConfig
3
+
4
+
5
+ __all__ = [
6
+ "Bybit",
7
+ "BybitConfig",
8
+ ]
@@ -0,0 +1,12 @@
1
+ from pfund.venues.bybit._ws_apis.ws_api_linear import BybitLinearWebSocketAPI
2
+ from pfund.venues.bybit._ws_apis.ws_api_inverse import BybitInverseWebSocketAPI
3
+ from pfund.venues.bybit._ws_apis.ws_api_option import BybitOptionWebSocketAPI
4
+ from pfund.venues.bybit._ws_apis.ws_api_spot import BybitSpotWebSocketAPI
5
+
6
+
7
+ __all__ = [
8
+ "BybitLinearWebSocketAPI",
9
+ "BybitInverseWebSocketAPI",
10
+ "BybitOptionWebSocketAPI",
11
+ "BybitSpotWebSocketAPI",
12
+ ]