webull-openapi-python-sdk 1.0.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 (295) hide show
  1. samples/__init__.py +1 -0
  2. samples/data/__init__.py +1 -0
  3. samples/data/data_client.py +57 -0
  4. samples/data/data_streaming_client.py +86 -0
  5. samples/data/data_streaming_client_async.py +101 -0
  6. samples/trade/__init__.py +0 -0
  7. samples/trade/trade_client.py +163 -0
  8. samples/trade/trade_client_v2.py +181 -0
  9. samples/trade/trade_event_client.py +47 -0
  10. webull/__init__.py +1 -0
  11. webull/core/__init__.py +12 -0
  12. webull/core/auth/__init__.py +0 -0
  13. webull/core/auth/algorithm/__init__.py +0 -0
  14. webull/core/auth/algorithm/sha_hmac1.py +65 -0
  15. webull/core/auth/algorithm/sha_hmac256.py +75 -0
  16. webull/core/auth/composer/__init__.py +0 -0
  17. webull/core/auth/composer/default_signature_composer.py +125 -0
  18. webull/core/auth/credentials.py +46 -0
  19. webull/core/auth/signers/__init__.py +0 -0
  20. webull/core/auth/signers/app_key_signer.py +72 -0
  21. webull/core/auth/signers/signer.py +48 -0
  22. webull/core/auth/signers/signer_factory.py +58 -0
  23. webull/core/cache/__init__.py +225 -0
  24. webull/core/client.py +410 -0
  25. webull/core/common/__init__.py +0 -0
  26. webull/core/common/api_type.py +19 -0
  27. webull/core/common/easy_enum.py +35 -0
  28. webull/core/common/region.py +7 -0
  29. webull/core/compat.py +85 -0
  30. webull/core/context/__init__.py +0 -0
  31. webull/core/context/request_context_holder.py +33 -0
  32. webull/core/data/endpoints.json +22 -0
  33. webull/core/data/retry_config.json +15 -0
  34. webull/core/endpoint/__init__.py +8 -0
  35. webull/core/endpoint/chained_endpoint_resolver.py +57 -0
  36. webull/core/endpoint/default_endpoint_resolver.py +60 -0
  37. webull/core/endpoint/local_config_regional_endpoint_resolver.py +77 -0
  38. webull/core/endpoint/resolver_endpoint_request.py +46 -0
  39. webull/core/endpoint/user_customized_endpoint_resolver.py +55 -0
  40. webull/core/exception/__init__.py +0 -0
  41. webull/core/exception/error_code.py +23 -0
  42. webull/core/exception/error_msg.py +21 -0
  43. webull/core/exception/exceptions.py +53 -0
  44. webull/core/headers.py +57 -0
  45. webull/core/http/__init__.py +0 -0
  46. webull/core/http/initializer/__init__.py +0 -0
  47. webull/core/http/initializer/client_initializer.py +79 -0
  48. webull/core/http/initializer/token/__init__.py +0 -0
  49. webull/core/http/initializer/token/bean/__init__.py +0 -0
  50. webull/core/http/initializer/token/bean/access_token.py +40 -0
  51. webull/core/http/initializer/token/bean/check_token_request.py +44 -0
  52. webull/core/http/initializer/token/bean/create_token_request.py +45 -0
  53. webull/core/http/initializer/token/bean/refresh_token_request.py +44 -0
  54. webull/core/http/initializer/token/token_manager.py +208 -0
  55. webull/core/http/initializer/token/token_operation.py +72 -0
  56. webull/core/http/method_type.py +43 -0
  57. webull/core/http/protocol_type.py +43 -0
  58. webull/core/http/request.py +121 -0
  59. webull/core/http/response.py +166 -0
  60. webull/core/request.py +278 -0
  61. webull/core/retry/__init__.py +0 -0
  62. webull/core/retry/backoff_strategy.py +102 -0
  63. webull/core/retry/retry_condition.py +214 -0
  64. webull/core/retry/retry_policy.py +63 -0
  65. webull/core/retry/retry_policy_context.py +51 -0
  66. webull/core/utils/__init__.py +0 -0
  67. webull/core/utils/common.py +62 -0
  68. webull/core/utils/data.py +25 -0
  69. webull/core/utils/desensitize.py +33 -0
  70. webull/core/utils/validation.py +49 -0
  71. webull/core/vendored/__init__.py +0 -0
  72. webull/core/vendored/requests/__init__.py +94 -0
  73. webull/core/vendored/requests/__version__.py +28 -0
  74. webull/core/vendored/requests/_internal_utils.py +56 -0
  75. webull/core/vendored/requests/adapters.py +539 -0
  76. webull/core/vendored/requests/api.py +166 -0
  77. webull/core/vendored/requests/auth.py +307 -0
  78. webull/core/vendored/requests/certs.py +34 -0
  79. webull/core/vendored/requests/compat.py +85 -0
  80. webull/core/vendored/requests/cookies.py +555 -0
  81. webull/core/vendored/requests/exceptions.py +136 -0
  82. webull/core/vendored/requests/help.py +134 -0
  83. webull/core/vendored/requests/hooks.py +48 -0
  84. webull/core/vendored/requests/models.py +960 -0
  85. webull/core/vendored/requests/packages/__init__.py +17 -0
  86. webull/core/vendored/requests/packages/certifi/__init__.py +17 -0
  87. webull/core/vendored/requests/packages/certifi/__main__.py +16 -0
  88. webull/core/vendored/requests/packages/certifi/cacert.pem +4433 -0
  89. webull/core/vendored/requests/packages/certifi/core.py +51 -0
  90. webull/core/vendored/requests/packages/chardet/__init__.py +53 -0
  91. webull/core/vendored/requests/packages/chardet/big5freq.py +400 -0
  92. webull/core/vendored/requests/packages/chardet/big5prober.py +61 -0
  93. webull/core/vendored/requests/packages/chardet/chardistribution.py +247 -0
  94. webull/core/vendored/requests/packages/chardet/charsetgroupprober.py +120 -0
  95. webull/core/vendored/requests/packages/chardet/charsetprober.py +159 -0
  96. webull/core/vendored/requests/packages/chardet/cli/__init__.py +1 -0
  97. webull/core/vendored/requests/packages/chardet/cli/chardetect.py +99 -0
  98. webull/core/vendored/requests/packages/chardet/codingstatemachine.py +102 -0
  99. webull/core/vendored/requests/packages/chardet/compat.py +48 -0
  100. webull/core/vendored/requests/packages/chardet/cp949prober.py +63 -0
  101. webull/core/vendored/requests/packages/chardet/enums.py +90 -0
  102. webull/core/vendored/requests/packages/chardet/escprober.py +115 -0
  103. webull/core/vendored/requests/packages/chardet/escsm.py +260 -0
  104. webull/core/vendored/requests/packages/chardet/eucjpprober.py +106 -0
  105. webull/core/vendored/requests/packages/chardet/euckrfreq.py +209 -0
  106. webull/core/vendored/requests/packages/chardet/euckrprober.py +61 -0
  107. webull/core/vendored/requests/packages/chardet/euctwfreq.py +401 -0
  108. webull/core/vendored/requests/packages/chardet/euctwprober.py +60 -0
  109. webull/core/vendored/requests/packages/chardet/gb2312freq.py +297 -0
  110. webull/core/vendored/requests/packages/chardet/gb2312prober.py +60 -0
  111. webull/core/vendored/requests/packages/chardet/hebrewprober.py +306 -0
  112. webull/core/vendored/requests/packages/chardet/jisfreq.py +339 -0
  113. webull/core/vendored/requests/packages/chardet/jpcntx.py +247 -0
  114. webull/core/vendored/requests/packages/chardet/langbulgarianmodel.py +242 -0
  115. webull/core/vendored/requests/packages/chardet/langcyrillicmodel.py +347 -0
  116. webull/core/vendored/requests/packages/chardet/langgreekmodel.py +239 -0
  117. webull/core/vendored/requests/packages/chardet/langhebrewmodel.py +214 -0
  118. webull/core/vendored/requests/packages/chardet/langhungarianmodel.py +239 -0
  119. webull/core/vendored/requests/packages/chardet/langthaimodel.py +213 -0
  120. webull/core/vendored/requests/packages/chardet/langturkishmodel.py +207 -0
  121. webull/core/vendored/requests/packages/chardet/latin1prober.py +159 -0
  122. webull/core/vendored/requests/packages/chardet/mbcharsetprober.py +105 -0
  123. webull/core/vendored/requests/packages/chardet/mbcsgroupprober.py +68 -0
  124. webull/core/vendored/requests/packages/chardet/mbcssm.py +586 -0
  125. webull/core/vendored/requests/packages/chardet/sbcharsetprober.py +146 -0
  126. webull/core/vendored/requests/packages/chardet/sbcsgroupprober.py +87 -0
  127. webull/core/vendored/requests/packages/chardet/sjisprober.py +106 -0
  128. webull/core/vendored/requests/packages/chardet/universaldetector.py +300 -0
  129. webull/core/vendored/requests/packages/chardet/utf8prober.py +96 -0
  130. webull/core/vendored/requests/packages/chardet/version.py +23 -0
  131. webull/core/vendored/requests/packages/urllib3/__init__.py +114 -0
  132. webull/core/vendored/requests/packages/urllib3/_collections.py +346 -0
  133. webull/core/vendored/requests/packages/urllib3/connection.py +405 -0
  134. webull/core/vendored/requests/packages/urllib3/connectionpool.py +910 -0
  135. webull/core/vendored/requests/packages/urllib3/contrib/__init__.py +0 -0
  136. webull/core/vendored/requests/packages/urllib3/contrib/_appengine_environ.py +44 -0
  137. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/__init__.py +0 -0
  138. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/bindings.py +607 -0
  139. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/low_level.py +360 -0
  140. webull/core/vendored/requests/packages/urllib3/contrib/appengine.py +303 -0
  141. webull/core/vendored/requests/packages/urllib3/contrib/ntlmpool.py +125 -0
  142. webull/core/vendored/requests/packages/urllib3/contrib/pyopenssl.py +484 -0
  143. webull/core/vendored/requests/packages/urllib3/contrib/securetransport.py +818 -0
  144. webull/core/vendored/requests/packages/urllib3/contrib/socks.py +206 -0
  145. webull/core/vendored/requests/packages/urllib3/exceptions.py +260 -0
  146. webull/core/vendored/requests/packages/urllib3/fields.py +192 -0
  147. webull/core/vendored/requests/packages/urllib3/filepost.py +112 -0
  148. webull/core/vendored/requests/packages/urllib3/packages/__init__.py +19 -0
  149. webull/core/vendored/requests/packages/urllib3/packages/backports/__init__.py +0 -0
  150. webull/core/vendored/requests/packages/urllib3/packages/backports/makefile.py +67 -0
  151. webull/core/vendored/requests/packages/urllib3/packages/ordered_dict.py +273 -0
  152. webull/core/vendored/requests/packages/urllib3/packages/six.py +882 -0
  153. webull/core/vendored/requests/packages/urllib3/packages/socks.py +887 -0
  154. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +19 -0
  155. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py +170 -0
  156. webull/core/vendored/requests/packages/urllib3/poolmanager.py +467 -0
  157. webull/core/vendored/requests/packages/urllib3/request.py +164 -0
  158. webull/core/vendored/requests/packages/urllib3/response.py +721 -0
  159. webull/core/vendored/requests/packages/urllib3/util/__init__.py +68 -0
  160. webull/core/vendored/requests/packages/urllib3/util/connection.py +148 -0
  161. webull/core/vendored/requests/packages/urllib3/util/queue.py +35 -0
  162. webull/core/vendored/requests/packages/urllib3/util/request.py +132 -0
  163. webull/core/vendored/requests/packages/urllib3/util/response.py +101 -0
  164. webull/core/vendored/requests/packages/urllib3/util/retry.py +426 -0
  165. webull/core/vendored/requests/packages/urllib3/util/selectors.py +601 -0
  166. webull/core/vendored/requests/packages/urllib3/util/ssl_.py +396 -0
  167. webull/core/vendored/requests/packages/urllib3/util/timeout.py +256 -0
  168. webull/core/vendored/requests/packages/urllib3/util/url.py +252 -0
  169. webull/core/vendored/requests/packages/urllib3/util/wait.py +164 -0
  170. webull/core/vendored/requests/packages.py +28 -0
  171. webull/core/vendored/requests/sessions.py +750 -0
  172. webull/core/vendored/requests/status_codes.py +105 -0
  173. webull/core/vendored/requests/structures.py +119 -0
  174. webull/core/vendored/requests/utils.py +916 -0
  175. webull/core/vendored/six.py +905 -0
  176. webull/data/__init__.py +3 -0
  177. webull/data/common/__init__.py +0 -0
  178. webull/data/common/category.py +26 -0
  179. webull/data/common/connect_ack.py +29 -0
  180. webull/data/common/direction.py +25 -0
  181. webull/data/common/exchange_code.py +33 -0
  182. webull/data/common/exercise_style.py +22 -0
  183. webull/data/common/expiration_cycle.py +26 -0
  184. webull/data/common/instrument_status.py +23 -0
  185. webull/data/common/option_type.py +20 -0
  186. webull/data/common/subscribe_type.py +22 -0
  187. webull/data/common/timespan.py +29 -0
  188. webull/data/data_client.py +35 -0
  189. webull/data/data_streaming_client.py +89 -0
  190. webull/data/internal/__init__.py +0 -0
  191. webull/data/internal/default_retry_policy.py +84 -0
  192. webull/data/internal/exceptions.py +60 -0
  193. webull/data/internal/quotes_client.py +314 -0
  194. webull/data/internal/quotes_decoder.py +40 -0
  195. webull/data/internal/quotes_payload_decoder.py +35 -0
  196. webull/data/internal/quotes_topic.py +36 -0
  197. webull/data/quotes/__init__.py +0 -0
  198. webull/data/quotes/instrument.py +33 -0
  199. webull/data/quotes/market_data.py +187 -0
  200. webull/data/quotes/market_streaming_data.py +66 -0
  201. webull/data/quotes/subscribe/__init__.py +0 -0
  202. webull/data/quotes/subscribe/ask_bid_result.py +49 -0
  203. webull/data/quotes/subscribe/basic_result.py +45 -0
  204. webull/data/quotes/subscribe/broker_result.py +33 -0
  205. webull/data/quotes/subscribe/message_pb2.py +37 -0
  206. webull/data/quotes/subscribe/order_result.py +30 -0
  207. webull/data/quotes/subscribe/payload_type.py +19 -0
  208. webull/data/quotes/subscribe/quote_decoder.py +28 -0
  209. webull/data/quotes/subscribe/quote_result.py +47 -0
  210. webull/data/quotes/subscribe/snapshot_decoder.py +30 -0
  211. webull/data/quotes/subscribe/snapshot_result.py +69 -0
  212. webull/data/quotes/subscribe/tick_decoder.py +29 -0
  213. webull/data/quotes/subscribe/tick_result.py +47 -0
  214. webull/data/request/__init__.py +0 -0
  215. webull/data/request/get_batch_historical_bars_request.py +43 -0
  216. webull/data/request/get_corp_action_request.py +47 -0
  217. webull/data/request/get_eod_bars_request.py +32 -0
  218. webull/data/request/get_historical_bars_request.py +43 -0
  219. webull/data/request/get_instruments_request.py +30 -0
  220. webull/data/request/get_quotes_request.py +35 -0
  221. webull/data/request/get_snapshot_request.py +38 -0
  222. webull/data/request/get_tick_request.py +37 -0
  223. webull/data/request/subscribe_request.py +43 -0
  224. webull/data/request/unsubscribe_request.py +42 -0
  225. webull/trade/__init__.py +2 -0
  226. webull/trade/common/__init__.py +0 -0
  227. webull/trade/common/account_type.py +22 -0
  228. webull/trade/common/category.py +29 -0
  229. webull/trade/common/combo_ticker_type.py +23 -0
  230. webull/trade/common/combo_type.py +31 -0
  231. webull/trade/common/currency.py +24 -0
  232. webull/trade/common/forbid_reason.py +27 -0
  233. webull/trade/common/instrument_type.py +27 -0
  234. webull/trade/common/markets.py +27 -0
  235. webull/trade/common/order_entrust_type.py +21 -0
  236. webull/trade/common/order_side.py +23 -0
  237. webull/trade/common/order_status.py +25 -0
  238. webull/trade/common/order_tif.py +24 -0
  239. webull/trade/common/order_type.py +30 -0
  240. webull/trade/common/trade_policy.py +22 -0
  241. webull/trade/common/trading_date_type.py +24 -0
  242. webull/trade/common/trailing_type.py +23 -0
  243. webull/trade/events/__init__.py +0 -0
  244. webull/trade/events/default_retry_policy.py +64 -0
  245. webull/trade/events/events_pb2.py +43 -0
  246. webull/trade/events/events_pb2_grpc.py +66 -0
  247. webull/trade/events/signature_composer.py +61 -0
  248. webull/trade/events/types.py +21 -0
  249. webull/trade/request/__init__.py +0 -0
  250. webull/trade/request/cancel_order_request.py +28 -0
  251. webull/trade/request/get_account_balance_request.py +28 -0
  252. webull/trade/request/get_account_positions_request.py +30 -0
  253. webull/trade/request/get_account_profile_request.py +26 -0
  254. webull/trade/request/get_app_subscriptions.py +28 -0
  255. webull/trade/request/get_open_orders_request.py +30 -0
  256. webull/trade/request/get_order_detail_request.py +27 -0
  257. webull/trade/request/get_today_orders_request.py +31 -0
  258. webull/trade/request/get_trade_calendar_request.py +30 -0
  259. webull/trade/request/get_trade_instrument_detail_request.py +24 -0
  260. webull/trade/request/get_trade_security_detail_request.py +42 -0
  261. webull/trade/request/get_tradeable_instruments_request.py +27 -0
  262. webull/trade/request/palce_order_request.py +91 -0
  263. webull/trade/request/place_order_request_v2.py +58 -0
  264. webull/trade/request/replace_order_request.py +73 -0
  265. webull/trade/request/replace_order_request_v2.py +38 -0
  266. webull/trade/request/v2/__init__.py +0 -0
  267. webull/trade/request/v2/cancel_option_request.py +28 -0
  268. webull/trade/request/v2/cancel_order_request.py +28 -0
  269. webull/trade/request/v2/get_account_balance_request.py +28 -0
  270. webull/trade/request/v2/get_account_list.py +23 -0
  271. webull/trade/request/v2/get_account_positions_request.py +24 -0
  272. webull/trade/request/v2/get_order_detail_request.py +26 -0
  273. webull/trade/request/v2/get_order_history_request.py +35 -0
  274. webull/trade/request/v2/palce_order_request.py +87 -0
  275. webull/trade/request/v2/place_option_request.py +64 -0
  276. webull/trade/request/v2/preview_option_request.py +28 -0
  277. webull/trade/request/v2/preview_order_request.py +59 -0
  278. webull/trade/request/v2/replace_option_request.py +28 -0
  279. webull/trade/request/v2/replace_order_request.py +57 -0
  280. webull/trade/trade/__init__.py +0 -0
  281. webull/trade/trade/account_info.py +83 -0
  282. webull/trade/trade/order_operation.py +246 -0
  283. webull/trade/trade/trade_calendar.py +37 -0
  284. webull/trade/trade/trade_instrument.py +72 -0
  285. webull/trade/trade/v2/__init__.py +0 -0
  286. webull/trade/trade/v2/account_info_v2.py +55 -0
  287. webull/trade/trade/v2/order_operation_v2.py +206 -0
  288. webull/trade/trade_client.py +43 -0
  289. webull/trade/trade_events_client.py +233 -0
  290. webull_openapi_python_sdk-1.0.0.dist-info/METADATA +28 -0
  291. webull_openapi_python_sdk-1.0.0.dist-info/RECORD +295 -0
  292. webull_openapi_python_sdk-1.0.0.dist-info/WHEEL +5 -0
  293. webull_openapi_python_sdk-1.0.0.dist-info/licenses/LICENSE +202 -0
  294. webull_openapi_python_sdk-1.0.0.dist-info/licenses/NOTICE +56 -0
  295. webull_openapi_python_sdk-1.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,59 @@
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 typing import List
15
+
16
+ from webull.core.request import ApiRequest
17
+
18
+
19
+ class CloseContract:
20
+ def __init__(self, contract_id: str, quantity: str):
21
+ self.contract_id = contract_id
22
+ self.quantity = quantity
23
+
24
+ def to_dict(self):
25
+ return {
26
+ "contract_id": self.contract_id,
27
+ "quantity": self.quantity
28
+ }
29
+
30
+
31
+ class PreviewOrderRequest(ApiRequest):
32
+ def __init__(self):
33
+ super().__init__("/openapi/account/orders/preview", version='v2', method="POST", body_params={})
34
+ self._new_orders = []
35
+ self._current_order = {}
36
+ self.add_body_params("new_orders", self._new_orders)
37
+
38
+ def add_new_order_params(self, k, v):
39
+ self._current_order[k] = v
40
+
41
+ def set_account_id(self, account_id):
42
+ self.add_query_param("account_id", account_id)
43
+
44
+ def set_close_contracts(self, close_contracts: List[CloseContract]):
45
+ if not isinstance(close_contracts, list):
46
+ raise TypeError("close_contracts must be a list of CloseContract objects.")
47
+ self.add_new_order_params("close_contracts", [contract.to_dict() for contract in close_contracts])
48
+
49
+ def set_new_orders(self, current_order):
50
+ self._current_order.update({k: v for k, v in current_order.items() if v is not None and k != 'self'})
51
+ if 'close_contracts' in current_order and current_order['close_contracts'] is not None:
52
+ self.set_close_contracts(current_order['close_contracts'])
53
+
54
+ def finalize_order(self):
55
+ if self._current_order:
56
+ self._new_orders.append(self._current_order)
57
+ self._current_order = {}
58
+ else:
59
+ raise ValueError("No order fields have been set.")
@@ -0,0 +1,28 @@
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 ReplaceOptionRequest(ApiRequest):
21
+ def __init__(self):
22
+ super().__init__("/openapi/account/orders/option/replace", version='v2', method="POST", body_params={})
23
+
24
+ def set_modify_orders(self, modify_orders):
25
+ self.add_body_params("modify_orders", modify_orders)
26
+
27
+ def set_account_id(self, account_id):
28
+ self.add_query_param("account_id", account_id)
@@ -0,0 +1,57 @@
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
+ from typing import List
16
+ from webull.core.request import ApiRequest
17
+
18
+ class CloseContract:
19
+ def __init__(self, contract_id: str, quantity: str):
20
+ self.contract_id = contract_id
21
+ self.quantity = quantity
22
+
23
+ def to_dict(self):
24
+ return {
25
+ "contract_id": self.contract_id,
26
+ "quantity": self.quantity
27
+ }
28
+
29
+ class ReplaceOrderRequest(ApiRequest):
30
+ def __init__(self):
31
+ ApiRequest.__init__(self, "/openapi/account/orders/replace", version='v2', method="POST", body_params={})
32
+ self._modify_orders = []
33
+ self._current_order = {}
34
+ self.add_body_params("modify_orders", self._modify_orders)
35
+
36
+ def add_order_param(self, key, value):
37
+ self._current_order[key] = value
38
+
39
+ def set_account_id(self, account_id):
40
+ self.add_query_param("account_id", account_id)
41
+
42
+ def set_close_contracts(self, close_contracts: List[CloseContract]):
43
+ if not isinstance(close_contracts, list):
44
+ raise TypeError("close_contracts must be a list of CloseContract objects.")
45
+ self.add_order_param("close_contracts", [contract.to_dict() for contract in close_contracts])
46
+
47
+ def set_modify_orders(self, current_order):
48
+ self._current_order.update({k: v for k, v in current_order.items() if v is not None and k != 'self'})
49
+ if 'close_contracts' in current_order and current_order['close_contracts'] is not None:
50
+ self.set_close_contracts(current_order['close_contracts'])
51
+
52
+ def finalize_order(self):
53
+ if self._current_order:
54
+ self._modify_orders.append(self._current_order)
55
+ self._current_order = {}
56
+ else:
57
+ raise ValueError("No order fields have been set.")
File without changes
@@ -0,0 +1,83 @@
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 json.tool import main
18
+ from webull.trade.common.currency import Currency
19
+ from webull.trade.request.get_account_balance_request import AccountBalanceRequest
20
+ from webull.trade.request.get_account_positions_request import AccountPositionsRequest
21
+ from webull.trade.request.get_account_profile_request import AccountProfileRequest
22
+ from webull.trade.request.get_app_subscriptions import GetAppSubscriptions
23
+
24
+
25
+ class Account:
26
+ def __init__(self, api_client):
27
+ self.client = api_client
28
+
29
+ def get_account_profile(self, account_id):
30
+ """
31
+ Query account details according to account ID, which only contains static information.
32
+
33
+ :param account_id: Account ID
34
+ """
35
+ account_profile_request = AccountProfileRequest()
36
+ account_profile_request.set_account_id(account_id)
37
+ response = self.client.get_response(account_profile_request)
38
+ return response
39
+
40
+ def get_account_balance(self, account_id, total_asset_currency):
41
+ """
42
+ Query account assets according to account id.
43
+
44
+ :param account_id: Account ID
45
+ :param total_asset_currency: The currency in which the total assets are denominated: the value refers to Currency
46
+ in the dictionary value. If it is empty, it defaults to HKD
47
+ """
48
+ account_balance_request = AccountBalanceRequest()
49
+ account_balance_request.set_account_id(account_id)
50
+ account_balance_request.set_total_asset_currency(total_asset_currency)
51
+ response = self.client.get_response(account_balance_request)
52
+ return response
53
+
54
+ def get_account_position(self, account_id, page_size=10, last_instrument_id=None):
55
+ """
56
+ Query the account position list according to the account ID page.
57
+
58
+ :param account_id: Account ID
59
+ :param page_size: Number of entries per page: default value is 10,
60
+ and the maximum value is 100 with integers being filled.
61
+ :param last_instrument_id: The last target id of the previous page,if not passed,
62
+ the first page is checked by default
63
+ """
64
+ account_positions_request = AccountPositionsRequest()
65
+ account_positions_request.set_account_id(account_id)
66
+ account_positions_request.set_page_size(page_size)
67
+ if last_instrument_id is not None:
68
+ account_positions_request.set_last_instrument_id(last_instrument_id)
69
+ response = self.client.get_response(account_positions_request)
70
+ return response
71
+
72
+ def get_app_subscriptions(self, subscription_id=None):
73
+ """
74
+ Paginate to query the account list and return account information.
75
+
76
+ :param subscription_id: The order ID of the last piece of data, if no parameter is passed,
77
+ the first 100 pieces of data are queried by default
78
+ """
79
+ app_subscriptions = GetAppSubscriptions()
80
+ if subscription_id is not None:
81
+ app_subscriptions.set_subscription_id(subscription_id)
82
+ response = self.client.get_response(app_subscriptions)
83
+ return response
@@ -0,0 +1,246 @@
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.core.context.request_context_holder import RequestContextHolder
15
+ # coding=utf-8
16
+ from webull.trade.request.cancel_order_request import CancelOrderRequest
17
+ from webull.trade.request.get_open_orders_request import OpenOrdersListRequest
18
+ from webull.trade.request.get_order_detail_request import OrderDetailRequest
19
+ from webull.trade.request.get_today_orders_request import TodayOrdersListRequest
20
+ from webull.trade.request.palce_order_request import PlaceOrderRequest
21
+ from webull.trade.request.place_order_request_v2 import PlaceOrderRequestV2
22
+ from webull.trade.request.replace_order_request import ReplaceOrderRequest
23
+ from webull.trade.request.replace_order_request_v2 import ReplaceOrderRequestV2
24
+ from webull.trade.request.v2.cancel_option_request import CancelOptionRequest
25
+ from webull.trade.request.v2.place_option_request import PlaceOptionRequest
26
+ from webull.trade.request.v2.preview_option_request import PreviewOptionRequest
27
+ from webull.trade.request.v2.replace_option_request import ReplaceOptionRequest
28
+
29
+
30
+ class OrderOperation:
31
+ def __init__(self, api_client):
32
+ self.client = api_client
33
+
34
+ def place_order(self, account_id, qty, instrument_id, side, client_order_id, order_type,
35
+ extended_hours_trading, tif, limit_price=None, stop_price=None,
36
+ trailing_type=None, trailing_stop_step=None):
37
+ """
38
+ This interface is used by customers in Hong Kong to place orders, and supports placing orders in two markets:
39
+ Hong Kong stocks, and A shares (China Connect).
40
+
41
+ :param account_id: Account ID
42
+ :param qty: The amount of the equities to place an order, integer, the maximum value supported is 1000000 shares
43
+ :param instrument_id: Instrument ID.
44
+ :param side: Buy and sell direction.
45
+ :param client_order_id: Third-party order ID, and the maximum length of this field is 40.
46
+ :param order_type: Order Type.
47
+ :param extended_hours_trading: Whether to allow pre-market and post-market trading.
48
+ Market orders can only be false, and limit orders can be true or false..
49
+ :param tif: Order validity period.
50
+ :param limit_price: Order_type is LIMIT, STOP_LOSS_LIMIT, ENHANCED_LIMIT,
51
+ AT_AUCTION_LIMIT (at-auction limit order) and needs to be passed.
52
+ :param stop_price: When order_type is STOP_LOSS (stop-loss order), STOP_LOSS_LIMIT (stop-loss limit price),
53
+ it needs to pass.
54
+ :param trailing_type: Spread type of trailing stop order, trailing stop order to be transmitted.
55
+ :param trailing_stop_step: Spread value of trailing stop order, trailing stop order to be transmitted
56
+ """
57
+ place_order_request = PlaceOrderRequest()
58
+ place_order_request.set_account_id(account_id)
59
+ place_order_request.set_stock_order(client_order_id=client_order_id, instrument_id=instrument_id, qty=qty,
60
+ side=side, tif=tif, extended_hours_trading=extended_hours_trading,
61
+ order_type=order_type, limit_price=limit_price, stop_price=stop_price,
62
+ trailing_type=trailing_type, trailing_stop_step=trailing_stop_step)
63
+ place_order_request.add_custom_headers_from_context()
64
+ response = self.client.get_response(place_order_request)
65
+ return response
66
+
67
+ def replace_order(self, account_id, qty, instrument_id, side, client_order_id, order_type,
68
+ extended_hours_trading, tif, limit_price=None, stop_price=None,
69
+ trailing_type=None, trailing_stop_step=None):
70
+ """
71
+ Modify order.
72
+
73
+ :param account_id: Account ID
74
+ :param qty: The amount of the equities to place an order, integer, the maximum value supported is 1000000 shares
75
+ :param instrument_id: Instrument ID.
76
+ :param side: Buy and sell direction.
77
+ :param client_order_id: Third-party order ID, and the maximum length of this field is 40.
78
+ :param order_type: Order Type.
79
+ :param extended_hours_trading: Whether to allow pre-market and post-market trading.
80
+ Market orders can only be false, and limit orders can be true or false..
81
+ :param tif: Order validity period.
82
+ :param limit_price: Order_type is LIMIT, STOP_LOSS_LIMIT, ENHANCED_LIMIT,
83
+ AT_AUCTION_LIMIT (at-auction limit order) and needs to be passed.
84
+ :param stop_price: When order_type is STOP_LOSS (stop-loss order),
85
+ STOP_LOSS_LIMIT (stop-loss limit price), it needs to pass.
86
+ :param trailing_type: Spread type of trailing stop order, trailing stop order to be transmitted.
87
+ :param trailing_stop_step: Spread value of trailing stop order, trailing stop order to be transmitted
88
+ """
89
+ replace_order_request = ReplaceOrderRequest()
90
+ replace_order_request.set_account_id(account_id)
91
+ replace_order_request.set_stock_order(client_order_id=client_order_id, instrument_id=instrument_id, qty=qty,
92
+ side=side, tif=tif, extended_hours_trading=extended_hours_trading,
93
+ order_type=order_type, limit_price=limit_price, stop_price=stop_price,
94
+ trailing_type=trailing_type, trailing_stop_step=trailing_stop_step)
95
+ response = self.client.get_response(replace_order_request)
96
+ return response
97
+
98
+ def place_order_v2(self, account_id, stock_order):
99
+ place_order_request = PlaceOrderRequestV2()
100
+ place_order_request.set_account_id(account_id)
101
+ place_order_request.set_stock_order(stock_order)
102
+ place_order_request.add_custom_headers_from_context()
103
+ response = self.client.get_response(place_order_request)
104
+ return response
105
+
106
+ def replace_order_v2(self, account_id, stock_order):
107
+ replace_order_request = ReplaceOrderRequestV2()
108
+ replace_order_request.set_account_id(account_id)
109
+ replace_order_request.set_stock_order(stock_order)
110
+ response = self.client.get_response(replace_order_request)
111
+ return response
112
+
113
+ def cancel_order(self, account_id, client_order_id):
114
+ """
115
+ Cancel order.
116
+
117
+ :param account_id: Account ID
118
+ :param client_order_id: Third-party order ID, and the maximum length of this field is 40.
119
+ """
120
+ cancel_order_request = CancelOrderRequest()
121
+ cancel_order_request.set_account_id(account_id)
122
+ cancel_order_request.set_client_order_id(client_order_id)
123
+ response = self.client.get_response(cancel_order_request)
124
+ return response
125
+
126
+ def list_today_orders(self, account_id, page_size=10, last_client_order_id=None):
127
+ """
128
+ Paging query all orders of the day, the number of data returned each time can be specified,
129
+ the maximum value is 100.
130
+
131
+ :param account_id: Account ID
132
+ :param page_size: For the number of entries per page, the default value is 10,
133
+ and the maximum value is 100. Integers can be filled.
134
+
135
+ :param last_client_order_id: The 3rd party order ID is not passed,
136
+ and the default check is conducted on the first page.
137
+ """
138
+ today_orders_list_request = TodayOrdersListRequest()
139
+ today_orders_list_request.set_account_id(account_id)
140
+ today_orders_list_request.set_page_size(page_size)
141
+ if last_client_order_id is not None:
142
+ today_orders_list_request.set_last_client_order_id(last_client_order_id)
143
+ response = self.client.get_response(today_orders_list_request)
144
+ return response
145
+
146
+ def list_open_orders(self, account_id, page_size=10, last_client_order_id=None):
147
+ """
148
+ Paging query pending orders.
149
+
150
+ :param account_id: Account ID
151
+ :param page_size: For the number of entries per page, the default value is 10, and the maximum value is 100.
152
+ Integers can be filled.
153
+ :param last_client_order_id: The 3rd party order ID is not passed,
154
+ and the default check is conducted on the first page.
155
+ """
156
+ open_orders_list_request = OpenOrdersListRequest()
157
+ open_orders_list_request.set_account_id(account_id)
158
+ open_orders_list_request.set_page_size(page_size)
159
+ if last_client_order_id is not None:
160
+ open_orders_list_request.set_last_client_order_id(last_client_order_id)
161
+ response = self.client.get_response(open_orders_list_request)
162
+ return response
163
+
164
+ def query_order_detail(self, account_id, client_order_id):
165
+ """
166
+ Paging query pending orders.
167
+
168
+ :param account_id: Account ID
169
+ :param client_order_id: The 3rd party order ID.
170
+ """
171
+ order_detail_request = OrderDetailRequest()
172
+ order_detail_request.set_account_id(account_id)
173
+ order_detail_request.set_client_order_id(client_order_id)
174
+ response = self.client.get_response(order_detail_request)
175
+ return response
176
+
177
+ def preview_option(self, account_id, new_orders):
178
+ """
179
+ This interface is exclusively available for Webull Hong Kong brokerage clients.
180
+ Currently, it does not support Webull Japan or Webull U.S. clients,
181
+ but support will be gradually introduced in the future.
182
+ """
183
+ preview_option_request = PreviewOptionRequest()
184
+ preview_option_request.set_new_orders(new_orders)
185
+ preview_option_request.set_account_id(account_id)
186
+ response = self.client.get_response(preview_option_request)
187
+ return response
188
+
189
+ def place_option(self, account_id, new_orders):
190
+ """
191
+ This interface is exclusively available for Webull Hong Kong brokerage clients.
192
+ Currently, it does not support Webull Japan or Webull U.S. clients,
193
+ but support will be gradually introduced in the future.
194
+ """
195
+ place_option_request = PlaceOptionRequest()
196
+ place_option_request.set_new_orders(new_orders)
197
+ place_option_request.set_account_id(account_id)
198
+ place_option_request.add_custom_headers_from_order(new_orders)
199
+ place_option_request.add_custom_headers_from_context()
200
+ response = self.client.get_response(place_option_request)
201
+ return response
202
+
203
+ def replace_option(self, account_id, modify_orders):
204
+ """
205
+ This interface is exclusively available for Webull Hong Kong brokerage clients.
206
+ Currently, it does not support Webull Japan or Webull U.S. clients,
207
+ but support will be gradually introduced in the future.
208
+ """
209
+ replace_option_request = ReplaceOptionRequest()
210
+ replace_option_request.set_modify_orders(modify_orders)
211
+ replace_option_request.set_account_id(account_id)
212
+ response = self.client.get_response(replace_option_request)
213
+ return response
214
+
215
+ def cancel_option(self, account_id, client_order_id):
216
+ """
217
+ This interface is exclusively available for Webull Hong Kong brokerage clients.
218
+ Currently, it does not support Webull Japan or Webull U.S. clients,
219
+ but support will be gradually introduced in the future.
220
+ """
221
+ cancel_option_request = CancelOptionRequest()
222
+ cancel_option_request.set_client_order_id(client_order_id)
223
+ cancel_option_request.set_account_id(account_id)
224
+ response = self.client.get_response(cancel_option_request)
225
+ return response
226
+
227
+ def add_custom_headers(self, headers_map: dict):
228
+ """
229
+ This is an optional feature; you can still make a request without setting it.
230
+ If set, you can specify certain headers to perform specific operations.
231
+ Note: If you set a header, call remove_custom_headers to clean up the header after the request is completed.
232
+
233
+ Currently supported header keys and functions:
234
+ Key:category {See Also: category}
235
+ Function: Frequency limit rules, please refer to the document for details. currently only supports Hong Kong
236
+ """
237
+ if not headers_map or len(headers_map) == 0:
238
+ return
239
+
240
+ RequestContextHolder.get().update(headers_map)
241
+
242
+ def remove_custom_headers(self):
243
+ """
244
+ Clearing headers after the request is completed.
245
+ """
246
+ RequestContextHolder.clear()
@@ -0,0 +1,37 @@
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.trade.request.get_trade_calendar_request import TradeCalendarRequest
15
+
16
+
17
+ class TradeCalendar:
18
+
19
+ def __init__(self, api_client):
20
+ self.client = api_client
21
+
22
+ def get_trade_calendar(self, market, start, end):
23
+ """
24
+ Get the trading calendar for the specified market.
25
+ Trading days are obtained by excluding weekends and holidays, and the dates of temporary market closures are
26
+ not excluded.
27
+
28
+ :param market: Markets, enumeration
29
+ :param start: Start date
30
+ :param end: End date
31
+ """
32
+ trade_calendar_request = TradeCalendarRequest()
33
+ trade_calendar_request.set_market(market)
34
+ trade_calendar_request.set_start(start)
35
+ trade_calendar_request.set_end(end)
36
+ response = self.client.get_response(trade_calendar_request)
37
+ return response
@@ -0,0 +1,72 @@
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.trade.request.get_trade_instrument_detail_request import TradeInstrumentDetailRequest
15
+ from webull.trade.request.get_trade_security_detail_request import TradeSecurityDetailRequest
16
+ from webull.trade.request.get_tradeable_instruments_request import TradeableInstrumentRequest
17
+
18
+
19
+ class TradeInstrument:
20
+
21
+ def __init__(self, api_client):
22
+ self.client = api_client
23
+
24
+ def get_trade_instrument_detail(self, instrument_id):
25
+ """
26
+ Query the information of traded symbol.
27
+
28
+ :param instrument_id: Symbol ID
29
+ """
30
+ instrument_detail_request = TradeInstrumentDetailRequest()
31
+ instrument_detail_request.set_instrument_id(instrument_id)
32
+ response = self.client.get_response(instrument_detail_request)
33
+ return response
34
+
35
+ def get_trade_security_detail(self, symbol, market, instrument_super_type, instrument_type, strike_price, init_exp_date):
36
+ """
37
+ Query the information of traded symbol.
38
+
39
+ :param symbol: The ticker symbol or code representing a specific financial instrument or security.
40
+ :param market: e.g. US, HK.
41
+ :param instrument_super_type: Asset Class (e.g. EQUITY, OPTION.)
42
+ :param instrument_type: Type of underlying equity,required when querying for options information (e.g., WARRANT, UNITS, ETF, CALL_OPTION, PUT_OPTION).
43
+ :param strike_price: Option Strike Price, required when querying for options information.
44
+ :param init_exp_date: Option Expiration Date, Format: yyyy-MM-dd, required when querying for options information.
45
+ """
46
+ security_detail_request = TradeSecurityDetailRequest()
47
+ security_detail_request.set_symbol(symbol)
48
+ security_detail_request.set_market(market)
49
+ security_detail_request.set_instrument_super_type(instrument_super_type)
50
+ security_detail_request.set_instrument_type(instrument_type)
51
+ security_detail_request.set_strike_price(strike_price)
52
+ security_detail_request.set_init_exp_date(init_exp_date)
53
+ response = self.client.get_response(security_detail_request)
54
+ return response
55
+
56
+ def get_tradeable_instruments(self, last_instrument_id=None, page_size=10):
57
+ """
58
+ Only for Webull JP
59
+
60
+ Paging query tradable instruments.
61
+
62
+ :param last_security_id: Pagination-specific id, if not passed, the first page will be searched by default
63
+
64
+ :param page_size: Number of entries per page: default value is 10,
65
+ and the maximum value is 100 with integers being filled.
66
+ """
67
+ tradeable_instruments_request = TradeableInstrumentRequest()
68
+ if last_instrument_id is not None:
69
+ tradeable_instruments_request.set_last_instrument_id(last_instrument_id)
70
+ tradeable_instruments_request.set_page_size(page_size)
71
+ response = self.client.get_response(tradeable_instruments_request)
72
+ return response
File without changes
@@ -0,0 +1,55 @@
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.trade.request.v2.get_account_balance_request import AccountBalanceRequest
17
+ from webull.trade.request.v2.get_account_list import GetAccountList
18
+ from webull.trade.request.v2.get_account_positions_request import AccountPositionsRequest
19
+
20
+
21
+ class AccountV2:
22
+ def __init__(self, api_client):
23
+ self.client = api_client
24
+
25
+ def get_account_list(self):
26
+ """
27
+ This interface is currently available only to individual brokerage customers in Webull Japan
28
+ and institutional brokerage clients in Webull Hong Kong. It is not yet available to
29
+ Webull US brokerage customers, but support will be introduced progressively in the future.
30
+ """
31
+ account_list = GetAccountList()
32
+ response = self.client.get_response(account_list)
33
+ return response
34
+
35
+ def get_account_balance(self, account_id):
36
+ """
37
+ This interface is currently available only to individual brokerage customers in Webull Japan
38
+ and institutional brokerage clients in Webull Hong Kong. It is not yet available to
39
+ Webull US brokerage customers, but support will be introduced progressively in the future.
40
+ """
41
+ account_balance_request = AccountBalanceRequest()
42
+ account_balance_request.set_account_id(account_id)
43
+ response = self.client.get_response(account_balance_request)
44
+ return response
45
+
46
+ def get_account_position(self, account_id):
47
+ """
48
+ This interface is currently available only to individual brokerage customers in Webull Japan
49
+ and institutional brokerage clients in Webull Hong Kong. It is not yet available to
50
+ Webull US brokerage customers, but support will be introduced progressively in the future.
51
+ """
52
+ account_positions_request = AccountPositionsRequest()
53
+ account_positions_request.set_account_id(account_id)
54
+ response = self.client.get_response(account_positions_request)
55
+ return response