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.
- pfund_bybit-0.0.1/PKG-INFO +17 -0
- pfund_bybit-0.0.1/README.md +5 -0
- pfund_bybit-0.0.1/pyproject.toml +34 -0
- pfund_bybit-0.0.1/pyproject.toml.orig +31 -0
- pfund_bybit-0.0.1/src/pfund_bybit/__init__.py +5 -0
- pfund_bybit-0.0.1/src/pfund_bybit/adapter.py +143 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/__init__.py +8 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/__init__.py +12 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_base.py +473 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_inverse.py +21 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_linear.py +21 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_option.py +23 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/_ws_apis/ws_api_spot.py +23 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/account.py +23 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/adapter.py +73 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/balance.py +5 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/config.py +5 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/market.py +6 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/order.py +43 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/position.py +5 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/product.py +90 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/rest_api.py +193 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/signer.py +67 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/venue.py +500 -0
- pfund_bybit-0.0.1/src/pfund_bybit/bybit_DEPRECATED/ws_api.py +139 -0
- pfund_bybit-0.0.1/src/pfund_bybit/parser.py +177 -0
- pfund_bybit-0.0.1/src/pfund_bybit/rest_api.py +56 -0
- pfund_bybit-0.0.1/src/pfund_bybit/typing.py +10 -0
- pfund_bybit-0.0.1/src/pfund_bybit/venue.py +54 -0
- 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,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,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,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
|
+
]
|