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.
- samples/__init__.py +1 -0
- samples/data/__init__.py +1 -0
- samples/data/data_client.py +57 -0
- samples/data/data_streaming_client.py +86 -0
- samples/data/data_streaming_client_async.py +101 -0
- samples/trade/__init__.py +0 -0
- samples/trade/trade_client.py +163 -0
- samples/trade/trade_client_v2.py +181 -0
- samples/trade/trade_event_client.py +47 -0
- webull/__init__.py +1 -0
- webull/core/__init__.py +12 -0
- webull/core/auth/__init__.py +0 -0
- webull/core/auth/algorithm/__init__.py +0 -0
- webull/core/auth/algorithm/sha_hmac1.py +65 -0
- webull/core/auth/algorithm/sha_hmac256.py +75 -0
- webull/core/auth/composer/__init__.py +0 -0
- webull/core/auth/composer/default_signature_composer.py +125 -0
- webull/core/auth/credentials.py +46 -0
- webull/core/auth/signers/__init__.py +0 -0
- webull/core/auth/signers/app_key_signer.py +72 -0
- webull/core/auth/signers/signer.py +48 -0
- webull/core/auth/signers/signer_factory.py +58 -0
- webull/core/cache/__init__.py +225 -0
- webull/core/client.py +410 -0
- webull/core/common/__init__.py +0 -0
- webull/core/common/api_type.py +19 -0
- webull/core/common/easy_enum.py +35 -0
- webull/core/common/region.py +7 -0
- webull/core/compat.py +85 -0
- webull/core/context/__init__.py +0 -0
- webull/core/context/request_context_holder.py +33 -0
- webull/core/data/endpoints.json +22 -0
- webull/core/data/retry_config.json +15 -0
- webull/core/endpoint/__init__.py +8 -0
- webull/core/endpoint/chained_endpoint_resolver.py +57 -0
- webull/core/endpoint/default_endpoint_resolver.py +60 -0
- webull/core/endpoint/local_config_regional_endpoint_resolver.py +77 -0
- webull/core/endpoint/resolver_endpoint_request.py +46 -0
- webull/core/endpoint/user_customized_endpoint_resolver.py +55 -0
- webull/core/exception/__init__.py +0 -0
- webull/core/exception/error_code.py +23 -0
- webull/core/exception/error_msg.py +21 -0
- webull/core/exception/exceptions.py +53 -0
- webull/core/headers.py +57 -0
- webull/core/http/__init__.py +0 -0
- webull/core/http/initializer/__init__.py +0 -0
- webull/core/http/initializer/client_initializer.py +79 -0
- webull/core/http/initializer/token/__init__.py +0 -0
- webull/core/http/initializer/token/bean/__init__.py +0 -0
- webull/core/http/initializer/token/bean/access_token.py +40 -0
- webull/core/http/initializer/token/bean/check_token_request.py +44 -0
- webull/core/http/initializer/token/bean/create_token_request.py +45 -0
- webull/core/http/initializer/token/bean/refresh_token_request.py +44 -0
- webull/core/http/initializer/token/token_manager.py +208 -0
- webull/core/http/initializer/token/token_operation.py +72 -0
- webull/core/http/method_type.py +43 -0
- webull/core/http/protocol_type.py +43 -0
- webull/core/http/request.py +121 -0
- webull/core/http/response.py +166 -0
- webull/core/request.py +278 -0
- webull/core/retry/__init__.py +0 -0
- webull/core/retry/backoff_strategy.py +102 -0
- webull/core/retry/retry_condition.py +214 -0
- webull/core/retry/retry_policy.py +63 -0
- webull/core/retry/retry_policy_context.py +51 -0
- webull/core/utils/__init__.py +0 -0
- webull/core/utils/common.py +62 -0
- webull/core/utils/data.py +25 -0
- webull/core/utils/desensitize.py +33 -0
- webull/core/utils/validation.py +49 -0
- webull/core/vendored/__init__.py +0 -0
- webull/core/vendored/requests/__init__.py +94 -0
- webull/core/vendored/requests/__version__.py +28 -0
- webull/core/vendored/requests/_internal_utils.py +56 -0
- webull/core/vendored/requests/adapters.py +539 -0
- webull/core/vendored/requests/api.py +166 -0
- webull/core/vendored/requests/auth.py +307 -0
- webull/core/vendored/requests/certs.py +34 -0
- webull/core/vendored/requests/compat.py +85 -0
- webull/core/vendored/requests/cookies.py +555 -0
- webull/core/vendored/requests/exceptions.py +136 -0
- webull/core/vendored/requests/help.py +134 -0
- webull/core/vendored/requests/hooks.py +48 -0
- webull/core/vendored/requests/models.py +960 -0
- webull/core/vendored/requests/packages/__init__.py +17 -0
- webull/core/vendored/requests/packages/certifi/__init__.py +17 -0
- webull/core/vendored/requests/packages/certifi/__main__.py +16 -0
- webull/core/vendored/requests/packages/certifi/cacert.pem +4433 -0
- webull/core/vendored/requests/packages/certifi/core.py +51 -0
- webull/core/vendored/requests/packages/chardet/__init__.py +53 -0
- webull/core/vendored/requests/packages/chardet/big5freq.py +400 -0
- webull/core/vendored/requests/packages/chardet/big5prober.py +61 -0
- webull/core/vendored/requests/packages/chardet/chardistribution.py +247 -0
- webull/core/vendored/requests/packages/chardet/charsetgroupprober.py +120 -0
- webull/core/vendored/requests/packages/chardet/charsetprober.py +159 -0
- webull/core/vendored/requests/packages/chardet/cli/__init__.py +1 -0
- webull/core/vendored/requests/packages/chardet/cli/chardetect.py +99 -0
- webull/core/vendored/requests/packages/chardet/codingstatemachine.py +102 -0
- webull/core/vendored/requests/packages/chardet/compat.py +48 -0
- webull/core/vendored/requests/packages/chardet/cp949prober.py +63 -0
- webull/core/vendored/requests/packages/chardet/enums.py +90 -0
- webull/core/vendored/requests/packages/chardet/escprober.py +115 -0
- webull/core/vendored/requests/packages/chardet/escsm.py +260 -0
- webull/core/vendored/requests/packages/chardet/eucjpprober.py +106 -0
- webull/core/vendored/requests/packages/chardet/euckrfreq.py +209 -0
- webull/core/vendored/requests/packages/chardet/euckrprober.py +61 -0
- webull/core/vendored/requests/packages/chardet/euctwfreq.py +401 -0
- webull/core/vendored/requests/packages/chardet/euctwprober.py +60 -0
- webull/core/vendored/requests/packages/chardet/gb2312freq.py +297 -0
- webull/core/vendored/requests/packages/chardet/gb2312prober.py +60 -0
- webull/core/vendored/requests/packages/chardet/hebrewprober.py +306 -0
- webull/core/vendored/requests/packages/chardet/jisfreq.py +339 -0
- webull/core/vendored/requests/packages/chardet/jpcntx.py +247 -0
- webull/core/vendored/requests/packages/chardet/langbulgarianmodel.py +242 -0
- webull/core/vendored/requests/packages/chardet/langcyrillicmodel.py +347 -0
- webull/core/vendored/requests/packages/chardet/langgreekmodel.py +239 -0
- webull/core/vendored/requests/packages/chardet/langhebrewmodel.py +214 -0
- webull/core/vendored/requests/packages/chardet/langhungarianmodel.py +239 -0
- webull/core/vendored/requests/packages/chardet/langthaimodel.py +213 -0
- webull/core/vendored/requests/packages/chardet/langturkishmodel.py +207 -0
- webull/core/vendored/requests/packages/chardet/latin1prober.py +159 -0
- webull/core/vendored/requests/packages/chardet/mbcharsetprober.py +105 -0
- webull/core/vendored/requests/packages/chardet/mbcsgroupprober.py +68 -0
- webull/core/vendored/requests/packages/chardet/mbcssm.py +586 -0
- webull/core/vendored/requests/packages/chardet/sbcharsetprober.py +146 -0
- webull/core/vendored/requests/packages/chardet/sbcsgroupprober.py +87 -0
- webull/core/vendored/requests/packages/chardet/sjisprober.py +106 -0
- webull/core/vendored/requests/packages/chardet/universaldetector.py +300 -0
- webull/core/vendored/requests/packages/chardet/utf8prober.py +96 -0
- webull/core/vendored/requests/packages/chardet/version.py +23 -0
- webull/core/vendored/requests/packages/urllib3/__init__.py +114 -0
- webull/core/vendored/requests/packages/urllib3/_collections.py +346 -0
- webull/core/vendored/requests/packages/urllib3/connection.py +405 -0
- webull/core/vendored/requests/packages/urllib3/connectionpool.py +910 -0
- webull/core/vendored/requests/packages/urllib3/contrib/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_appengine_environ.py +44 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/bindings.py +607 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/low_level.py +360 -0
- webull/core/vendored/requests/packages/urllib3/contrib/appengine.py +303 -0
- webull/core/vendored/requests/packages/urllib3/contrib/ntlmpool.py +125 -0
- webull/core/vendored/requests/packages/urllib3/contrib/pyopenssl.py +484 -0
- webull/core/vendored/requests/packages/urllib3/contrib/securetransport.py +818 -0
- webull/core/vendored/requests/packages/urllib3/contrib/socks.py +206 -0
- webull/core/vendored/requests/packages/urllib3/exceptions.py +260 -0
- webull/core/vendored/requests/packages/urllib3/fields.py +192 -0
- webull/core/vendored/requests/packages/urllib3/filepost.py +112 -0
- webull/core/vendored/requests/packages/urllib3/packages/__init__.py +19 -0
- webull/core/vendored/requests/packages/urllib3/packages/backports/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/packages/backports/makefile.py +67 -0
- webull/core/vendored/requests/packages/urllib3/packages/ordered_dict.py +273 -0
- webull/core/vendored/requests/packages/urllib3/packages/six.py +882 -0
- webull/core/vendored/requests/packages/urllib3/packages/socks.py +887 -0
- webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +19 -0
- webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py +170 -0
- webull/core/vendored/requests/packages/urllib3/poolmanager.py +467 -0
- webull/core/vendored/requests/packages/urllib3/request.py +164 -0
- webull/core/vendored/requests/packages/urllib3/response.py +721 -0
- webull/core/vendored/requests/packages/urllib3/util/__init__.py +68 -0
- webull/core/vendored/requests/packages/urllib3/util/connection.py +148 -0
- webull/core/vendored/requests/packages/urllib3/util/queue.py +35 -0
- webull/core/vendored/requests/packages/urllib3/util/request.py +132 -0
- webull/core/vendored/requests/packages/urllib3/util/response.py +101 -0
- webull/core/vendored/requests/packages/urllib3/util/retry.py +426 -0
- webull/core/vendored/requests/packages/urllib3/util/selectors.py +601 -0
- webull/core/vendored/requests/packages/urllib3/util/ssl_.py +396 -0
- webull/core/vendored/requests/packages/urllib3/util/timeout.py +256 -0
- webull/core/vendored/requests/packages/urllib3/util/url.py +252 -0
- webull/core/vendored/requests/packages/urllib3/util/wait.py +164 -0
- webull/core/vendored/requests/packages.py +28 -0
- webull/core/vendored/requests/sessions.py +750 -0
- webull/core/vendored/requests/status_codes.py +105 -0
- webull/core/vendored/requests/structures.py +119 -0
- webull/core/vendored/requests/utils.py +916 -0
- webull/core/vendored/six.py +905 -0
- webull/data/__init__.py +3 -0
- webull/data/common/__init__.py +0 -0
- webull/data/common/category.py +26 -0
- webull/data/common/connect_ack.py +29 -0
- webull/data/common/direction.py +25 -0
- webull/data/common/exchange_code.py +33 -0
- webull/data/common/exercise_style.py +22 -0
- webull/data/common/expiration_cycle.py +26 -0
- webull/data/common/instrument_status.py +23 -0
- webull/data/common/option_type.py +20 -0
- webull/data/common/subscribe_type.py +22 -0
- webull/data/common/timespan.py +29 -0
- webull/data/data_client.py +35 -0
- webull/data/data_streaming_client.py +89 -0
- webull/data/internal/__init__.py +0 -0
- webull/data/internal/default_retry_policy.py +84 -0
- webull/data/internal/exceptions.py +60 -0
- webull/data/internal/quotes_client.py +314 -0
- webull/data/internal/quotes_decoder.py +40 -0
- webull/data/internal/quotes_payload_decoder.py +35 -0
- webull/data/internal/quotes_topic.py +36 -0
- webull/data/quotes/__init__.py +0 -0
- webull/data/quotes/instrument.py +33 -0
- webull/data/quotes/market_data.py +187 -0
- webull/data/quotes/market_streaming_data.py +66 -0
- webull/data/quotes/subscribe/__init__.py +0 -0
- webull/data/quotes/subscribe/ask_bid_result.py +49 -0
- webull/data/quotes/subscribe/basic_result.py +45 -0
- webull/data/quotes/subscribe/broker_result.py +33 -0
- webull/data/quotes/subscribe/message_pb2.py +37 -0
- webull/data/quotes/subscribe/order_result.py +30 -0
- webull/data/quotes/subscribe/payload_type.py +19 -0
- webull/data/quotes/subscribe/quote_decoder.py +28 -0
- webull/data/quotes/subscribe/quote_result.py +47 -0
- webull/data/quotes/subscribe/snapshot_decoder.py +30 -0
- webull/data/quotes/subscribe/snapshot_result.py +69 -0
- webull/data/quotes/subscribe/tick_decoder.py +29 -0
- webull/data/quotes/subscribe/tick_result.py +47 -0
- webull/data/request/__init__.py +0 -0
- webull/data/request/get_batch_historical_bars_request.py +43 -0
- webull/data/request/get_corp_action_request.py +47 -0
- webull/data/request/get_eod_bars_request.py +32 -0
- webull/data/request/get_historical_bars_request.py +43 -0
- webull/data/request/get_instruments_request.py +30 -0
- webull/data/request/get_quotes_request.py +35 -0
- webull/data/request/get_snapshot_request.py +38 -0
- webull/data/request/get_tick_request.py +37 -0
- webull/data/request/subscribe_request.py +43 -0
- webull/data/request/unsubscribe_request.py +42 -0
- webull/trade/__init__.py +2 -0
- webull/trade/common/__init__.py +0 -0
- webull/trade/common/account_type.py +22 -0
- webull/trade/common/category.py +29 -0
- webull/trade/common/combo_ticker_type.py +23 -0
- webull/trade/common/combo_type.py +31 -0
- webull/trade/common/currency.py +24 -0
- webull/trade/common/forbid_reason.py +27 -0
- webull/trade/common/instrument_type.py +27 -0
- webull/trade/common/markets.py +27 -0
- webull/trade/common/order_entrust_type.py +21 -0
- webull/trade/common/order_side.py +23 -0
- webull/trade/common/order_status.py +25 -0
- webull/trade/common/order_tif.py +24 -0
- webull/trade/common/order_type.py +30 -0
- webull/trade/common/trade_policy.py +22 -0
- webull/trade/common/trading_date_type.py +24 -0
- webull/trade/common/trailing_type.py +23 -0
- webull/trade/events/__init__.py +0 -0
- webull/trade/events/default_retry_policy.py +64 -0
- webull/trade/events/events_pb2.py +43 -0
- webull/trade/events/events_pb2_grpc.py +66 -0
- webull/trade/events/signature_composer.py +61 -0
- webull/trade/events/types.py +21 -0
- webull/trade/request/__init__.py +0 -0
- webull/trade/request/cancel_order_request.py +28 -0
- webull/trade/request/get_account_balance_request.py +28 -0
- webull/trade/request/get_account_positions_request.py +30 -0
- webull/trade/request/get_account_profile_request.py +26 -0
- webull/trade/request/get_app_subscriptions.py +28 -0
- webull/trade/request/get_open_orders_request.py +30 -0
- webull/trade/request/get_order_detail_request.py +27 -0
- webull/trade/request/get_today_orders_request.py +31 -0
- webull/trade/request/get_trade_calendar_request.py +30 -0
- webull/trade/request/get_trade_instrument_detail_request.py +24 -0
- webull/trade/request/get_trade_security_detail_request.py +42 -0
- webull/trade/request/get_tradeable_instruments_request.py +27 -0
- webull/trade/request/palce_order_request.py +91 -0
- webull/trade/request/place_order_request_v2.py +58 -0
- webull/trade/request/replace_order_request.py +73 -0
- webull/trade/request/replace_order_request_v2.py +38 -0
- webull/trade/request/v2/__init__.py +0 -0
- webull/trade/request/v2/cancel_option_request.py +28 -0
- webull/trade/request/v2/cancel_order_request.py +28 -0
- webull/trade/request/v2/get_account_balance_request.py +28 -0
- webull/trade/request/v2/get_account_list.py +23 -0
- webull/trade/request/v2/get_account_positions_request.py +24 -0
- webull/trade/request/v2/get_order_detail_request.py +26 -0
- webull/trade/request/v2/get_order_history_request.py +35 -0
- webull/trade/request/v2/palce_order_request.py +87 -0
- webull/trade/request/v2/place_option_request.py +64 -0
- webull/trade/request/v2/preview_option_request.py +28 -0
- webull/trade/request/v2/preview_order_request.py +59 -0
- webull/trade/request/v2/replace_option_request.py +28 -0
- webull/trade/request/v2/replace_order_request.py +57 -0
- webull/trade/trade/__init__.py +0 -0
- webull/trade/trade/account_info.py +83 -0
- webull/trade/trade/order_operation.py +246 -0
- webull/trade/trade/trade_calendar.py +37 -0
- webull/trade/trade/trade_instrument.py +72 -0
- webull/trade/trade/v2/__init__.py +0 -0
- webull/trade/trade/v2/account_info_v2.py +55 -0
- webull/trade/trade/v2/order_operation_v2.py +206 -0
- webull/trade/trade_client.py +43 -0
- webull/trade/trade_events_client.py +233 -0
- webull_openapi_python_sdk-1.0.0.dist-info/METADATA +28 -0
- webull_openapi_python_sdk-1.0.0.dist-info/RECORD +295 -0
- webull_openapi_python_sdk-1.0.0.dist-info/WHEEL +5 -0
- webull_openapi_python_sdk-1.0.0.dist-info/licenses/LICENSE +202 -0
- webull_openapi_python_sdk-1.0.0.dist-info/licenses/NOTICE +56 -0
- 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
|