Skip to content

Commit eed3f03

Browse files
author
方佳
committed
Merge branch 'main_260523_merge' into 'main'
feat: New support added for the SG market, futures orders now supported in the HK region. See merge request webull/webull-openapi-mcp!4
2 parents 2977330 + e689a72 commit eed3f03

11 files changed

Lines changed: 195 additions & 59 deletions

File tree

‎.env.example‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ WEBULL_APP_SECRET=
2020
# Set to 'prod' for live trading (use with caution)
2121
# WEBULL_ENVIRONMENT=uat
2222

23-
# Region ID: us, hk, or jp
23+
# Region ID: us, hk, jp, or sg
2424
# Default: us
2525
# WEBULL_REGION_ID=us
2626

‎README.md‎

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ See [DISCLAIMER.md](DISCLAIMER.md) for the full disclaimer.
1717

1818
## Features
1919

20-
- **Multi-Region Support** — US, HK, and JP regions with region-specific order types, trading sessions, and validation
20+
- **Multi-Region Support** — US, HK, JP, and SG regions with region-specific order types, trading sessions, and validation
2121
- **Market Data** — Real-time snapshots, tick data, quotes (depth), footprint, and OHLCV bars for stocks, futures, crypto, and event contracts
2222
- **NOII Data** — Net Order Imbalance Indicator bars and snapshots for US stock opening/closing auctions
2323
- **Screener** — Top gainers/losers and most active stocks ranking
@@ -92,11 +92,13 @@ Here are some prompts you can use with your AI assistant:
9292
- US: [developer.webull.com](https://developer.webull.com/apis/home)
9393
- HK: [developer.webull.hk](https://developer.webull.hk/apis/home)
9494
- JP: [developer.webull.co.jp](https://developer.webull.co.jp/)
95+
- SG: [developer.webull.com.sg](https://developer.webull.com.sg/apis/home)
9596
2. **API Credentials** — Obtain your `App Key` and `App Secret`
9697
3. **Market Data Subscription** — Subscribe to quotes for market data access:
9798
- US: [webullapp.com/quote](https://www.webullapp.com/quote) | [Guide](https://developer.webull.com/apis/docs/market-data-api/subscribe-quotes)
9899
- HK: [webullapp.hk/quote](https://www.webullapp.hk/quote) | [Guide](https://developer.webull.hk/apis/docs/market-data-api/subscribe-quotes)
99100
- JP: [webull.co.jp/pricing](https://www.webull.co.jp/pricing) | [Guide](https://developer.webull.co.jp/api-doc/market-data/subscribe-quotes/)
101+
- SG: [webull.com.sg/quote](https://www.webull.com.sg/quote) | [Guide](https://developer.webull.com.sg/apis/docs/market-data-api/subscribe-quotes)
100102
4. **Python 3.10+**
101103
5. **uv** (recommended) — [Install guide](https://docs.astral.sh/uv/getting-started/installation/)
102104

@@ -226,7 +228,7 @@ Add to your MCP configuration:
226228
| `WEBULL_APP_KEY` | App Key (required) | — |
227229
| `WEBULL_APP_SECRET` | App Secret (required) | — |
228230
| `WEBULL_ENVIRONMENT` | `uat` (sandbox) or `prod` | `uat` |
229-
| `WEBULL_REGION_ID` | `us`, `hk`, or `jp` | `us` |
231+
| `WEBULL_REGION_ID` | `us`, `hk`, `jp`, or `sg` | `us` |
230232
| `WEBULL_TOOLSETS` | Enabled tool categories (comma-separated). Valid values: `account`, `market-data`, `trading`, `instrument` | (all enabled) |
231233
| `WEBULL_MAX_ORDER_NOTIONAL_USD` | Max order value for US market (USD) | `10000` |
232234
| `WEBULL_MAX_ORDER_NOTIONAL_HKD` | Max order value for HK market (HKD) | `80000` |
@@ -238,7 +240,7 @@ Add to your MCP configuration:
238240
| `WEBULL_AUDIT_LOG_FILE` | Audit log file path | stderr only |
239241
| `WEBULL_LOG_LEVEL` | SDK log level | `WARNING` |
240242

241-
> **Note:** `WEBULL_REGION_ID=us` represents **Webull US** ([developer.webull.com](https://developer.webull.com/apis/home)), `WEBULL_REGION_ID=hk` represents **Webull Hong Kong** ([developer.webull.hk](https://developer.webull.hk/apis/home)), and `WEBULL_REGION_ID=jp` represents **Webull Japan** ([developer.webull.co.jp](https://developer.webull.co.jp/)).
243+
> **Note:** `WEBULL_REGION_ID=us` represents **Webull US** ([developer.webull.com](https://developer.webull.com/apis/home)), `WEBULL_REGION_ID=hk` represents **Webull Hong Kong** ([developer.webull.hk](https://developer.webull.hk/apis/home)), `WEBULL_REGION_ID=jp` represents **Webull Japan** ([developer.webull.co.jp](https://developer.webull.co.jp/)), and `WEBULL_REGION_ID=sg` represents **Webull Singapore** ([developer.webull.com.sg](https://developer.webull.com.sg/apis/home)).
242244
243245
See [.env.example](.env.example) for full configuration template.
244246

@@ -250,57 +252,58 @@ See [.env.example](.env.example) for full configuration template.
250252

251253
| Category | Tools | Region |
252254
|----------|-------|--------|
253-
| **Stock** | `get_stock_tick`, `get_stock_snapshot`, `get_stock_quotes`, `get_stock_footprint`, `get_stock_bars`, `get_stock_bars_single`, `get_stock_noii_bars`, `get_stock_noii_snapshot` | US, HK, JP |
254-
| **Futures** | `get_futures_tick`, `get_futures_snapshot`, `get_futures_depth`, `get_futures_bars`, `get_futures_footprint` | US |
255+
| **Stock** | `get_stock_tick`, `get_stock_snapshot`, `get_stock_quotes`, `get_stock_footprint`, `get_stock_bars`, `get_stock_bars_single`, `get_stock_noii_bars`, `get_stock_noii_snapshot` | US, HK, JP, SG |
256+
| **Futures** | `get_futures_tick`, `get_futures_snapshot`, `get_futures_depth`, `get_futures_bars`, `get_futures_footprint` | US, HK |
255257
| **Crypto** | `get_crypto_snapshot`, `get_crypto_bars` | US |
256258
| **Event** | `get_event_tick`, `get_event_snapshot`, `get_event_depth`, `get_event_bars` | US |
257-
| **Screener** | `get_gainers_losers`, `get_most_active` | US, HK, JP |
258-
| **Watchlist** | `get_watchlists`, `create_watchlist`, `update_watchlist`, `delete_watchlist`, `get_watchlist_instruments`, `add_watchlist_instruments`, `remove_watchlist_instruments`, `update_watchlist_instruments` | US, HK, JP |
259+
| **Screener** | `get_gainers_losers`, `get_most_active` | US, HK, JP, SG |
260+
| **Watchlist** | `get_watchlists`, `create_watchlist`, `update_watchlist`, `delete_watchlist`, `get_watchlist_instruments`, `add_watchlist_instruments`, `remove_watchlist_instruments`, `update_watchlist_instruments` | US, HK, JP, SG |
259261

260262
### Fundamental & Instrument
261263

262264
| Category | Tools | Region |
263265
|----------|-------|--------|
264266
| **Instrument** | `get_instruments`, `get_futures_instruments`, `get_futures_products`, `get_crypto_instruments`, `get_event_series`, `get_event_instruments`, `get_event_categories`, `get_event_events` | varies |
265-
| **Fundamental** | `get_company_profile`, `get_analyst_rating`, `get_analyst_target_price` | US, HK, JP |
267+
| **Fundamental** | `get_company_profile`, `get_analyst_rating`, `get_analyst_target_price` | US, HK, JP, SG |
266268

267269
### Trading
268270

269271
| Category | Tools | Region |
270272
|----------|-------|--------|
271-
| **Account** | `get_account_list` | US, HK, JP |
272-
| **Assets** | `get_account_balance`, `get_account_positions`, `get_account_position_details` (JP only) | US, HK, JP |
273-
| **Stock Order** | `place_stock_order`, `preview_stock_order`, `replace_stock_order` | US, HK, JP |
273+
| **Account** | `get_account_list` | US, HK, JP, SG |
274+
| **Assets** | `get_account_balance`, `get_account_positions`, `get_account_position_details` (JP only) | US, HK, JP, SG |
275+
| **Stock Order** | `place_stock_order`, `preview_stock_order`, `replace_stock_order` | US, HK, JP, SG |
274276
| **Combo Order** | `place_stock_combo_order` (OTO/OCO/OTOCO) | US |
275277
| **Option Order** | `place_option_single_order`, `preview_option_order`, `replace_option_order` | US, HK |
276278
| **Option Strategy** | `place_option_strategy_order` | US |
277279
| **Algo Order** | `place_algo_order` (TWAP/VWAP/POV) | US |
278-
| **Futures Order** | `place_futures_order`, `replace_futures_order` | US |
280+
| **Futures Order** | `place_futures_order`, `replace_futures_order` | US, HK |
279281
| **Crypto Order** | `place_crypto_order` | US |
280282
| **Event Order** | `place_event_order`, `replace_event_order` | US |
281-
| **Order** | `cancel_order`, `get_order_history`, `get_open_orders`, `get_order_detail` | US, HK, JP |
283+
| **Order** | `cancel_order`, `get_order_history`, `get_open_orders`, `get_order_detail` | US, HK, JP, SG |
282284

283285
### Region Differences
284286

285-
| Feature | US | HK | JP |
286-
|---------|----|----|----|
287-
| Stock Trading | Yes | Yes | Yes |
288-
| Option Trading | Yes | Yes | No |
289-
| Futures Trading | Yes | No | No |
290-
| Crypto Trading | Yes | No | No |
291-
| Event Contracts | Yes | No | No |
292-
| Combo Orders | Yes | No | No |
293-
| Option Strategies | Yes | No | No |
294-
| Algo Orders | Yes | No | No |
295-
| Screener (Gainers/Losers/Active) | Yes | Yes | Yes |
296-
| Watchlist | Yes | Yes | Yes |
297-
| Fundamental (Company/Analyst) | Yes | Yes | Yes |
298-
| NOII (Auction Imbalance) | Yes | Yes | Yes |
299-
| Markets | US | US, HK, CN | US, JP |
300-
| Instrument Categories | US_STOCK, US_ETF | US_STOCK, US_ETF, HK_STOCK, CN_STOCK | US_STOCK, US_ETF |
301-
| Order Types | LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TRAILING_STOP_LOSS, etc. | LIMIT, MARKET, ENHANCED_LIMIT, AT_AUCTION, AT_AUCTION_LIMIT, etc. | JP market: LIMIT, MARKET — US market: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT |
302-
| Time-in-Force | DAY, GTC | US market: DAY, GTC, GTD — HK market: DAY, GTC — CN market: DAY | JP market: DAY — US market: DAY, GTC, GTD |
303-
| JP Order Fields | — | — | `account_tax_type` required (GENERAL or SPECIFIC); `margin_type` (ONE_DAY or INDEFINITE) and `position_intent` optional margin-account-only fields; `close_contracts` optional |
287+
| Feature | US | HK | JP | SG |
288+
|---------|----|----|----|----|
289+
| Stock Trading | Yes | Yes | Yes | Yes |
290+
| Option Trading | Yes | Yes | No | No |
291+
| Futures Trading | Yes | Yes | No | No |
292+
| Crypto Trading | Yes | No | No | No |
293+
| Event Contracts | Yes | No | No | No |
294+
| Combo Orders | Yes | No | No | No |
295+
| Option Strategies | Yes | No | No | No |
296+
| Algo Orders | Yes | No | No | No |
297+
| Screener (Gainers/Losers/Active) | Yes | Yes | Yes | Yes |
298+
| Watchlist | Yes | Yes | Yes | Yes |
299+
| Fundamental (Company/Analyst) | Yes | Yes | Yes | Yes |
300+
| NOII (Auction Imbalance) | Yes | Yes | Yes | Yes |
301+
| Markets | US | US, HK, CN | US, JP | US |
302+
| Instrument Categories | US_STOCK, US_ETF | US_STOCK, US_ETF, HK_STOCK, CN_STOCK | US_STOCK, US_ETF | US_STOCK, US_ETF |
303+
| Order Types | LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TRAILING_STOP_LOSS, etc. | LIMIT, MARKET, ENHANCED_LIMIT, AT_AUCTION, AT_AUCTION_LIMIT, etc. | JP market: LIMIT, MARKET — US market: LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT | MARKET, LIMIT, STOP_LOSS, STOP_LOSS_LIMIT |
304+
| Time-in-Force | DAY, GTC | US market: DAY, GTC, GTD — HK market: DAY, GTC — CN market: DAY | JP market: DAY — US market: DAY, GTC, GTD | DAY, GTC |
305+
| Trading Sessions | ALL, CORE, NIGHT | CORE, ALL_DAY, NIGHT, ALL | CORE, ALL, NIGHT, ALL_DAY | NIGHT, ALL, CORE, ALL_DAY |
306+
| JP Order Fields | — | — | `account_tax_type` required (GENERAL or SPECIFIC); `margin_type` (ONE_DAY or INDEFINITE) and `position_intent` optional margin-account-only fields; `close_contracts` optional | — |
304307

305308
> **Note:** Screener, Fundamental, and NOII currently only support querying US stock data (`US_STOCK` category). Watchlist supports US stocks and HK stocks.
306309
@@ -387,6 +390,7 @@ Subscribe to quotes:
387390
- HK: [webullapp.hk/quote](https://www.webullapp.hk/quote) | [Guide](https://developer.webull.hk/apis/docs/market-data-api/subscribe-quotes)
388391
- US: [webullapp.com/quote](https://www.webullapp.com/quote) | [Guide](https://developer.webull.com/apis/docs/market-data-api/subscribe-quotes)
389392
- JP: [webull.co.jp/pricing](https://www.webull.co.jp/pricing) | [Guide](https://developer.webull.co.jp/api-doc/market-data/subscribe-quotes/)
393+
- SG: [webull.com.sg/quote](https://www.webull.com.sg/quote) | [Guide](https://developer.webull.com.sg/apis/docs/market-data-api/subscribe-quotes)
390394

391395
### Token Expired
392396

@@ -421,7 +425,7 @@ webull-openapi-mcp/
421425
│ ├── server.py # MCP server setup and tool registration
422426
│ ├── sdk_client.py # Webull SDK adapter (ApiClient, TradeClient, DataClient)
423427
│ ├── config.py # Configuration loading and validation
424-
│ ├── region_config.py # Region-specific settings (US, HK, JP)
428+
│ ├── region_config.py # Region-specific settings (US, HK, JP, SG)
425429
│ ├── guards.py # Order validation (price, quantity, notional, region rules)
426430
│ ├── audit.py # Audit logging for order operations
427431
│ ├── errors.py # Exception definitions and SDK error handling

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "webull-openapi-mcp"
7-
version = "1.1.0"
7+
version = "1.1.1"
88
description = "MCP Server for Webull OpenAPI - enables AI assistants to securely access Webull trading and market data"
99
readme = "README.md"
1010
license = "Apache-2.0"

‎tests/test_sdk_client.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_default_region_is_us(self):
2727
assert UAT_ENDPOINTS["default_region"] == "us"
2828

2929
def test_regions_list(self):
30-
assert set(UAT_ENDPOINTS["regions"]) == {"us", "hk", "jp"}
30+
assert set(UAT_ENDPOINTS["regions"]) == {"us", "hk", "jp", "sg"}
3131

3232
def test_each_region_has_all_api_types(self):
3333
for region in ("us", "hk", "jp"):

‎webull_openapi_mcp/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Webull OpenAPI MCP Server - AI assistant integration for Webull OpenAPI."""
22

3-
__version__ = "1.1.0"
3+
__version__ = "1.1.1"

‎webull_openapi_mcp/formatters.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
"取引にはリスクがあります。慎重に判断してください。\n\n"
3838
)
3939

40+
_DISCLAIMER_SG = (
41+
"⚠️ Disclaimer: "
42+
"The information provided by this tool is for reference only "
43+
"and does not constitute investment advice. "
44+
"Trading involves risk; please make decisions carefully.\n\n"
45+
)
46+
4047
# Default (backward compatibility)
4148
DISCLAIMER = _DISCLAIMER_US
4249

@@ -52,6 +59,8 @@ def set_disclaimer_region(region_id: str) -> None:
5259
DISCLAIMER = _DISCLAIMER_HK
5360
elif _current_region == "jp":
5461
DISCLAIMER = _DISCLAIMER_JP
62+
elif _current_region == "sg":
63+
DISCLAIMER = _DISCLAIMER_SG
5564
else:
5665
DISCLAIMER = _DISCLAIMER_US
5766

‎webull_openapi_mcp/region_config.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,39 @@ class RegionConfig:
120120
)
121121

122122

123+
# =============================================================================
124+
# SG Region Configuration
125+
# =============================================================================
126+
SG_REGION_CONFIG = RegionConfig(
127+
region_id="sg",
128+
supports_futures=False,
129+
supports_crypto=False,
130+
supports_event_contracts=False,
131+
supports_combo_orders=False,
132+
supports_option_strategies=False,
133+
supports_algo_orders=False,
134+
valid_order_types=frozenset({
135+
"MARKET", "LIMIT", "STOP_LOSS", "STOP_LOSS_LIMIT"
136+
}),
137+
valid_time_in_force=frozenset({"DAY", "GTC"}),
138+
valid_trading_sessions=frozenset({"NIGHT", "ALL", "CORE", "ALL_DAY"}),
139+
valid_combo_types=frozenset({"NORMAL"}),
140+
valid_option_strategies=frozenset({"SINGLE"}),
141+
valid_market_categories=frozenset({"US"}),
142+
valid_order_markets=frozenset({"US"}),
143+
valid_instrument_categories=frozenset({"US_STOCK", "US_ETF"}),
144+
supports_options=False,
145+
)
146+
147+
123148
# =============================================================================
124149
# Region Configuration Registry
125150
# =============================================================================
126151
REGION_CONFIGS: dict[str, RegionConfig] = {
127152
"us": US_REGION_CONFIG,
128153
"hk": HK_REGION_CONFIG,
129154
"jp": JP_REGION_CONFIG,
155+
"sg": SG_REGION_CONFIG,
130156
}
131157

132158
SUPPORTED_REGIONS: frozenset[str] = frozenset(REGION_CONFIGS.keys())

‎webull_openapi_mcp/sdk_client.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
_2FA_GUIDE_LINKS: dict[str, str] = {
2121
"hk": "https://developer.webull.hk/apis/docs/authentication/token",
2222
"jp": "https://developer.webull.co.jp/apis/docs/authentication/token",
23+
"sg": "https://developer.webull.com.sg/apis/docs/authentication/token",
2324
"us": "https://developer.webull.com/apis/docs/authentication/token",
2425
}
2526

@@ -132,7 +133,7 @@ def __init__(self, region_id: str, environment: str) -> None:
132133
# based on each request's api_type - no add_endpoint() calls needed.
133134
UAT_ENDPOINTS: dict = {
134135
"default_region": "us",
135-
"regions": ["us", "hk", "jp"],
136+
"regions": ["us", "hk", "jp", "sg"],
136137
"region_mapping": {
137138
"us": {
138139
"api": "us-openapi-alb.uat.webullbroker.com",
@@ -149,6 +150,11 @@ def __init__(self, region_id: str, environment: str) -> None:
149150
"quotes-api": "data-api.uat.webullbroker.com",
150151
"events-api": "jp-openapi-events.uat.webullbroker.com",
151152
},
153+
"sg": {
154+
"api": "sg-api.uat.webullbroker.com",
155+
"quotes-api": "data-api.uat.webullbroker.com",
156+
"events-api": "sg-events-api.uat.webullbroker.com",
157+
},
152158
},
153159
}
154160

0 commit comments

Comments
 (0)