webull-openapi-python-sdk 1.0.9__py3-none-any.whl → 1.1.0__py3-none-any.whl

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 (33) hide show
  1. samples/data/data_client_event.py +52 -0
  2. samples/data/data_streaming_client_event.py +66 -0
  3. samples/trade/trade_client_v3.py +64 -1
  4. samples/trade/trade_client_v3_event.py +102 -0
  5. samples/trade/trade_event_client.py +4 -1
  6. webull/__init__.py +1 -1
  7. webull/core/__init__.py +1 -1
  8. webull/data/__init__.py +1 -1
  9. webull/data/common/category.py +1 -0
  10. webull/data/data_client.py +2 -0
  11. webull/data/data_streaming_client.py +6 -1
  12. webull/data/quotes/event_market_data.py +50 -0
  13. webull/data/quotes/instrument.py +43 -0
  14. webull/data/quotes/subscribe/ask_bid_result.py +9 -3
  15. webull/data/quotes/subscribe/event_depth_decoder.py +27 -0
  16. webull/data/quotes/subscribe/event_depth_result.py +46 -0
  17. webull/data/quotes/subscribe/event_snapshot_decoder.py +29 -0
  18. webull/data/quotes/subscribe/event_snapshot_result.py +85 -0
  19. webull/data/quotes/subscribe/message_pb2.py +25 -19
  20. webull/data/quotes/subscribe/payload_type.py +3 -1
  21. webull/data/request/get_event_depth_request.py +32 -0
  22. webull/data/request/get_event_instrument_request.py +33 -0
  23. webull/data/request/get_event_series_request.py +30 -0
  24. webull/data/request/get_event_snapshot_request.py +31 -0
  25. webull/trade/__init__.py +1 -1
  26. webull/trade/events/types.py +1 -1
  27. webull/trade/trade_events_client.py +1 -1
  28. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/METADATA +1 -1
  29. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/RECORD +33 -21
  30. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/WHEEL +1 -1
  31. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/licenses/LICENSE +0 -0
  32. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/licenses/NOTICE +0 -0
  33. {webull_openapi_python_sdk-1.0.9.dist-info → webull_openapi_python_sdk-1.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,52 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.data.common.category import Category
18
+ from webull.core.client import ApiClient
19
+ from webull.data.data_client import DataClient
20
+
21
+ optional_api_endpoint = "<api_endpoint>"
22
+ your_app_key = "<your_app_key>"
23
+ your_app_secret = "<your_app_secret>"
24
+ region_id = "<region_id>"
25
+ # The token_dir parameter can be used to specify the directory for storing the 2FA token. Both absolute and relative paths are supported and this option has the highest priority.
26
+ # Alternatively, the storage directory can be configured via an environment variable with the key WEBULL_OPENAPI_TOKEN_DIR, which also supports both absolute and relative paths.
27
+ # If neither is specified, the default configuration will be used, and the token will be stored at conf/token.txt under the current working directory.
28
+ # token_dir = "<your_token_dir>"
29
+ # api_client.set_token_dir(token_dir)
30
+
31
+ api_client = ApiClient(your_app_key, your_app_secret, region_id)
32
+ api_client.add_endpoint(region_id, optional_api_endpoint)
33
+
34
+
35
+ if __name__ == '__main__':
36
+ data_client = DataClient(api_client)
37
+
38
+ res = data_client.instrument.get_event_series("ECONOMICS")
39
+ if res.status_code == 200:
40
+ print('get_event_series:', res.json())
41
+
42
+ res = data_client.instrument.get_event_instrument("KXGDP")
43
+ if res.status_code == 200:
44
+ print('get_event_instrument:', res.json())
45
+
46
+ res = data_client.event_market_data.get_event_snapshot("KXRATECUTCOUNT-25DEC31-T10", Category.US_EVENT.name)
47
+ if res.status_code == 200:
48
+ print('get_event_snapshot:', res.json())
49
+
50
+ res = data_client.event_market_data.get_event_depth("KXRATECUTCOUNT-25DEC31-T10", Category.US_EVENT.name)
51
+ if res.status_code == 200:
52
+ print('get_event_depth:', res.json())
@@ -0,0 +1,66 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ import logging
18
+ import uuid
19
+ from logging.handlers import TimedRotatingFileHandler
20
+
21
+ from webull.data.common.category import Category
22
+ from webull.data.common.subscribe_type import SubscribeType
23
+ from webull.data.data_streaming_client import DataStreamingClient
24
+
25
+ your_app_key = "</your_app_key>"
26
+ your_app_secret = "</your_app_secret>"
27
+ optional_api_endpoint = "</optional_quotes_endpoint>"
28
+ optional_quotes_endpoint = "</optional_quotes_endpoint>"
29
+ region_id = '<region_id>'
30
+ # The token_dir parameter can be used to specify the directory for storing the 2FA token. Both absolute and relative paths are supported and this option has the highest priority.
31
+ # Alternatively, the storage directory can be configured via an environment variable with the key WEBULL_OPENAPI_TOKEN_DIR, which also supports both absolute and relative paths.
32
+ # If neither is specified, the default configuration will be used, and the token will be stored at conf/token.txt under the current working directory.
33
+ # token_dir = "<your_token_dir>"
34
+ # data_streaming_client.set_token_dir(token_dir)
35
+
36
+ session_id = uuid.uuid4().hex
37
+ data_streaming_client = DataStreamingClient(your_app_key, your_app_secret, region_id, session_id,
38
+ http_host=optional_api_endpoint,
39
+ mqtt_host=optional_quotes_endpoint)
40
+
41
+ if __name__ == '__main__':
42
+ def my_connect_success_func(client, api_client, quotes_session_id):
43
+ print("connect success with session_id:%s" % quotes_session_id)
44
+ # subscribe
45
+ symbols = ['KXNHLGAME-26JAN21ANACOL-ANA', 'KXNBAGAME-26JAN20LACCHI-LAC']
46
+ sub_types = [SubscribeType.QUOTE.name, SubscribeType.SNAPSHOT.name]
47
+ client.subscribe(symbols, Category.US_EVENT.name, sub_types)
48
+
49
+ def my_quotes_message_func(client, topic, quotes):
50
+ print("receive message: topic:%s, quotes:%s" % (topic, quotes))
51
+
52
+ def my_subscribe_success_func(client, api_client, quotes_session_id):
53
+ print("subscribe success with session_id:%s" % quotes_session_id)
54
+
55
+
56
+ # set connect success callback func
57
+ data_streaming_client.on_connect_success = my_connect_success_func
58
+ # set quotes receiving callback func
59
+ data_streaming_client.on_quotes_message = my_quotes_message_func
60
+ # set subscribe success callback func
61
+ data_streaming_client.on_subscribe_success = my_subscribe_success_func
62
+
63
+ # the sync mode, blocking in current thread
64
+ data_streaming_client.connect_and_loop_forever()
65
+
66
+
@@ -454,4 +454,67 @@ if __name__ == '__main__':
454
454
  # get futures order history
455
455
  res = trade_client.order_v3.get_order_history(account_id, page_size=10)
456
456
  if res.status_code == 200:
457
- print('get order history res:', res.json())
457
+ print('get order history res:', res.json())
458
+
459
+ # ============================================================
460
+ # Algo Order Example
461
+ # ============================================================
462
+ alog_client_order_id = uuid.uuid4().hex
463
+ print('client order id:', alog_client_order_id)
464
+ new_normal_equity_orders = [
465
+ {
466
+ "combo_type": "NORMAL",
467
+ "client_order_id": alog_client_order_id,
468
+ "symbol": "AAPL",
469
+ "instrument_type": "EQUITY",
470
+ "market": "US",
471
+ "order_type": "LIMIT",
472
+ "limit_price": "188",
473
+ "quantity": "1",
474
+ "support_trading_session": "N",
475
+ "side": "BUY",
476
+ "time_in_force": "DAY",
477
+ "entrust_type": "QTY",
478
+ "algo_start_time": "16:00:00",
479
+ "algo_end_time": "23:00:00",
480
+ "target_vol_percent": "10",
481
+ "algo_type": "POV"
482
+ }
483
+ ]
484
+
485
+ res = trade_client.order_v3.preview_order(account_id, new_normal_equity_orders)
486
+ if res.status_code == 200:
487
+ print('preview algo order res:', res.json())
488
+
489
+ res = trade_client.order_v3.place_order(account_id, new_normal_equity_orders)
490
+ if res.status_code == 200:
491
+ print('place algo order res:', res.json())
492
+ sleep(3)
493
+
494
+ replace_normal_equity_orders = [
495
+ {
496
+ "client_order_id": alog_client_order_id,
497
+ "quantity": "100",
498
+ "limit_price": "200"
499
+ }
500
+ ]
501
+ res = trade_client.order_v3.replace_order(account_id, replace_normal_equity_orders)
502
+ if res.status_code == 200:
503
+ print('replace algo order res:', res.json())
504
+ sleep(3)
505
+
506
+ res = trade_client.order_v3.cancel_order(account_id, alog_client_order_id)
507
+ if res.status_code == 200:
508
+ print('cancel algo order res:', res.json())
509
+
510
+ res = trade_client.order_v3.get_order_open(account_id=account_id)
511
+ if res.status_code == 200:
512
+ print("order_open_res=" + json.dumps(res.json(), indent=4))
513
+
514
+ res = trade_client.order_v3.get_order_history(account_id)
515
+ if res.status_code == 200:
516
+ print('get order history res:', res.json())
517
+
518
+ res = trade_client.order_v3.get_order_detail(account_id, alog_client_order_id)
519
+ if res.status_code == 200:
520
+ print('get order detail res:', res.json())
@@ -0,0 +1,102 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import json
16
+ import uuid
17
+ from time import sleep
18
+
19
+ from webull.core.client import ApiClient
20
+ from webull.trade.trade_client import TradeClient
21
+
22
+ optional_api_endpoint = "<api_endpoint>"
23
+ your_app_key = "<your_app_key>"
24
+ your_app_secret = "<your_app_secret>"
25
+ region_id = "<region_id>"
26
+ account_id = "<your_account_id>"
27
+ # The token_dir parameter can be used to specify the directory for storing the 2FA token. Both absolute and relative paths are supported and this option has the highest priority.
28
+ # Alternatively, the storage directory can be configured via an environment variable with the key WEBULL_OPENAPI_TOKEN_DIR, which also supports both absolute and relative paths.
29
+ # If neither is specified, the default configuration will be used, and the token will be stored at conf/token.txt under the current working directory.
30
+ # token_dir = "<your_token_dir>"
31
+ # api_client.set_token_dir(token_dir)
32
+
33
+ api_client = ApiClient(your_app_key, your_app_secret, region_id)
34
+ api_client.add_endpoint(region_id, optional_api_endpoint)
35
+
36
+
37
+ if __name__ == '__main__':
38
+ trade_client = TradeClient(api_client)
39
+
40
+ res = trade_client.account_v2.get_account_list()
41
+ if res.status_code == 200:
42
+ print('get account list:', res.json())
43
+
44
+ res = trade_client.account_v2.get_account_balance(account_id)
45
+ if res.status_code == 200:
46
+ print('get account balance res:', res.json())
47
+
48
+ res = trade_client.account_v2.get_account_position(account_id)
49
+ if res.status_code == 200:
50
+ print('get account position res:', res.json())
51
+
52
+ # normal event order
53
+ normal_event_client_order_id = uuid.uuid4().hex
54
+ print('event client order id:', normal_event_client_order_id)
55
+ new_normal_event_orders = [
56
+ {
57
+ "combo_type": "NORMAL",
58
+ "client_order_id": normal_event_client_order_id,
59
+ "instrument_type": "EVENT",
60
+ "market": "US",
61
+ "symbol": "KXRATECUTCOUNT-25DEC31-T9",
62
+ "order_type": "LIMIT",
63
+ "entrust_type": "QTY",
64
+ "time_in_force": "DAY",
65
+ "side": "BUY",
66
+ "quantity": "1",
67
+ "limit_price": "0.1",
68
+ "event_outcome": "yes"
69
+ }
70
+ ]
71
+
72
+ res = trade_client.order_v3.preview_order(account_id, new_normal_event_orders)
73
+ if res.status_code == 200:
74
+ print('preview normal event order res:', res.json())
75
+
76
+ res = trade_client.order_v3.place_order(account_id, new_normal_event_orders)
77
+ if res.status_code == 200:
78
+ print('place normal event order res:', res.json())
79
+ sleep(3)
80
+
81
+ # normal event order replace
82
+ replace_normal_event_orders = [
83
+ {
84
+ "client_order_id": normal_event_client_order_id,
85
+ "quantity": "10",
86
+ "limit_price": "0.1"
87
+ }
88
+ ]
89
+ res = trade_client.order_v3.replace_order(account_id, replace_normal_event_orders)
90
+ if res.status_code == 200:
91
+ print('replace normal event order res:', res.json())
92
+ sleep(3)
93
+
94
+ # normal event order cancel
95
+ res = trade_client.order_v3.cancel_order(account_id, normal_event_client_order_id)
96
+ if res.status_code == 200:
97
+ print('cancel normal event order res:', res.json())
98
+
99
+ # get event order detail
100
+ res = trade_client.order_v3.get_order_detail(account_id, normal_event_client_order_id)
101
+ if res.status_code == 200:
102
+ print('get event order detail res:', res.json())
@@ -14,7 +14,8 @@
14
14
 
15
15
  import logging
16
16
 
17
- from webull.trade.events.types import ORDER_STATUS_CHANGED, EVENT_TYPE_ORDER
17
+ from webull.trade.events.types import ORDER_STATUS_CHANGED, EVENT_TYPE_ORDER, EVENT_TYPE_POSITION, \
18
+ POSITION_STATUS_CHANGED
18
19
  from webull.trade.trade_events_client import TradeEventsClient
19
20
 
20
21
  your_app_key = "<your_app_key>"
@@ -32,6 +33,8 @@ def my_on_events_message(event_type, subscribe_type, payload, raw_message):
32
33
  if EVENT_TYPE_ORDER == event_type and ORDER_STATUS_CHANGED == subscribe_type:
33
34
  print('----request_id:%s----' % payload['request_id'])
34
35
  print(payload)
36
+ if EVENT_TYPE_POSITION == event_type and POSITION_STATUS_CHANGED == subscribe_type:
37
+ print('event payload:%s' % payload)
35
38
 
36
39
  if __name__ == '__main__':
37
40
 
webull/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.0.9'
1
+ __version__ = '1.1.0'
webull/core/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = '1.0.9'
1
+ __version__ = '1.1.0'
2
2
 
3
3
  import logging
4
4
 
webull/data/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # coding=utf-8
2
2
 
3
- __version__ = '1.0.9'
3
+ __version__ = '1.1.0'
@@ -25,3 +25,4 @@ class Category(EasyEnum):
25
25
  CN_STOCK = (7, "CN STOCK")
26
26
  US_CRYPTO = (8, "US CRYPTO")
27
27
  US_FUTURES = (12, "US FUTURES")
28
+ US_EVENT = (13, "US EVENT")
@@ -19,6 +19,7 @@ import sys
19
19
 
20
20
  from webull.core.http.initializer.client_initializer import ClientInitializer
21
21
  from webull.data.quotes.crypto_market_data import CryptoMarketData
22
+ from webull.data.quotes.event_market_data import EventMarketData
22
23
  from webull.data.quotes.futures_market_data import FuturesMarketData
23
24
  from webull.data.quotes.instrument import Instrument
24
25
  from webull.data.quotes.market_data import MarketData
@@ -32,6 +33,7 @@ class DataClient:
32
33
  self.market_data = MarketData(api_client)
33
34
  self.crypto_market_data = CryptoMarketData(api_client)
34
35
  self.futures_market_data = FuturesMarketData(api_client)
36
+ self.event_market_data = EventMarketData(api_client)
35
37
 
36
38
  def _init_logger(self, api_client):
37
39
  # No logger configured, using default console and local file logging.
@@ -16,7 +16,10 @@
16
16
 
17
17
  from webull.data.internal.quotes_client import QuotesClient, LOG_ERR
18
18
  from webull.data.quotes.market_streaming_data import MarketDataStreaming
19
- from webull.data.quotes.subscribe.payload_type import PAYLOAD_TYPE_QUOTE, PAYLOAD_TYPE_SHAPSHOT, PAYLOAD_TYPE_TICK
19
+ from webull.data.quotes.subscribe.event_depth_decoder import EventDepthDecoder
20
+ from webull.data.quotes.subscribe.event_snapshot_decoder import EventSnapshotDecoder
21
+ from webull.data.quotes.subscribe.payload_type import PAYLOAD_TYPE_QUOTE, PAYLOAD_TYPE_SHAPSHOT, PAYLOAD_TYPE_TICK, \
22
+ PAYLOAD_TYPE_EVENT_SHAPSHOT, PAYLOAD_TYPE_EVENT_DEPTH
20
23
  from webull.data.quotes.subscribe.quote_decoder import QuoteDecoder
21
24
  from webull.data.quotes.subscribe.snapshot_decoder import SnapshotDecoder
22
25
  from webull.data.quotes.subscribe.tick_decoder import TickDecoder
@@ -39,6 +42,8 @@ class DataStreamingClient(QuotesClient):
39
42
  self.register_payload_decoder(PAYLOAD_TYPE_QUOTE, QuoteDecoder())
40
43
  self.register_payload_decoder(PAYLOAD_TYPE_SHAPSHOT, SnapshotDecoder())
41
44
  self.register_payload_decoder(PAYLOAD_TYPE_TICK, TickDecoder())
45
+ self.register_payload_decoder(PAYLOAD_TYPE_EVENT_DEPTH, EventDepthDecoder())
46
+ self.register_payload_decoder(PAYLOAD_TYPE_EVENT_SHAPSHOT, EventSnapshotDecoder())
42
47
 
43
48
  @property
44
49
  def on_connect_success(self):
@@ -0,0 +1,50 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from webull.data.common.category import Category
15
+ from webull.data.request.get_event_depth_request import GetEventDepthRequest
16
+ from webull.data.request.get_event_snapshot_request import GetEventSnapshotRequest
17
+
18
+ class EventMarketData:
19
+ def __init__(self, api_client):
20
+ self.client = api_client
21
+
22
+ def get_event_snapshot(self, symbols, category=Category.US_EVENT.name):
23
+ """
24
+ Get real-time market snapshot data for a event instrument. Price unit is based on usd_cent.
25
+
26
+ :param symbols: Symbol of the event market, supports JSON array format, multiple symbols separated by commas; maximum 100 symbols per query.
27
+ :param category: default is US_EVENT, currently only US_EVENT is supported.
28
+ """
29
+ snapshot_request = GetEventSnapshotRequest()
30
+ snapshot_request.set_symbols(symbols)
31
+ snapshot_request.set_category(category)
32
+ response = self.client.get_response(snapshot_request)
33
+ return response
34
+
35
+ def get_event_depth(self, symbol, category=Category.US_EVENT.name, depth=10):
36
+ """
37
+ Get the current order book for a specific event instrument.
38
+ The order book shows all active bid orders for both yes and no sides of a binary market.
39
+ It returns yes bids and no bids only (no asks are returned). Price unit is based on usd_cent.
40
+
41
+ :param symbol:Symbol of the event market.
42
+ :param category: default is US_EVENT, currently only US_EVENT is supported.
43
+ :param depth: Depth of buying and selling orders, default 10 levels, etc.
44
+ """
45
+ quote_request = GetEventDepthRequest()
46
+ quote_request.set_symbol(symbol)
47
+ quote_request.set_category(category)
48
+ quote_request.set_depth(depth)
49
+ response = self.client.get_response(quote_request)
50
+ return response
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  from webull.data.common.category import Category
15
+ from webull.data.request.get_event_instrument_request import GetEventInstrumentRequest
16
+ from webull.data.request.get_event_series_request import GetEventSeriesRequest
15
17
  from webull.data.request.get_instruments_request import GetInstrumentsRequest
16
18
  from webull.data.request.get_crypto_instruments_request import GetCryptoInstrumentsRequest
17
19
  from webull.data.request.get_futures_instruments_request import GetFuturesInstrumentsRequest
@@ -108,3 +110,44 @@ class Instrument:
108
110
  futures_instrument_request.set_contract_type(contract_type)
109
111
  response = self.client.get_response(futures_instrument_request)
110
112
  return response
113
+
114
+ def get_event_series(self, category, last_instrument_id=None, page_size=500):
115
+ """
116
+ Retrieve multiple series with specified filters.
117
+ A series represents a template for recurring events that follow the same format and rules (e.g., “Monthly Jobs Report” ).
118
+ This endpoint allows you to browse and discover available series templates by category.
119
+
120
+ :param category: The category which this series belongs to.Allowed values:
121
+ ECONOMICS, FINANCIALS, POLITICS, ENTERTAINMENT, SCIENCE_TECHNOLOGY,
122
+ CLIMATE_WEATHER, TRANSPORTATION, CRYPTO, SPORTS
123
+ :param last_instrument_id: Last series id for pagination.
124
+ :param page_size: Page size, default 500.
125
+ """
126
+
127
+ event_series_request = GetEventSeriesRequest()
128
+ event_series_request.set_category(category)
129
+ if last_instrument_id:
130
+ event_series_request.set_last_instrument_id(last_instrument_id)
131
+ event_series_request.set_page_size(page_size)
132
+ response = self.client.get_response(event_series_request)
133
+ return response
134
+
135
+ def get_event_instrument(self, series_symbol, expiration_date_after=None, last_instrument_id=None, page_size=500):
136
+ """
137
+ Retrieve profile information for event contract markets based on the series symbol.
138
+
139
+ :param series_symbol: Symbol that identifies this series.
140
+ :param expiration_date_after: Used to filter items whose expiration date is later than a specified date; the default selection is the current day (inclusive).
141
+ :param last_instrument_id: Last series id for pagination.
142
+ :param page_size: Page size, default 500.
143
+ """
144
+
145
+ event_instrument_request = GetEventInstrumentRequest()
146
+ event_instrument_request.set_series_symbol(series_symbol)
147
+ if expiration_date_after:
148
+ event_instrument_request.set_expiration_date_after(expiration_date_after)
149
+ if last_instrument_id:
150
+ event_instrument_request.set_last_instrument_id(last_instrument_id)
151
+ event_instrument_request.set_page_size(page_size)
152
+ response = self.client.get_response(event_instrument_request)
153
+ return response
@@ -22,11 +22,11 @@ class AskBidResult:
22
22
  self.price = Decimal(ask_bid.price) if ask_bid.price else None
23
23
  self.size = ask_bid.size
24
24
  self.order = []
25
- if ask_bid.order:
25
+ if hasattr(ask_bid, 'order') and ask_bid.order:
26
26
  for order in ask_bid.order:
27
27
  self.order.append(Order(order))
28
28
  self.broker = []
29
- if ask_bid.broker:
29
+ if hasattr(ask_bid, 'broker') and ask_bid.broker:
30
30
  for broker in ask_bid.broker:
31
31
  self.broker.append(Broker(broker))
32
32
 
@@ -43,7 +43,13 @@ class AskBidResult:
43
43
  return self.broker
44
44
 
45
45
  def __repr__(self):
46
- return "price:%s,size:%s,order:%s,broker:%s" % (self.price, self.size, self.order, self.broker)
46
+ result = f"price:{self.price},size:{self.size}"
47
+ # 可选字段
48
+ if self.order:
49
+ result += f",order:{str(self.order)}"
50
+ if self.broker:
51
+ result += f",broker:{str(self.broker)}"
52
+ return result
47
53
 
48
54
  def __str__(self):
49
55
  return self.__repr__()
@@ -0,0 +1,27 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # coding=utf-8
15
+
16
+ from webull.data.quotes.subscribe.message_pb2 import EventQuote
17
+ from webull.data.quotes.subscribe.event_depth_result import EventDepthResult
18
+ from webull.data.internal.quotes_payload_decoder import BaseQuotesPayloadDecoder
19
+
20
+ class EventDepthDecoder(BaseQuotesPayloadDecoder):
21
+ def __init__(self):
22
+ super().__init__()
23
+
24
+ def parse(self, payload):
25
+ eventQuote = EventQuote()
26
+ eventQuote.ParseFromString(payload)
27
+ return EventDepthResult(eventQuote)
@@ -0,0 +1,46 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.data.quotes.subscribe.basic_result import BasicResult
18
+ from webull.data.quotes.subscribe.ask_bid_result import AskBidResult
19
+
20
+
21
+ class EventDepthResult:
22
+ def __init__(self, pb_event_depth):
23
+ self.basic = BasicResult(pb_event_depth.basic)
24
+ self.yes_bids = []
25
+ if pb_event_depth.yes_bids:
26
+ for bid in pb_event_depth.yes_bids:
27
+ self.yes_bids.append(AskBidResult(bid))
28
+ self.no_bids = []
29
+ if pb_event_depth.no_bids:
30
+ for bid in pb_event_depth.no_bids:
31
+ self.no_bids.append(AskBidResult(bid))
32
+
33
+ def get_basic(self):
34
+ return self.basic
35
+
36
+ def get_yes_bids(self):
37
+ return self.yes_bids
38
+
39
+ def get_no_bids(self):
40
+ return self.no_bids
41
+
42
+ def __repr__(self):
43
+ return "basic: %s,yes_bids:%s,no_bids:%s" % (self.basic, self.yes_bids, self.no_bids)
44
+
45
+ def __str__(self):
46
+ return self.__repr__()
@@ -0,0 +1,29 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # coding=utf-8
15
+
16
+ from webull.data.quotes.subscribe.message_pb2 import EventSnapshot
17
+ from webull.data.quotes.subscribe.event_snapshot_result import EventSnapshotResult
18
+ from webull.data.internal.quotes_payload_decoder import BaseQuotesPayloadDecoder
19
+
20
+
21
+
22
+ class EventSnapshotDecoder(BaseQuotesPayloadDecoder):
23
+ def __init__(self):
24
+ super().__init__()
25
+
26
+ def parse(self, payload):
27
+ eventSnapshot = EventSnapshot()
28
+ eventSnapshot.ParseFromString(payload)
29
+ return EventSnapshotResult(eventSnapshot)
@@ -0,0 +1,85 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from decimal import Decimal
18
+ from webull.data.quotes.subscribe.basic_result import BasicResult
19
+
20
+
21
+ class EventSnapshotResult:
22
+ def __init__(self, pb_event_snapshot):
23
+ self.basic = BasicResult(pb_event_snapshot.basic)
24
+ self.price = Decimal(pb_event_snapshot.price) if pb_event_snapshot.price else None
25
+ self.volume = Decimal(pb_event_snapshot.volume) if pb_event_snapshot.volume else None
26
+ self.last_trade_time = int(pb_event_snapshot.last_trade_time) if pb_event_snapshot.last_trade_time else None
27
+ self.open_interest = Decimal(pb_event_snapshot.open_interest) if pb_event_snapshot.open_interest else None
28
+ self.yes_ask = Decimal(pb_event_snapshot.yes_ask) if pb_event_snapshot.yes_ask else None
29
+ self.yes_ask_size = Decimal(pb_event_snapshot.yes_ask_size) if pb_event_snapshot.yes_ask_size else None
30
+ self.yes_bid = Decimal(pb_event_snapshot.yes_bid) if pb_event_snapshot.yes_bid else None
31
+ self.yes_bid_size = Decimal(pb_event_snapshot.yes_bid_size) if pb_event_snapshot.yes_bid_size else None
32
+ self.no_bid = Decimal(pb_event_snapshot.no_bid) if pb_event_snapshot.no_bid else None
33
+ self.no_bid_size = Decimal(pb_event_snapshot.no_bid_size) if pb_event_snapshot.no_bid_size else None
34
+ self.no_ask = Decimal(pb_event_snapshot.no_ask) if pb_event_snapshot.no_ask else None
35
+ self.no_ask_size = Decimal(pb_event_snapshot.no_ask_size) if pb_event_snapshot.no_ask_size else None
36
+
37
+ def get_basic(self):
38
+ return self.basic
39
+
40
+ def get_price(self):
41
+ return self.price
42
+
43
+ def get_volume(self):
44
+ return self.volume
45
+
46
+ def get_last_trade_time(self):
47
+ return self.last_trade_time
48
+
49
+ def get_open_interest(self):
50
+ return self.open_interest
51
+
52
+ def get_yes_bid(self):
53
+ return self.yes_bid
54
+
55
+ def get_yes_bid_size(self):
56
+ return self.yes_bid_size
57
+
58
+ def get_yes_ask(self):
59
+ return self.yes_ask
60
+
61
+ def get_yes_ask_size(self):
62
+ return self.yes_ask_size
63
+
64
+ def get_no_bid(self):
65
+ return self.no_bid
66
+
67
+ def get_no_bid_size(self):
68
+ return self.no_bid_size
69
+
70
+ def get_no_ask(self):
71
+ return self.no_ask
72
+
73
+ def get_no_ask_size(self):
74
+ return self.no_ask_size
75
+
76
+ def __repr__(self):
77
+ attrs = ['price', 'volume', 'last_trade_time', 'open_interest']
78
+ yes_attrs = [f"yes_{name}" for name in ['bid', 'bid_size', 'ask', 'ask_size']]
79
+ no_attrs = [f"no_{name}" for name in ['bid', 'bid_size', 'ask', 'ask_size']]
80
+ all_attrs = attrs + yes_attrs + no_attrs
81
+ attr_str = ', '.join(f"{name}:{getattr(self, name)}" for name in all_attrs)
82
+ return f"{self.basic}, {attr_str}"
83
+
84
+ def __str__(self):
85
+ return self.__repr__()
@@ -2,10 +2,10 @@
2
2
  # Generated by the protocol buffer compiler. DO NOT EDIT!
3
3
  # source: message.proto
4
4
  """Generated protocol buffer code."""
5
- from google.protobuf.internal import builder as _builder
6
5
  from google.protobuf import descriptor as _descriptor
7
6
  from google.protobuf import descriptor_pool as _descriptor_pool
8
7
  from google.protobuf import symbol_database as _symbol_database
8
+ from google.protobuf.internal import builder as _builder
9
9
  # @@protoc_insertion_point(imports)
10
10
 
11
11
  _sym_db = _symbol_database.Default()
@@ -13,25 +13,31 @@ _sym_db = _symbol_database.Default()
13
13
 
14
14
 
15
15
 
16
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rmessage.proto\"Z\n\x05\x42\x61sic\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x15\n\rinstrument_id\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\t\x12\x17\n\x0ftrading_session\x18\x04 \x01(\t\"\xd6\x03\n\x08Snapshot\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x12\n\ntrade_time\x18\x02 \x01(\t\x12\r\n\x05price\x18\x03 \x01(\t\x12\x0c\n\x04open\x18\x04 \x01(\t\x12\x0c\n\x04high\x18\x05 \x01(\t\x12\x0b\n\x03low\x18\x06 \x01(\t\x12\x11\n\tpre_close\x18\x07 \x01(\t\x12\x0e\n\x06volume\x18\x08 \x01(\t\x12\x0e\n\x06\x63hange\x18\t \x01(\t\x12\x14\n\x0c\x63hange_ratio\x18\n \x01(\t\x12\x16\n\x0e\x65xt_trade_time\x18\x0b \x01(\t\x12\x11\n\text_price\x18\x0c \x01(\t\x12\x10\n\x08\x65xt_high\x18\r \x01(\t\x12\x0f\n\x07\x65xt_low\x18\x0e \x01(\t\x12\x12\n\next_volume\x18\x0f \x01(\t\x12\x12\n\next_change\x18\x10 \x01(\t\x12\x18\n\x10\x65xt_change_ratio\x18\x11 \x01(\t\x12\x16\n\x0eovn_trade_time\x18\x12 \x01(\t\x12\x11\n\tovn_price\x18\x13 \x01(\t\x12\x10\n\x08ovn_high\x18\x14 \x01(\t\x12\x0f\n\x07ovn_low\x18\x15 \x01(\t\x12\x12\n\novn_volume\x18\x16 \x01(\t\x12\x12\n\novn_change\x18\x17 \x01(\t\x12\x18\n\x10ovn_change_ratio\x18\x18 \x01(\t\"L\n\x05Quote\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x15\n\x04\x61sks\x18\x02 \x03(\x0b\x32\x07.AskBid\x12\x15\n\x04\x62ids\x18\x03 \x03(\x0b\x32\x07.AskBid\"X\n\x04Tick\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x0c\n\x04time\x18\x02 \x01(\t\x12\r\n\x05price\x18\x03 \x01(\t\x12\x0e\n\x06volume\x18\x04 \x01(\t\x12\x0c\n\x04side\x18\x05 \x01(\t\"U\n\x06\x41skBid\x12\r\n\x05price\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\t\x12\x15\n\x05order\x18\x03 \x03(\x0b\x32\x06.Order\x12\x17\n\x06\x62roker\x18\x04 \x03(\x0b\x32\x07.Broker\"#\n\x05Order\x12\x0c\n\x04mpid\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\t\"#\n\x06\x42roker\x12\x0b\n\x03\x62id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\tb\x06proto3')
16
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rmessage.proto\"Z\n\x05\x42\x61sic\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x15\n\rinstrument_id\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\t\x12\x17\n\x0ftrading_session\x18\x04 \x01(\t\"\xd6\x03\n\x08Snapshot\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x12\n\ntrade_time\x18\x02 \x01(\t\x12\r\n\x05price\x18\x03 \x01(\t\x12\x0c\n\x04open\x18\x04 \x01(\t\x12\x0c\n\x04high\x18\x05 \x01(\t\x12\x0b\n\x03low\x18\x06 \x01(\t\x12\x11\n\tpre_close\x18\x07 \x01(\t\x12\x0e\n\x06volume\x18\x08 \x01(\t\x12\x0e\n\x06\x63hange\x18\t \x01(\t\x12\x14\n\x0c\x63hange_ratio\x18\n \x01(\t\x12\x16\n\x0e\x65xt_trade_time\x18\x0b \x01(\t\x12\x11\n\text_price\x18\x0c \x01(\t\x12\x10\n\x08\x65xt_high\x18\r \x01(\t\x12\x0f\n\x07\x65xt_low\x18\x0e \x01(\t\x12\x12\n\next_volume\x18\x0f \x01(\t\x12\x12\n\next_change\x18\x10 \x01(\t\x12\x18\n\x10\x65xt_change_ratio\x18\x11 \x01(\t\x12\x16\n\x0eovn_trade_time\x18\x12 \x01(\t\x12\x11\n\tovn_price\x18\x13 \x01(\t\x12\x10\n\x08ovn_high\x18\x14 \x01(\t\x12\x0f\n\x07ovn_low\x18\x15 \x01(\t\x12\x12\n\novn_volume\x18\x16 \x01(\t\x12\x12\n\novn_change\x18\x17 \x01(\t\x12\x18\n\x10ovn_change_ratio\x18\x18 \x01(\t\"L\n\x05Quote\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x15\n\x04\x61sks\x18\x02 \x03(\x0b\x32\x07.AskBid\x12\x15\n\x04\x62ids\x18\x03 \x03(\x0b\x32\x07.AskBid\"X\n\x04Tick\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x0c\n\x04time\x18\x02 \x01(\t\x12\r\n\x05price\x18\x03 \x01(\t\x12\x0e\n\x06volume\x18\x04 \x01(\t\x12\x0c\n\x04side\x18\x05 \x01(\t\"U\n\x06\x41skBid\x12\r\n\x05price\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\t\x12\x15\n\x05order\x18\x03 \x03(\x0b\x32\x06.Order\x12\x17\n\x06\x62roker\x18\x04 \x03(\x0b\x32\x07.Broker\"#\n\x05Order\x12\x0c\n\x04mpid\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\t\"#\n\x06\x42roker\x12\x0b\n\x03\x62id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"\x8d\x02\n\rEventSnapshot\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\r\n\x05price\x18\x02 \x01(\t\x12\x0e\n\x06volume\x18\x03 \x01(\t\x12\x17\n\x0flast_trade_time\x18\x04 \x01(\t\x12\x15\n\ropen_interest\x18\x05 \x01(\t\x12\x0f\n\x07yes_ask\x18\x06 \x01(\t\x12\x0f\n\x07yes_bid\x18\x07 \x01(\t\x12\x14\n\x0cyes_ask_size\x18\x08 \x01(\t\x12\x14\n\x0cyes_bid_size\x18\t \x01(\t\x12\x0e\n\x06no_ask\x18\n \x01(\t\x12\x0e\n\x06no_bid\x18\x0b \x01(\t\x12\x13\n\x0bno_ask_size\x18\x0c \x01(\t\x12\x13\n\x0bno_bid_size\x18\r \x01(\t\"b\n\nEventQuote\x12\x15\n\x05\x62\x61sic\x18\x01 \x01(\x0b\x32\x06.Basic\x12\x1e\n\x08yes_bids\x18\x02 \x03(\x0b\x32\x0c.EventAskBid\x12\x1d\n\x07no_bids\x18\x03 \x03(\x0b\x32\x0c.EventAskBid\"*\n\x0b\x45ventAskBid\x12\r\n\x05price\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\tb\x06proto3')
17
17
 
18
- _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
19
- _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'message_pb2', globals())
18
+ _globals = globals()
19
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
20
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'message_pb2', _globals)
20
21
  if _descriptor._USE_C_DESCRIPTORS == False:
21
-
22
22
  DESCRIPTOR._options = None
23
- _BASIC._serialized_start=17
24
- _BASIC._serialized_end=107
25
- _SNAPSHOT._serialized_start=110
26
- _SNAPSHOT._serialized_end=580
27
- _QUOTE._serialized_start=582
28
- _QUOTE._serialized_end=658
29
- _TICK._serialized_start=660
30
- _TICK._serialized_end=748
31
- _ASKBID._serialized_start=750
32
- _ASKBID._serialized_end=835
33
- _ORDER._serialized_start=837
34
- _ORDER._serialized_end=872
35
- _BROKER._serialized_start=874
36
- _BROKER._serialized_end=909
23
+ _globals['_BASIC']._serialized_start=17
24
+ _globals['_BASIC']._serialized_end=107
25
+ _globals['_SNAPSHOT']._serialized_start=110
26
+ _globals['_SNAPSHOT']._serialized_end=580
27
+ _globals['_QUOTE']._serialized_start=582
28
+ _globals['_QUOTE']._serialized_end=658
29
+ _globals['_TICK']._serialized_start=660
30
+ _globals['_TICK']._serialized_end=748
31
+ _globals['_ASKBID']._serialized_start=750
32
+ _globals['_ASKBID']._serialized_end=835
33
+ _globals['_ORDER']._serialized_start=837
34
+ _globals['_ORDER']._serialized_end=872
35
+ _globals['_BROKER']._serialized_start=874
36
+ _globals['_BROKER']._serialized_end=909
37
+ _globals['_EVENTSNAPSHOT']._serialized_start=912
38
+ _globals['_EVENTSNAPSHOT']._serialized_end=1181
39
+ _globals['_EVENTQUOTE']._serialized_start=1183
40
+ _globals['_EVENTQUOTE']._serialized_end=1281
41
+ _globals['_EVENTASKBID']._serialized_start=1283
42
+ _globals['_EVENTASKBID']._serialized_end=1325
37
43
  # @@protoc_insertion_point(module_scope)
@@ -16,4 +16,6 @@
16
16
 
17
17
  PAYLOAD_TYPE_QUOTE = 'quote'
18
18
  PAYLOAD_TYPE_SHAPSHOT = 'snapshot'
19
- PAYLOAD_TYPE_TICK = 'tick'
19
+ PAYLOAD_TYPE_TICK = 'tick'
20
+ PAYLOAD_TYPE_EVENT_DEPTH = 'event-quote'
21
+ PAYLOAD_TYPE_EVENT_SHAPSHOT = 'event-snapshot'
@@ -0,0 +1,32 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.core.request import ApiRequest
18
+
19
+
20
+ class GetEventDepthRequest(ApiRequest):
21
+ def __init__(self):
22
+ ApiRequest.__init__(self, "/openapi/market-data/event/depth", version='v2', method="GET", query_params={})
23
+
24
+ def set_symbol(self, symbol):
25
+ self.add_query_param("symbol", symbol)
26
+
27
+ def set_category(self, category):
28
+ self.add_query_param("category", category)
29
+
30
+ def set_depth(self, depth):
31
+ if depth:
32
+ self.add_query_param("depth", depth)
@@ -0,0 +1,33 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.core.request import ApiRequest
18
+
19
+ class GetEventInstrumentRequest(ApiRequest):
20
+ def __init__(self):
21
+ ApiRequest.__init__(self, "/openapi/instrument/event/market/list", version='v2', method="GET", query_params={})
22
+
23
+ def set_series_symbol(self, series_symbol):
24
+ self.add_query_param("series_symbol", series_symbol)
25
+
26
+ def set_expiration_date_after(self, expiration_date_after):
27
+ self.add_query_param("expiration_date_after", expiration_date_after)
28
+
29
+ def set_last_instrument_id(self, last_instrument_id):
30
+ self.add_query_param("last_instrument_id", last_instrument_id)
31
+
32
+ def set_page_size(self, page_size):
33
+ self.add_query_param("page_size", page_size)
@@ -0,0 +1,30 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.core.request import ApiRequest
18
+
19
+ class GetEventSeriesRequest(ApiRequest):
20
+ def __init__(self):
21
+ ApiRequest.__init__(self, "/openapi/instrument/event/series/list", version='v2', method="GET", query_params={})
22
+
23
+ def set_category(self, category):
24
+ self.add_query_param("category", category)
25
+
26
+ def set_last_instrument_id(self, last_instrument_id):
27
+ self.add_query_param("last_instrument_id", last_instrument_id)
28
+
29
+ def set_page_size(self, page_size):
30
+ self.add_query_param("page_size", page_size)
@@ -0,0 +1,31 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # coding=utf-8
16
+
17
+ from webull.core.request import ApiRequest
18
+
19
+
20
+ class GetEventSnapshotRequest(ApiRequest):
21
+ def __init__(self):
22
+ ApiRequest.__init__(self, "/openapi/market-data/event/snapshot", version='v2', method="GET", query_params={})
23
+
24
+ def set_symbols(self, symbols):
25
+ if isinstance(symbols, str):
26
+ self.add_query_param("symbols", symbols)
27
+ elif isinstance(symbols, list):
28
+ self.add_query_param("symbols", ",".join(symbols))
29
+
30
+ def set_category(self, category):
31
+ self.add_query_param("category", category)
webull/trade/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.0.9'
1
+ __version__ = '1.1.0'
@@ -15,7 +15,7 @@
15
15
  # coding=utf-8
16
16
 
17
17
  EVENT_TYPE_ORDER = 1024
18
- EVENT_TYPE_POSITION = 1025
18
+ EVENT_TYPE_POSITION = 1028
19
19
 
20
20
  ORDER_STATUS_CHANGED = 1
21
21
  POSITION_STATUS_CHANGED = 2
@@ -69,7 +69,7 @@ class TradeEventsClient():
69
69
 
70
70
  def _build_request(self, app_key, app_secret, accounts):
71
71
  request = pb.SubscribeRequest(
72
- subscribeType=1, # only 1 allowed now
72
+ subscribeType= 3, # only 1、2 allowed now
73
73
  timestamp=int(time.time() * 1000), # millis
74
74
  accounts=accounts,
75
75
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webull-openapi-python-sdk
3
- Version: 1.0.9
3
+ Version: 1.1.0
4
4
  Summary: Webull Python SDK.
5
5
  Home-page:
6
6
  Author: Webull
@@ -5,18 +5,21 @@ samples/assets/__init__.py,sha256=eoZ6GfifbqhMLNzjlqRDVil-yyBkOmVN9ujSgJWNBlY,15
5
5
  samples/assets/assets_client.py,sha256=p9LS2Td3gbUMkHn4LD_9RMCFuaQRUbsKvG4PhZBGJDc,1974
6
6
  samples/data/__init__.py,sha256=eoZ6GfifbqhMLNzjlqRDVil-yyBkOmVN9ujSgJWNBlY,15
7
7
  samples/data/data_client.py,sha256=8FR5ZOY8jWCGfN3XohzyvLdFxYv-TdqfWRKw3E827WY,5248
8
+ samples/data/data_client_event.py,sha256=aqOTvuUOoWhqfac7z8JHWQC1EXWoVaGcnp8tlHO_PVE,2301
8
9
  samples/data/data_streaming_client.py,sha256=IdCUNdfo2_dR9OLgWZuIc9U9s-0-uNjwqkf9aLoG-44,4088
9
10
  samples/data/data_streaming_client_async.py,sha256=o_u1ch8JdbcYnLCvDCCUzO-Z1IG7BUKncu_GB_kCbOs,4443
11
+ samples/data/data_streaming_client_event.py,sha256=BRMxFdkzEHyppLlhvFfzvET0RQZPxHxAHIn3g-dIf10,3050
10
12
  samples/order/__init__.py,sha256=eoZ6GfifbqhMLNzjlqRDVil-yyBkOmVN9ujSgJWNBlY,15
11
13
  samples/order/order_option_client.py,sha256=njxr1QZc69_VbHsp9D9cOv1_-AekO2uNYKiY7o0-1Eg,3602
12
14
  samples/order/order_stock_client.py,sha256=hYwVwVFVERk-YS7gRcW-LuGfAvcF8VJHZs1qwLcFhYU,3529
13
15
  samples/trade/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
16
  samples/trade/trade_client.py,sha256=LyWSvZJH4ByCkRORqP9WdkXfx65A2b6fhc9_GzL8DOM,6258
15
17
  samples/trade/trade_client_v2.py,sha256=IO-zmRiUnCmIetTdiYunPh8jVK2VaPrOR77Dwvz1auY,10771
16
- samples/trade/trade_client_v3.py,sha256=70f4VJYWcSJP3ppA8mRAoftJqjRTn5GTeGZck8eLCTg,16526
17
- samples/trade/trade_event_client.py,sha256=uOx9EwFaves2yaTNm13BHpYC0IHXSoBL8BWPbDLeFw4,2469
18
- webull/__init__.py,sha256=mg2kb865UYMe9zOkU2VcRPfv-5zzU182OL3t45SXXWk,22
19
- webull/core/__init__.py,sha256=MSNIk2XHGC6pQer-Z5tjWyHUXb0Wi1O1Vnn93JEPa5A,225
18
+ samples/trade/trade_client_v3.py,sha256=cyP-gEyzi-mXtrb2RBRou8WmCOZhjEgr75lE27DuEZc,18783
19
+ samples/trade/trade_client_v3_event.py,sha256=91HlT04KlK8Q5gUnsB8F5ErCFdJRnpDABKkBfYRc-YE,3932
20
+ samples/trade/trade_event_client.py,sha256=BWdD1L41LXmDlaig6ku9T3t3fSCCZEdj5nxH1xI1AZA,2653
21
+ webull/__init__.py,sha256=b6-WiVk0Li5MaV2rBnHYl104TsouINojSWKqHDas0js,22
22
+ webull/core/__init__.py,sha256=oLOxMxcWb31kX-WluC8UBbN_qh7Ybd68lBklE_xJOK4,225
20
23
  webull/core/client.py,sha256=OE_ghPA558eE85MmaU_I3Tg0j-osCQFChTk-6dy4OW0,16398
21
24
  webull/core/compat.py,sha256=HDis0D271oQ6OCpA7ViX10NJdhfXdoBfzx6nuV3vrnI,3114
22
25
  webull/core/headers.py,sha256=7aMt3_YtaL9Yhqj2T1g7ESQgkI78SAXIk7hMX5U5FgE,2019
@@ -186,11 +189,11 @@ webull/core/vendored/requests/packages/urllib3/util/ssl_.py,sha256=aRUKc1WIyS-sU
186
189
  webull/core/vendored/requests/packages/urllib3/util/timeout.py,sha256=sAyiBBds7eOk1oM3ulvVMWZiqx1B743puHqK92XwBcY,10325
187
190
  webull/core/vendored/requests/packages/urllib3/util/url.py,sha256=_CgqbyNrQWubrv_y5aWhuutz3mnbj1cvTUe4VYbGYWA,7367
188
191
  webull/core/vendored/requests/packages/urllib3/util/wait.py,sha256=0FHS8R3OrMU-97XWt8AxuUStkSGXTct9CfOwY_fWn7U,5971
189
- webull/data/__init__.py,sha256=16Et8WoO5VLLeKZR62v51Ah41JMXVyb5jk5AlVyFpvU,38
190
- webull/data/data_client.py,sha256=JGouoFd37-sxpP6GyOJ0rRw7UuBmXqoIcis0jiRGJPQ,1871
191
- webull/data/data_streaming_client.py,sha256=hYqrdKTeIB3Xmp7LMjMwN1XE6Y7bKXX0y-lGX1ty6W4,3870
192
+ webull/data/__init__.py,sha256=zA42W1xpbGVCnbQBesHoLxJSnAU9Jk30T5FCHCttTUc,38
193
+ webull/data/data_client.py,sha256=1_jrNHrqes7vygUkA1GRI_CIMJp4zcv_Ny8XUDyck1E,1997
194
+ webull/data/data_streaming_client.py,sha256=W6asCGuEmqciCZhIFf4dLh5CNHoxybixhwjF19p4AJk,4271
192
195
  webull/data/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
- webull/data/common/category.py,sha256=r_cMxgc-wJvAvI6xjUR18Tb_VaT9fmwkCtOGmi7VINw,910
196
+ webull/data/common/category.py,sha256=7zp-C6ex1eBHw4jTKgeg4X_JASjAM619pLpzQK9XTbc,942
194
197
  webull/data/common/connect_ack.py,sha256=PGhtTzb1hAciHRvMSqMUasyEMC6vdV52taP8RbTB8t8,1209
195
198
  webull/data/common/contract_type.py,sha256=dQZMIC1kMDbz0TM34ElfsMRI_k2SXsRYyXX6UcI9JG8,715
196
199
  webull/data/common/direction.py,sha256=N0Me8CJD3oQDmx2EpNzlvFQDjmmhxa4qKorpV11OLM0,987
@@ -210,17 +213,22 @@ webull/data/internal/quotes_payload_decoder.py,sha256=x2XGYDu4wSdc1LLrcIo3BXeb5j
210
213
  webull/data/internal/quotes_topic.py,sha256=kG4RZTjj01U0e54qoOrJHlLrPeBzXekySasm2uoyXVo,1138
211
214
  webull/data/quotes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
212
215
  webull/data/quotes/crypto_market_data.py,sha256=UQlxUz0GntvwcRS-Vh_h7cXbhQ045MqPlG5AhWUoQI4,3063
216
+ webull/data/quotes/event_market_data.py,sha256=qWOgJoQWO8-RHdoC80EQt2eYdMRgcmUB84mFXAVodTU,2382
213
217
  webull/data/quotes/futures_market_data.py,sha256=fc9giYNy1LcdLHOJV31zMbPBKtWDH8kBW5xRFgHzQUA,5596
214
- webull/data/quotes/instrument.py,sha256=4mrL8VEftiPmbEl_7qdpnrgFDuty54tb6C9j_Hh8iME,5089
218
+ webull/data/quotes/instrument.py,sha256=n-QCRSC0iHWvWMc7Nq5tbJT-XOHeHCCQQ44hGyq59Aw,7470
215
219
  webull/data/quotes/market_data.py,sha256=5HjzLQje1F7OxasRrjNPZ2d-tkuYJ-aDMZj3fVEO6cI,11329
216
220
  webull/data/quotes/market_streaming_data.py,sha256=cI9xxGpKV_KDS8cgh9azHifBji0yeSuKmH7Jxaqij38,3139
217
221
  webull/data/quotes/subscribe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
- webull/data/quotes/subscribe/ask_bid_result.py,sha256=EWu5dFMb_BwFGYPLe-f9uCD8_Ftl1wguhpU1qXi2zaY,1552
222
+ webull/data/quotes/subscribe/ask_bid_result.py,sha256=J6Ms_01a44IvzNcw9krwMM0CuA_-zh-5eBGqx2kQbv4,1759
219
223
  webull/data/quotes/subscribe/basic_result.py,sha256=l9pxGlt8HLHwE3plq_6J0OPZ_X4ZjjRfa1f9nExu2dE,1450
220
224
  webull/data/quotes/subscribe/broker_result.py,sha256=E6pM0Ydr6tU_bPSOeyu1KJf7oYgbO-lIXLIdJQANH4I,1013
221
- webull/data/quotes/subscribe/message_pb2.py,sha256=JimxZN9hCEvt_NF0eYRNZJttEsCAc3bWAelE5Tva7yM,3136
225
+ webull/data/quotes/subscribe/event_depth_decoder.py,sha256=-2mOw4o32HWO1a7MuB3hgFoST0ct96Z3PrBFzfCNMJs,1061
226
+ webull/data/quotes/subscribe/event_depth_result.py,sha256=30hUvNqQZNnwGNngmqPO3eFtCkJXd6OjjV8FadN7uXE,1510
227
+ webull/data/quotes/subscribe/event_snapshot_decoder.py,sha256=R1Pnz-Ktmwo3vZ7CVTSY9labn-nZealarE6c0cSieRU,1090
228
+ webull/data/quotes/subscribe/event_snapshot_result.py,sha256=npGS47XNpxP8-u6-3K2mLnLeiI8ofgotOOleqfHkUsc,3327
229
+ webull/data/quotes/subscribe/message_pb2.py,sha256=idUZoqQiG4t0An_sA61CjMr3-v7wTO6mZN3I1LB36pc,4445
222
230
  webull/data/quotes/subscribe/order_result.py,sha256=bqLjRzCDK0jpQBMm00QxfgV-SPg04lOLYxc8SgpkFDw,912
223
- webull/data/quotes/subscribe/payload_type.py,sha256=nacQubAzKjutfddNdilckpsbamCUt6nrBnzrxgMOrWQ,674
231
+ webull/data/quotes/subscribe/payload_type.py,sha256=mkbjRKmiAmGmPvTbJlB74HXWkeJHrz32fiMv2xgqRas,762
224
232
  webull/data/quotes/subscribe/quote_decoder.py,sha256=vTDKi3TaQ79ODTydVcEEiJR2g0fQLPf5hUOqo7Mi1gw,1016
225
233
  webull/data/quotes/subscribe/quote_result.py,sha256=2SoRzSGANphAut1jleNnfZtUhpqqbELRcs1biu440p8,1442
226
234
  webull/data/quotes/subscribe/snapshot_decoder.py,sha256=dukBHXa971LHp9oPkgQ4mqL_8yIAU5XSlUIUjpMz2NY,1045
@@ -234,6 +242,10 @@ webull/data/request/get_crypto_historical_bars_request.py,sha256=FKIp2hB2fPbkMLx
234
242
  webull/data/request/get_crypto_instruments_request.py,sha256=GwOA9oPBH4qNg7yR-lVjrRSGZDF5zfRUBS4PegKLcjk,1549
235
243
  webull/data/request/get_crypto_snapshot_request.py,sha256=W-z9nuBu2RaXqy07zFVHMQs9GP5Hc55vOWWYKoibWVA,1136
236
244
  webull/data/request/get_eod_bars_request.py,sha256=CwbyXeAE-iPKu43zNxcekSw5qOlfEwZsztFxCQvAXuQ,1234
245
+ webull/data/request/get_event_depth_request.py,sha256=g0WzBAc7ab8TdYFJ1EWs9KxOvkrXcvuQrDSS-hNrOkQ,1079
246
+ webull/data/request/get_event_instrument_request.py,sha256=fpfxUhra1d5HP3l_srMiFTZF_VPF-ZgIptV8UPnbGzI,1292
247
+ webull/data/request/get_event_series_request.py,sha256=JR7FXikBnivMDZ_NR347wktJKiAoxWEnjy7uZr3etmE,1126
248
+ webull/data/request/get_event_snapshot_request.py,sha256=rQzdZWQ7eFohYMYmWaZInmdpyNi6rR5KhxgDOPlr_Wc,1133
237
249
  webull/data/request/get_footprint_request.py,sha256=MnbKhhe7QMkKqyTxmXl-ztDl5l_3kkFhT1vtql82K3Y,1664
238
250
  webull/data/request/get_futures_depth_request.py,sha256=d6Tl-75pcJlvX6-beAdko15o8hDhdB-486uxH8AeGIk,1083
239
251
  webull/data/request/get_futures_footprint_request.py,sha256=I0l-SlXBKqY61Oxq1zn1EWwLY79euuEoUcrvCzPJlA8,1673
@@ -250,9 +262,9 @@ webull/data/request/get_snapshot_request.py,sha256=OD2PiaxmBCboFDaU8DFTwvfNd2zOb
250
262
  webull/data/request/get_tick_request.py,sha256=rUHhQgC8Z_6ensLyCkg3DDK55SlEi0Bc_dhpCIIspDs,1366
251
263
  webull/data/request/subscribe_request.py,sha256=dm93Q5Q4gigAMqAobolaYYSs3wM6QddPUZOjEtJsX-8,1471
252
264
  webull/data/request/unsubscribe_request.py,sha256=hQA4mYM64PgmQEA2otl47-3nCXqjsSY_weFA3_wNbMM,1446
253
- webull/trade/__init__.py,sha256=mu4LFHUATfA8gJh1jUgMKeIXEjlhbQqTC5UyMGu-2Gs,21
265
+ webull/trade/__init__.py,sha256=XIz3qAg9G9YysQi3Ryp0CN3rtc_JiecHZ9L2vEzcM6s,21
254
266
  webull/trade/trade_client.py,sha256=_6lH4KO-jKgKWU28fWNsc9-KEHto-WvaP0gT96BJ_dw,2184
255
- webull/trade/trade_events_client.py,sha256=4a7qupeT3dKJRKBQqXNhCai6ENzX6PA4yjTDHHxPR0w,8892
267
+ webull/trade/trade_events_client.py,sha256=KCabQmP9zwo6o8mJYOkXL21dz4yb-SFUcVpKfY88hPQ,8897
256
268
  webull/trade/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
269
  webull/trade/common/account_type.py,sha256=haVAB33MERN6XyPsbrfVQhK9_CpU90VltI6_KDkxzlE,715
258
270
  webull/trade/common/category.py,sha256=GJ9pDCMkwq7062o9L9o5aPvqHoYxuMqEbInlkfxD65U,911
@@ -275,7 +287,7 @@ webull/trade/events/default_retry_policy.py,sha256=zWoaJFJSUTtHw_qLj9_AIPBzFW6UH
275
287
  webull/trade/events/events_pb2.py,sha256=NLolj5VOws1LJT5YIvnuZab9YYhR4lm2-iCkztaARPo,2440
276
288
  webull/trade/events/events_pb2_grpc.py,sha256=ebxp_VCJHBQFCKvxBKRUMhW67TZoUn6NwCBvKpiTEpg,2482
277
289
  webull/trade/events/signature_composer.py,sha256=zcfBgwQ6XpoEOmeqSnKlgl0j0oDQ0x80_KS_11W3gwA,2496
278
- webull/trade/events/types.py,sha256=jRX198gzHd5z_xke9yzfrJhclEBVTbCsDoln2PA-q0g,689
290
+ webull/trade/events/types.py,sha256=NkBeC3mQPflcg7NDTChVS-DAtDPX_G-od9YJt_FLZTc,689
279
291
  webull/trade/request/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
280
292
  webull/trade/request/cancel_order_request.py,sha256=JbyeVNOVu9xvwzba7Ntw2Sh4BrNVUbBTkYLTKgXIU5U,1016
281
293
  webull/trade/request/get_account_balance_request.py,sha256=S9M1rz6HFlIwRpWfkQKVfRo996_DWF8Qe6bGirSnkV0,1042
@@ -330,9 +342,9 @@ webull/trade/trade/v2/account_info_v2.py,sha256=IGY_BGTrZ0h7yQ_nDodNtmKen9gXW6he
330
342
  webull/trade/trade/v2/order_operation_v2.py,sha256=m54RH2j45CBBWEnqe4KxrsltAF44XKtPMT4kv8t7djQ,12745
331
343
  webull/trade/trade/v3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
344
  webull/trade/trade/v3/order_opration_v3.py,sha256=_L10--m_XhoMe8YeYjQXVvRoTAWoRRzLU59UeneyMrU,7428
333
- webull_openapi_python_sdk-1.0.9.dist-info/licenses/LICENSE,sha256=ALOnsLtb1aHxmDJg3-oMi0BO-i-cjfyZaOBfnnavKMc,11359
334
- webull_openapi_python_sdk-1.0.9.dist-info/licenses/NOTICE,sha256=X5TApte6CPV10b96Cb70IRLusXmiRmK_R-dB-1tQM_I,2018
335
- webull_openapi_python_sdk-1.0.9.dist-info/METADATA,sha256=I4Ohkx7rljnJeBfQ0goKx42vBTbF48Kp4aSWQF3xEcM,702
336
- webull_openapi_python_sdk-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
337
- webull_openapi_python_sdk-1.0.9.dist-info/top_level.txt,sha256=h8pEjNDGWS2ZUZ2vYFpUShoMQT0ZRIQaD57QJWD8_aI,15
338
- webull_openapi_python_sdk-1.0.9.dist-info/RECORD,,
345
+ webull_openapi_python_sdk-1.1.0.dist-info/licenses/LICENSE,sha256=ALOnsLtb1aHxmDJg3-oMi0BO-i-cjfyZaOBfnnavKMc,11359
346
+ webull_openapi_python_sdk-1.1.0.dist-info/licenses/NOTICE,sha256=X5TApte6CPV10b96Cb70IRLusXmiRmK_R-dB-1tQM_I,2018
347
+ webull_openapi_python_sdk-1.1.0.dist-info/METADATA,sha256=SoLm3zYNjQ1YlShV_dBgS8UZ6_CoQt7FEmu3xqYciGQ,702
348
+ webull_openapi_python_sdk-1.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
349
+ webull_openapi_python_sdk-1.1.0.dist-info/top_level.txt,sha256=h8pEjNDGWS2ZUZ2vYFpUShoMQT0ZRIQaD57QJWD8_aI,15
350
+ webull_openapi_python_sdk-1.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5