vnpy_okx 2025.11.1__tar.gz → 2025.11.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vnpy_okx
3
- Version: 2025.11.1
3
+ Version: 2025.11.8
4
4
  Summary: OKX trading gateway for VeighNa.
5
5
  Project-URL: Homepage, https://www.github.com/veighna-global
6
6
  Project-URL: Source, https://www.github.com/veighna-global
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
33
33
  </p>
34
34
 
35
35
  <p align="center">
36
- <img src ="https://img.shields.io/badge/version-2025.11.01-blueviolet.svg"/>
36
+ <img src ="https://img.shields.io/badge/version-2025.11.08-blueviolet.svg"/>
37
37
  <img src ="https://img.shields.io/badge/platform-windows|linux|macos-yellow.svg"/>
38
38
  <img src ="https://img.shields.io/badge/python-3.10|3.11|3.12|3.13-blue.svg" />
39
39
  <img src ="https://img.shields.io/github/license/veighna-global/vnpy_okx.svg?color=orange"/>
@@ -5,7 +5,7 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <img src ="https://img.shields.io/badge/version-2025.11.01-blueviolet.svg"/>
8
+ <img src ="https://img.shields.io/badge/version-2025.11.08-blueviolet.svg"/>
9
9
  <img src ="https://img.shields.io/badge/platform-windows|linux|macos-yellow.svg"/>
10
10
  <img src ="https://img.shields.io/badge/python-3.10|3.11|3.12|3.13-blue.svg" />
11
11
  <img src ="https://img.shields.io/github/license/veighna-global/vnpy_okx.svg?color=orange"/>
@@ -23,7 +23,7 @@
23
23
  from .okx_gateway import OkxGateway
24
24
 
25
25
 
26
- __version__ = "2025.11.01"
26
+ __version__ = "2025.11.08"
27
27
 
28
28
 
29
29
  __all__ = ["OkxGateway"]
@@ -8,6 +8,7 @@ from datetime import datetime
8
8
  from urllib.parse import urlencode
9
9
  from types import TracebackType
10
10
  from collections.abc import Callable
11
+ from time import sleep
11
12
 
12
13
  from vnpy.event import EventEngine, Event, EVENT_TIMER
13
14
  from vnpy.trader.constant import (
@@ -47,12 +48,6 @@ REAL_PUBLIC_HOST: str = "wss://ws.okx.com:8443/ws/v5/public"
47
48
  REAL_PRIVATE_HOST: str = "wss://ws.okx.com:8443/ws/v5/private"
48
49
  REAL_BUSINESS_HOST: str = "wss://ws.okx.com:8443/ws/v5/business"
49
50
 
50
- # AWS server hosts
51
- AWS_REST_HOST: str = "https://aws.okx.com"
52
- AWS_PUBLIC_HOST: str = "wss://wsaws.okx.com:8443/ws/v5/public"
53
- AWS_PRIVATE_HOST: str = "wss://wsaws.okx.com:8443/ws/v5/private"
54
- AWS_BUSINESS_HOST: str = "wss://wsaws.okx.com:8443/ws/v5/business"
55
-
56
51
  # Demo server hosts
57
52
  DEMO_REST_HOST: str = "https://www.okx.com"
58
53
  DEMO_PUBLIC_HOST: str = "wss://wspap.okx.com:8443/ws/v5/public"
@@ -113,7 +108,7 @@ class OkxGateway(BaseGateway):
113
108
  "API Key": "",
114
109
  "Secret Key": "",
115
110
  "Passphrase": "",
116
- "Server": ["REAL", "AWS", "DEMO"],
111
+ "Server": ["REAL", "DEMO"],
117
112
  "Proxy Host": "",
118
113
  "Proxy Port": 0,
119
114
  "Spread Trading": ["False", "True"],
@@ -152,6 +147,8 @@ class OkxGateway(BaseGateway):
152
147
  self.ping_count: int = 0
153
148
  self.ping_interval: int = 20
154
149
 
150
+ self.subscribed_symbols: set[str] = set()
151
+
155
152
  def connect(self, setting: dict) -> None:
156
153
  """
157
154
  Start server connections.
@@ -218,11 +215,18 @@ class OkxGateway(BaseGateway):
218
215
  Parameters:
219
216
  req: Subscription request object containing symbol information
220
217
  """
218
+ # Check if symbol exists in contract map
221
219
  contract: ContractData | None = self.symbol_contract_map.get(req.symbol, None)
222
220
  if not contract:
223
221
  self.write_log(f"Failed to subscribe data, symbol not found: {req.symbol}")
224
222
  return
225
223
 
224
+ # Filter duplicate subscription
225
+ if req.vt_symbol in self.subscribed_symbols:
226
+ return
227
+ self.subscribed_symbols.add(req.vt_symbol)
228
+
229
+ # Send request to corresponding API
226
230
  if contract.product == Product.SPREAD:
227
231
  self.business_api.subscribe(req)
228
232
  else:
@@ -557,7 +561,7 @@ class RestApi(RestClient):
557
561
  key: API Key for authentication
558
562
  secret: API Secret for request signing
559
563
  passphrase: API Passphrase for authentication
560
- server: Server type ("REAL", "AWS", or "DEMO")
564
+ server: Server type ("REAL" or "DEMO")
561
565
  proxy_host: Proxy server hostname or IP
562
566
  proxy_port: Proxy server port
563
567
  spread_trading: Whether to enable spread trading
@@ -573,7 +577,6 @@ class RestApi(RestClient):
573
577
 
574
578
  server_hosts: dict[str, str] = {
575
579
  "REAL": REAL_REST_HOST,
576
- "AWS": AWS_REST_HOST,
577
580
  "DEMO": DEMO_REST_HOST,
578
581
  }
579
582
 
@@ -880,6 +883,9 @@ class RestApi(RestClient):
880
883
 
881
884
  # Loop until no more data or request fails
882
885
  while True:
886
+ # Add small delay to avoid rate limit
887
+ sleep(0.1)
888
+
883
889
  # Create query params
884
890
  params: dict = {
885
891
  id_key: contract.name,
@@ -1089,7 +1095,10 @@ class WebsocketApi(WebsocketClient):
1089
1095
  def send_ping(self) -> None:
1090
1096
  """Send heartbeat ping to server"""
1091
1097
  if self.connected:
1092
- self.wsapp.send("ping")
1098
+ try:
1099
+ self.wsapp.send("ping")
1100
+ except Exception:
1101
+ pass
1093
1102
 
1094
1103
 
1095
1104
  class PublicApi(WebsocketApi):
@@ -1115,7 +1124,6 @@ class PublicApi(WebsocketApi):
1115
1124
 
1116
1125
  self.server_hosts: dict[str, str] = {
1117
1126
  "REAL": REAL_PUBLIC_HOST,
1118
- "AWS": AWS_PUBLIC_HOST,
1119
1127
  "DEMO": DEMO_PUBLIC_HOST,
1120
1128
  }
1121
1129
 
@@ -1275,7 +1283,6 @@ class PrivateApi(WebsocketApi):
1275
1283
 
1276
1284
  self.server_hosts: dict[str, str] = {
1277
1285
  "REAL": REAL_PRIVATE_HOST,
1278
- "AWS": AWS_PRIVATE_HOST,
1279
1286
  "DEMO": DEMO_PRIVATE_HOST,
1280
1287
  }
1281
1288
 
@@ -1299,7 +1306,7 @@ class PrivateApi(WebsocketApi):
1299
1306
  key: API Key for authentication
1300
1307
  secret: API Secret for request signing
1301
1308
  passphrase: API Passphrase for authentication
1302
- server: Server type ("REAL", "AWS", or "DEMO")
1309
+ server: Server type ("REAL" or "DEMO")
1303
1310
  proxy_host: Proxy server hostname or IP
1304
1311
  proxy_port: Proxy server port
1305
1312
  """
@@ -1701,7 +1708,6 @@ class BusinessApi(WebsocketApi):
1701
1708
 
1702
1709
  self.server_hosts: dict[str, str] = {
1703
1710
  "REAL": REAL_BUSINESS_HOST,
1704
- "AWS": AWS_BUSINESS_HOST,
1705
1711
  "DEMO": DEMO_BUSINESS_HOST,
1706
1712
  }
1707
1713
 
@@ -1725,7 +1731,7 @@ class BusinessApi(WebsocketApi):
1725
1731
  key: API Key for authentication
1726
1732
  secret: API Secret for request signing
1727
1733
  passphrase: API Passphrase for authentication
1728
- server: Server type ("REAL", "AWS", or "DEMO")
1734
+ server: Server type ("REAL" or "DEMO")
1729
1735
  proxy_host: Proxy server hostname or IP
1730
1736
  proxy_port: Proxy server port
1731
1737
  """
File without changes
File without changes