webull-openapi

Trade stocks, options, futures, crypto, and event contracts on Webull. Query real-time and historical market data. Manage accounts and positions. Supports US and HK regions with configurable risk controls.

10 stars

Best use case

webull-openapi is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Trade stocks, options, futures, crypto, and event contracts on Webull. Query real-time and historical market data. Manage accounts and positions. Supports US and HK regions with configurable risk controls.

Teams using webull-openapi should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/webull_openapi_skills/SKILL.md --create-dirs "https://raw.githubusercontent.com/webull-inc/webull-agent-skills/main/webull_openapi_skills/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/webull_openapi_skills/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How webull-openapi Compares

Feature / Agentwebull-openapiStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Trade stocks, options, futures, crypto, and event contracts on Webull. Query real-time and historical market data. Manage accounts and positions. Supports US and HK regions with configurable risk controls.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Webull OpenAPI Skill

This skill lets you interact with Webull's trading platform through natural language. You can place orders, check market data, query account info, and manage positions — all via the official Webull Python SDK.

## What You Can Do

- **Trade**: Place, preview, modify, and cancel orders for stocks, options, futures, crypto, and event contracts
- **Market Data**: Get real-time snapshots, historical bars, tick data, quotes, and order flow for all asset classes
- **Accounts**: List accounts, check balances, view positions
- **Instruments**: Look up stock, crypto, futures, and event contract instruments

## Safety Rules

**All order-mutating operations require user confirmation before execution.**

Mutating actions: `place`, `replace`, `cancel`, `batch-place`, `algo-place`, `option-place`, `option-replace`, `option-strategy-place`, `futures-place`, `futures-replace`, `crypto-place`, `event-place`, `event-replace`.

Before executing any of these operations, the AI must:
1. Display a clear summary of the operation to the user, including:
   - Action type (place / replace / cancel)
   - Symbol, side, order type, quantity, price
   - Account being used
2. Explicitly ask the user to confirm (e.g., "Confirm this order? [Yes/No]")
3. Only proceed after receiving explicit user approval

Read-only operations (`account-list`, `balance`, `position`, `open`, `history`, `detail`, `instrument-*`, all `market-data` actions) do not require confirmation and can be executed immediately.

---

## Quick Examples

> **Python command:** Use `python3` on macOS/Linux, `python` on Windows. Examples below use `python3`.

> **Passing order JSON:** Prefer `--order-file <path>` (write JSON to a temp file first) over `--order-json '<inline>'`. Inline JSON with `--order-json` is fragile across shells — Windows bash, PowerShell, and some macOS terminals mangle quotes and escapes. Using `--order-file` avoids all shell quoting issues.

```bash
# Check your accounts
python3 scripts/cli.py trading --action account-list

# Get AAPL stock price
python3 scripts/cli.py market-data --action stock-snapshot --symbols AAPL

# Get account balance
python3 scripts/cli.py trading --action balance --account-id <id>

# Place a limit buy order (recommended: use --order-file)
# First write JSON to a file, then pass it:
#   echo '{"symbol":"AAPL","side":"BUY","order_type":"LIMIT","limit_price":180,"quantity":10,"instrument_type":"EQUITY","market":"US","time_in_force":"DAY","entrust_type":"QTY","support_trading_session":"CORE","combo_type":"NORMAL"}' > /tmp/order.json
#   python3 scripts/cli.py trading --action place --account-id <id> --order-file /tmp/order.json
#
# Alternative (inline, may fail on some shells):
python3 scripts/cli.py trading --action place --account-id <id> \
  --order-json '{"symbol":"AAPL","side":"BUY","order_type":"LIMIT","limit_price":180,"quantity":10,"instrument_type":"EQUITY","market":"US","time_in_force":"DAY","entrust_type":"QTY","support_trading_session":"CORE","combo_type":"NORMAL"}'

# Cancel an order
python3 scripts/cli.py trading --action cancel --account-id <id> --client-order-id <oid>
```

## CLI Entry Point

```
python3 scripts/cli.py [--env-file PATH] [--verbose-sdk-log] <module> --action <ACTION> [options]
```

Three modules: `trading`, `market-data`, `auth`.

---

## Module: trading

Instrument queries, account/asset operations, and all order operations.

### Instrument Queries

| Action | Description | Key Options |
|--------|-------------|-------------|
| `instrument-stock` | Stock/ETF instrument info | `--symbols AAPL,TSLA` |
| `instrument-crypto` | Crypto instrument info | `--symbols BTCUSD` |
| `instrument-futures-products` | Futures product codes | `--category US_FUTURES` |
| `instrument-futures-list` | Futures instruments by symbol | `--symbols ESM6` |
| `instrument-futures-by-code` | Futures by product code | `--code ES` |
| `instrument-event-series` | Event contract series | `--page-size 50` |
| `instrument-event-list` | Event instruments by series | `--series-symbol <sym>` |
| `instrument-event-categories` | Event contract categories | |
| `instrument-event-events` | Events within a series | `--series-symbol <sym>` |

### Account & Asset

| Action | Description | Key Options |
|--------|-------------|-------------|
| `account-list` | List all linked accounts | |
| `balance` | Account balance | `--account-id <id>` |
| `position` | Account positions | `--account-id <id>` |

### Stock Orders

| Action | Description |
|--------|-------------|
| `place` | Place stock order (single, non-combo) |
| `preview` | Preview order without submitting |
| `replace` | Modify existing stock order |
| `batch-place` | Combo orders (OTO/OCO/OTOCO) — US only |
| `algo-place` | Algorithmic order (TWAP/VWAP/POV) — US only |

### Option Orders

| Action | Description |
|--------|-------------|
| `option-place` | Place single-leg option order |
| `option-preview` | Preview option order |
| `option-replace` | Modify option order |
| `option-strategy-place` | Multi-leg strategy (VERTICAL, STRADDLE, etc.) — US only |

### Futures / Crypto / Event Orders (US only)

| Action | Description |
|--------|-------------|
| `futures-place` | Place futures order |
| `futures-replace` | Modify futures order |
| `crypto-place` | Place crypto order (no replace supported) |
| `event-place` | Place event contract order |
| `event-replace` | Modify event contract order |

### Order Management

| Action | Description | Key Options |
|--------|-------------|-------------|
| `cancel` | Cancel an order | `--account-id`, `--client-order-id` |
| `open` | List open/pending orders | `--account-id` |
| `history` | Order history | `--account-id` |
| `detail` | Single order detail | `--account-id`, `--client-order-id` |
| `local-check` | Risk check only (no API call) | `--order-json` |

---

### Order JSON Format

Orders are passed via `--order-json` (inline string) or `--order-file` (path to a JSON file). **`--order-file` is strongly recommended** to avoid shell quoting issues.

> **Important:** The `place` and `replace` actions accept **different** JSON fields. Do NOT use `place` fields for `replace` — the CLI spreads JSON keys directly into the function, so unexpected fields cause errors.

> **`client_order_id` / `client_combo_order_id` rules:** Max 32 characters, must be alphanumeric only (letters and digits, no hyphens/underscores/special chars), and must be unique per account. If not provided, the system auto-generates one.

---

#### Place Order JSON (for `place`, `preview`)

> **Type note:** Stock place CLI does `float()` conversion internally, so strings technically work — but for consistency and to avoid issues, always use **number** types for numeric fields.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `combo_type` | Yes | string | `NORMAL` (single order). For combo: `MASTER`, `STOP_PROFIT`, `STOP_LOSS`, `OTO`, `OCO`, `OTOCO` |
| `symbol` | Yes | string | Ticker symbol, e.g. `AAPL`, `00700`, `BTCUSD`, `ESZ5` |
| `instrument_type` | Yes | string | `EQUITY`, `OPTION`, `FUTURES`, `CRYPTO`, `EVENT` |
| `market` | Yes | string | `US`, `HK`, `CN` |
| `side` | Yes | string | `BUY`, `SELL`, `SHORT` |
| `order_type` | Yes | string | See [Order Types by Market](#order-types-by-market) below |
| `time_in_force` | Yes | string | See [Time in Force](#time-in-force) below |
| `quantity` | Conditional | number (float) | Number of shares/contracts. Required when `entrust_type=QTY`. e.g. `10` — NOT `"10"` |
| `entrust_type` | Yes | string | `QTY` (by quantity) or `AMOUNT` (fractional shares / crypto by dollar amount) |
| `limit_price` | Conditional | number (float) | Required for `LIMIT`, `STOP_LOSS_LIMIT` orders, e.g. `180` — NOT `"180"` |
| `stop_price` | Conditional | number (float) | Required for `STOP_LOSS`, `STOP_LOSS_LIMIT` orders |
| `support_trading_session` | US stocks | string | `CORE` (regular hours), `ALL` (extended hours), `NIGHT` (night session) |
| `total_cash_amount` | Conditional | number (float) | Required when `entrust_type=AMOUNT` (US fractional shares / crypto) |
| `trailing_type` | Conditional | string | Required for `TRAILING_STOP_LOSS`: `AMOUNT` or `PERCENTAGE` |
| `trailing_stop_step` | Conditional | number (float) | Required for `TRAILING_STOP_LOSS`: trail amount or percentage (0.01 = 1%) |
| `sender_sub_id` | No (HK broker) | string | Broker user UUID for third-party transactions (HK region, institutional only) |
| `no_party_ids` | No (HK broker) | array | BCAN party identifiers for HK stock orders (institutional only). See below |

> **`quantity` vs `total_cash_amount`:** These two fields are mutually exclusive.
> - When `entrust_type=QTY`: provide `quantity` (number of shares/contracts)
> - When `entrust_type=AMOUNT`: provide `total_cash_amount` (dollar amount for fractional shares / crypto)
> - Do NOT provide both at the same time.

Stock limit buy example:
```json
{
  "symbol": "AAPL",
  "side": "BUY",
  "order_type": "LIMIT",
  "limit_price": 180,
  "quantity": 10,
  "instrument_type": "EQUITY",
  "market": "US",
  "time_in_force": "DAY",
  "entrust_type": "QTY",
  "support_trading_session": "CORE",
  "combo_type": "NORMAL"
}
```

HK stock order example (with BCAN, institutional/broker only):
```json
{
  "symbol": "00700",
  "side": "BUY",
  "order_type": "ENHANCED_LIMIT",
  "limit_price": 350,
  "quantity": 100,
  "instrument_type": "EQUITY",
  "market": "HK",
  "time_in_force": "DAY",
  "entrust_type": "QTY",
  "combo_type": "NORMAL",
  "sender_sub_id": "<broker_user_uuid>",
  "no_party_ids": [
    {
      "party_id": "ABC123.2568",
      "party_id_source": "D",
      "party_role": "3"
    }
  ]
}
```

`no_party_ids` array item fields:

| Field | Required | Description |
|-------|----------|-------------|
| `party_id` | Yes | BCAN ID, format: `CE_NUMBER.BCAN` e.g. `ABC123.2568` |
| `party_id_source` | Yes | Always `"D"` (Proprietary/Custom Code) |
| `party_role` | Yes | Always `"3"` (Client ID / BCAN Field) |

---

#### Option Place JSON (for `option-place`, `option-preview`)

> **⚠️ Type-sensitive:** Option place uses `**o` spread — JSON types must match function signatures exactly. `quantity` must be **integer**, `strike_price`/`limit_price`/`stop_price` must be **number** (float), not strings.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `symbol` | Yes | string | Underlying symbol, e.g. `AAPL` |
| `instrument_type` | Yes | string | `OPTION` |
| `option_type` | Yes | string | `CALL` or `PUT` |
| `strike_price` | Yes | number (float) | Strike price, e.g. `220.00` — NOT `"220.00"` |
| `expiration_date` | Yes | string | Expiration date, format `yyyy-MM-dd`, e.g. `"2026-06-19"` |
| `side` | Yes | string | `BUY`, `SELL`, `SHORT` |
| `order_type` | Yes | string | `MARKET`, `LIMIT`, `STOP_LOSS`, `STOP_LOSS_LIMIT` |
| `time_in_force` | Yes | string | `DAY`, `GTC`. Sell-side only supports `DAY` |
| `quantity` | Yes | number (int) | Number of contracts, e.g. `1` — NOT `"1"` |
| `limit_price` | Conditional | number (float) | Required for `LIMIT` orders, e.g. `11.25` — NOT `"11.25"` |
| `stop_price` | Conditional | number (float) | Required for `STOP_LOSS` orders |
| `position_intent` | No | string | Position strategy (US only). `BUY_TO_OPEN`, `BUY_TO_CLOSE`, `SELL_TO_OPEN`, `SELL_TO_CLOSE`. Must match `side` |
| `sender_sub_id` | No (HK broker) | string | Broker user UUID (HK region, institutional only). No BCAN needed for options |

Option single-leg example:
```json
{
  "symbol": "AAPL",
  "instrument_type": "OPTION",
  "option_type": "CALL",
  "strike_price": 220.00,
  "expiration_date": "2026-06-19",
  "side": "BUY",
  "order_type": "LIMIT",
  "limit_price": 11.25,
  "quantity": 1,
  "time_in_force": "DAY",
  "position_intent": "BUY_TO_OPEN"
}
```

---

#### Option Strategy Place JSON (for `option-strategy-place`)

> **⚠️ Type-sensitive:** Same as option-place — numeric fields must be numbers, not strings.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `strategy` | Yes | string | `VERTICAL`, `STRADDLE`, `STRANGLE`, `BUTTERFLY`, `CONDOR`, `CALENDAR`, `DIAGONAL`, `IRON_BUTTERFLY`, `IRON_CONDOR`, `COLLAR_WITH_STOCK`, `COVERED_STOCK` |
| `symbol` | Yes | string | Underlying symbol |
| `order_type` | Yes | string | `LIMIT`, `MARKET` |
| `time_in_force` | Yes | string | `DAY`, `GTC` |
| `quantity` | No | number (int) | Number of contracts per leg |
| `limit_price` | Conditional | number (float) | Net debit/credit price for the strategy |
| `legs` | Yes | array | Array of leg objects (see below) |

Each leg object:

| Field | Required | JSON Type | Values |
|-------|----------|-----------|--------|
| `side` | Yes | string | `BUY`, `SELL` |
| `quantity` | Yes | string | Contracts for this leg |
| `symbol` | Yes | string | Underlying symbol |
| `strike_price` | Yes | string | Strike price |
| `option_expire_date` | Yes | string | `yyyy-MM-dd` |
| `instrument_type` | Yes | string | `OPTION` |
| `option_type` | Yes | string | `CALL` or `PUT` |
| `market` | Yes | string | `US` |

---

#### Futures Place JSON (for `futures-place`)

> **⚠️ Type-sensitive:** Futures place uses `**o` spread — `quantity`/`limit_price`/`stop_price` must be **number** (float), not strings.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `symbol` | Yes | string | Futures symbol, e.g. `ESZ5`, `NQM6` |
| `side` | Yes | string | `BUY`, `SELL` |
| `order_type` | Yes | string | `MARKET`, `LIMIT`, `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TRAILING_STOP_LOSS` |
| `time_in_force` | Yes | string | `DAY`, `GTC` |
| `quantity` | Yes | number (float) | Number of contracts, e.g. `1` — NOT `"1"` |
| `limit_price` | Conditional | number (float) | Required for `LIMIT`, `STOP_LOSS_LIMIT` |
| `stop_price` | Conditional | number (float) | Required for `STOP_LOSS`, `STOP_LOSS_LIMIT` |

Futures example:
```json
{
  "symbol": "ESZ5",
  "side": "BUY",
  "order_type": "LIMIT",
  "limit_price": 4500,
  "quantity": 1,
  "time_in_force": "DAY"
}
```

---

#### Crypto Place JSON (for `crypto-place`)

> **⚠️ Type-sensitive:** Crypto place uses `**o` spread — `quantity`/`limit_price`/`stop_price`/`total_cash_amount` must be **number** (float), not strings.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `symbol` | Yes | string | e.g. `BTCUSD`, `ETHUSD` |
| `side` | Yes | string | `BUY`, `SELL` |
| `order_type` | Yes | string | `MARKET` (tif **must** be `IOC`), `LIMIT` (tif `DAY`/`GTC`), `STOP_LOSS_LIMIT` (tif `DAY`/`GTC`) |
| `time_in_force` | Yes | string | `IOC` (only for `MARKET`), `DAY` or `GTC` (for `LIMIT`/`STOP_LOSS_LIMIT`) |
| `entrust_type` | Yes | string | `QTY` or `AMOUNT` |
| `quantity` | Conditional | number (float) | Required when `entrust_type=QTY`. Supports up to 8 decimal places |
| `total_cash_amount` | Conditional | number (float) | Required when `entrust_type=AMOUNT` |
| `limit_price` | Conditional | number (float) | Required for `LIMIT`, `STOP_LOSS_LIMIT` |
| `stop_price` | Conditional | number (float) | Required for `STOP_LOSS_LIMIT` |

> Note: Crypto does NOT support replace (modify) orders. When selling, position must not fall below $2.

Crypto example:
```json
{
  "symbol": "BTCUSD",
  "side": "BUY",
  "order_type": "LIMIT",
  "limit_price": 80000,
  "quantity": 0.003,
  "time_in_force": "DAY",
  "entrust_type": "QTY"
}
```

---

#### Event Contract Place JSON (for `event-place`)

> **⚠️ Type-sensitive:** Event place uses `**o` spread — `quantity` and `limit_price` must be **number** (float), not strings.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `symbol` | Yes | string | Event contract symbol |
| `side` | Yes | string | `BUY`, `SELL` |
| `quantity` | Yes | number (float) | Number of contracts. Accepts 0-2 decimal places |
| `limit_price` | Yes | number (float) | Limit price (LIMIT orders only) |
| `event_outcome` | Yes | string | `yes` or `no` |
| `order_type` | No | string | Default `LIMIT` (only LIMIT supported) |
| `time_in_force` | No | string | Default `DAY` (only DAY supported) |

Event contract example:
```json
{
  "symbol": "KXRATECUTCOUNT-26DEC31-T3",
  "side": "BUY",
  "quantity": 5,
  "limit_price": 0.10,
  "event_outcome": "yes"
}
```

---

#### Algo Place JSON (for `algo-place`) — US only

> **⚠️ Type-sensitive:** Algo place uses `**o` spread — `quantity`/`limit_price` must be **number**, `target_vol_percent`/`max_target_percent` must be **integer**.

| Field | Required | JSON Type | Values / Description |
|-------|----------|-----------|----------------------|
| `symbol` | Yes | string | Stock symbol |
| `side` | Yes | string | `BUY`, `SELL` |
| `quantity` | Yes | number (float) | Number of shares |
| `algo_type` | Yes | string | `TWAP`, `VWAP`, `POV` |
| `order_type` | No | string | `MARKET` or `LIMIT` (default `LIMIT`) |
| `limit_price` | Conditional | number (float) | Required for `LIMIT` order type |
| `max_target_percent` | Conditional | number (int) | Required for `TWAP`/`VWAP`. Integer 1-20 |
| `target_vol_percent` | Conditional | number (int) | Required for `POV`. Integer 1-20 |
| `algo_start_time` | No | string | US Eastern Time, `HH:mm:ss` format, e.g. `"09:30:00"` |
| `algo_end_time` | No | string | US Eastern Time, `HH:mm:ss` format, e.g. `"16:00:00"` |

Algo TWAP example:
```json
{
  "symbol": "AAPL",
  "side": "BUY",
  "quantity": 100,
  "algo_type": "TWAP",
  "order_type": "LIMIT",
  "limit_price": 180,
  "max_target_percent": 10,
  "algo_start_time": "09:30:00",
  "algo_end_time": "16:00:00"
}
```

---

### Replace (Modify) Order JSON

Replace actions use a **different, smaller** set of fields. Only include `client_order_id` plus the fields you want to change.

> **CRITICAL:** Do NOT include `symbol`, `side`, `instrument_type`, `market`, `entrust_type`, or `combo_type` in replace JSON — these cause `unexpected keyword argument` errors.

> **Note:** `client_order_id` MUST be in the JSON body. The `--client-order-id` CLI flag is NOT passed to replace functions.

#### Stock Replace (`replace`)

| Field | Required | JSON Type | Description |
|-------|----------|-----------|-------------|
| `client_order_id` | Yes | string | The order to modify |
| `quantity` | No | number (float) | New quantity |
| `limit_price` | No | number (float) | New limit price |
| `stop_price` | No | number (float) | New stop price |
| `time_in_force` | No | string | `DAY`, `GTC` |
| `order_type` | No | string | New order type |
| `trailing_type` | No | string | `AMOUNT` or `PERCENTAGE` |
| `trailing_stop_step` | No | number (float) | New trailing stop spread |
| `target_vol_percent` | No | number (int) | For algo orders (1-20) |
| `max_target_percent` | No | number (int) | For algo orders (1-20) |
| `algo_start_time` | No | string | For algo orders, `HH:mm:ss` |
| `algo_end_time` | No | string | For algo orders, `HH:mm:ss` |

Stock replace example — change quantity from 1 to 2:
```json
{
  "client_order_id": "7af9c5c03a6f4e6ca46a194609f158e1",
  "quantity": 2,
  "limit_price": 258
}
```

Replace example using `--order-file` (recommended):
```bash
echo '{"client_order_id":"<oid>","quantity":2}' > /tmp/replace.json
python3 scripts/cli.py trading --action replace --account-id <id> --order-file /tmp/replace.json
```

#### Option Replace (`option-replace`)

> **⚠️ Type-sensitive:** Option replace requires `quantity` as **integer** (not string) and `limit_price`/`stop_price` as **number** (not string). Passing `"2"` instead of `2` will cause errors.

| Field | Required | JSON Type | Description |
|-------|----------|-----------|-------------|
| `client_order_id` | Yes | string | The order to modify |
| `quantity` | No | number (int) | New quantity — must be integer, NOT string |
| `limit_price` | No | number (float) | New limit price — must be number, NOT string |
| `stop_price` | No | number (float) | New stop price — must be number, NOT string |
| `time_in_force` | No | string | `DAY`, `GTC` |

Option replace example:
```json
{
  "client_order_id": "abc123def456",
  "quantity": 2,
  "limit_price": 3.5
}
```

> Note: Option leg IDs are auto-fetched from order detail. No need to provide `legs` manually.

#### Futures Replace (`futures-replace`)

Futures modification rules (from official API docs):
- Market orders: only `quantity` can be modified
- Limit orders: `order_type` (can only change to `MARKET`), `time_in_force`, `quantity`, `limit_price`
- Stop orders: `order_type` (can only change to `MARKET`), `time_in_force`, `quantity`, `stop_price`
- Stop limit orders: `order_type` (can only change to `LIMIT`), `time_in_force`, `quantity`, `limit_price`, `stop_price`
- Trailing stop orders: only `trailing_stop_step` can be modified

| Field | Required | JSON Type | Description |
|-------|----------|-----------|-------------|
| `client_order_id` | Yes | string | The order to modify |
| `quantity` | No | number (float) | New quantity |
| `limit_price` | No | number (float) | New limit price |
| `order_type` | No | string | New order type (restricted, see rules above) |

Futures replace example:
```json
{
  "client_order_id": "abc123def456",
  "quantity": 2,
  "limit_price": 4550
}
```

#### Event Replace (`event-replace`)

| Field | Required | JSON Type | Description |
|-------|----------|-----------|-------------|
| `client_order_id` | Yes | string | The order to modify |
| `quantity` | No | number (float) | New quantity |
| `limit_price` | No | number (float) | New limit price |

Event replace example:
```json
{
  "client_order_id": "abc123def456",
  "quantity": 10,
  "limit_price": 0.15
}
```

#### Crypto Replace

**Not supported.** Cancel and re-place instead.

---

### Order Types by Market

| Market | Supported Order Types |
|--------|----------------------|
| US stocks/ETFs | `MARKET`, `LIMIT`, `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TRAILING_STOP_LOSS` |
| US stocks (institutional) | Also: `MARKET_ON_OPEN`, `MARKET_ON_CLOSE`, `LIMIT_ON_OPEN` |
| US options | `MARKET`, `LIMIT`, `STOP_LOSS`, `STOP_LOSS_LIMIT` |
| US futures | `MARKET`, `LIMIT`, `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TRAILING_STOP_LOSS` |
| US crypto | `MARKET`, `LIMIT`, `STOP_LOSS_LIMIT` |
| US event contracts | `LIMIT` only |
| HK stocks | `ENHANCED_LIMIT`, `AT_AUCTION`, `AT_AUCTION_LIMIT` |
| CN A-shares (via HK) | `LIMIT` only |

### Time in Force

| Value | Description | Supported By |
|-------|-------------|--------------|
| `DAY` | Valid for current trading day only | All instruments |
| `GTC` | Good-Till-Canceled (up to 60 days) | US stocks, options, futures, crypto |
| `IOC` | Immediate-Or-Cancel (unfilled portion canceled) | Crypto `MARKET` orders only |

### Trading Sessions (US stocks only)

| Value | Description |
|-------|-------------|
| `CORE` | Regular hours (9:30 AM - 4:00 PM ET) |
| `ALL` | Extended hours (pre-market + after-hours) |
| `NIGHT` | Night session only |

### Combo Types (US stocks only)

| Value | Description |
|-------|-------------|
| `NORMAL` | Standard single order |
| `MASTER` | Simple order + take profit or stop loss |
| `STOP_PROFIT` | Take profit order (child of MASTER) |
| `STOP_LOSS` | Stop loss order (child of MASTER) |
| `OTO` | One Triggers Other |
| `OCO` | One Cancels Other |
| `OTOCO` | One Triggers a One Cancels Other |

### Option Strategies (US only)

`SINGLE`, `COVERED_STOCK`, `VERTICAL`, `STRADDLE`, `STRANGLE`, `CALENDAR`, `DIAGONAL`, `BUTTERFLY`, `CONDOR`, `COLLAR_WITH_STOCK`, `IRON_BUTTERFLY`, `IRON_CONDOR`

### Algo Types (US only)

| Type | Description | Required Param |
|------|-------------|----------------|
| `TWAP` | Time Weighted Average Price | `max_target_percent` (1-20) |
| `VWAP` | Volume Weighted Average Price | `max_target_percent` (1-20) |
| `POV` | Percentage of Volume | `target_vol_percent` (1-20) |

---

## Module: market-data

Real-time and historical market data for all asset classes.

### Stock

| Action | Description | Key Options |
|--------|-------------|-------------|
| `stock-snapshot` | Real-time snapshot | `--symbols AAPL,TSLA` |
| `stock-bars` | OHLCV bars (single symbol) | `--symbol AAPL --timespan D --count 200` |
| `stock-batch-bars` | OHLCV bars (multiple symbols) | `--symbols AAPL,TSLA --timespan D` |
| `stock-tick` | Tick-by-tick trades | `--symbol AAPL --count 30` |
| `stock-quotes` | Bid/ask depth | `--symbol AAPL --depth 5` |
| `stock-footprint` | Large order flow | `--symbols AAPL --timespan M1` |

### Futures (US only)

| Action | Description | Key Options |
|--------|-------------|-------------|
| `futures-snapshot` | Futures snapshot | `--symbols ESM6` |
| `futures-bars` | Futures OHLCV | `--symbols ESM6 --timespan D` |
| `futures-tick` | Futures ticks | `--symbol ESM6 --count 30` |
| `futures-depth` | Order book depth | `--symbol ESM6 --depth 5` |
| `futures-footprint` | Futures order flow | `--symbols ESM6 --timespan M1` |

### Crypto (US only)

| Action | Description | Key Options |
|--------|-------------|-------------|
| `crypto-snapshot` | Crypto snapshot | `--symbols BTCUSD` |
| `crypto-bars` | Crypto OHLCV | `--symbols BTCUSD --timespan D` |

### Event Contracts (US only)

| Action | Description | Key Options |
|--------|-------------|-------------|
| `event-snapshot` | Event snapshot | `--symbols <sym>` |
| `event-depth` | Event depth | `--symbol <sym> --depth 5` |
| `event-bars` | Event OHLCV | `--symbols <sym> --timespan D` |
| `event-tick` | Event ticks | `--symbol <sym> --count 30` |

### Common Options

| Option | Default | Description |
|--------|---------|-------------|
| `--category` | auto | See [Category Values](#category-values) below |
| `--timespan` | `D` | `M1`, `M5`, `M15`, `M30`, `H1`, `H4`, `D`, `W` |
| `--count` | `200` | Number of bars/ticks |
| `--depth` | `1` | Order book depth levels |
| `--extend-hour-required` | false | Include extended hours |
| `--overnight-required` | false | Include overnight data |

### Category Values

Category determines which market's data you're querying. It varies by region:

**US Region (`WEBULL_REGION_ID=us`):**

| Category | Description |
|----------|-------------|
| `US_STOCK` | US stocks (default for stock actions) |
| `US_ETF` | US ETFs |
| `US_FUTURES` | US futures (default for futures actions) |
| `US_CRYPTO` | US crypto (default for crypto actions) |
| `US_EVENT` | US event contracts (default for event actions) |

**HK Region (`WEBULL_REGION_ID=hk`):**

| Category | Description |
|----------|-------------|
| `US_STOCK` | US stocks (traded via HK account) |
| `US_ETF` | US ETFs (traded via HK account) |
| `HK_STOCK` | Hong Kong stocks |
| `CN_STOCK` | China Connect A-shares |

Examples:
```bash
# US stock (default for US region)
python3 scripts/cli.py market-data --action stock-snapshot --symbols AAPL

# HK stock (must specify category for HK region)
python3 scripts/cli.py market-data --action stock-snapshot --symbols 00700 --category HK_STOCK

# China Connect A-share
python3 scripts/cli.py market-data --action stock-snapshot --symbols 600519 --category CN_STOCK
```

---

## Module: auth

```bash
python3 scripts/cli.py auth
```

Interactive 2FA authentication. Run once before first use. The SDK waits up to 5 minutes for you to approve in the Webull mobile app. Token is cached and auto-refreshes.

---

## Output Format

All operations output formatted text directly to stdout, with a region-aware disclaimer at the top:

```
⚠️ Disclaimer: The information provided by this tool is for reference only ...

=== Stock Snapshot: AAPL ===
  Symbol:          AAPL
  Price:           255.92
  Pre Close:       255.63
  Change:          0.29
  ...
```

- Success: disclaimer + formatted data to stdout, exit code 0
- Error: error message to stderr, exit code 1
- US region: English disclaimer only
- HK region: English + Simplified Chinese + Traditional Chinese disclaimer

---

## Configuration

Via `.env` file or environment variables. Required:

```
WEBULL_APP_KEY=<your_app_key>
WEBULL_APP_SECRET=<your_app_secret>
```

**`.env` lookup order** (when `--env-file` is not specified):
1. `$WEBULL_CONFIG_DIR/.env` — if `WEBULL_CONFIG_DIR` is set
2. `<project_root>/.env` — default (sibling of `webull_openapi_skills/`)
3. Current working directory `.env` — last resort

> To keep credentials outside the project directory, set `WEBULL_CONFIG_DIR` as a **system environment variable** (e.g. in `~/.zshrc`), then place your `.env` at `$WEBULL_CONFIG_DIR/.env`. Setting `WEBULL_CONFIG_DIR` inside a `.env` file has no effect — it must be set before the process starts.

Optional:

| Variable | Default | Description |
|----------|---------|-------------|
| `WEBULL_ENVIRONMENT` | `uat` | `uat` (sandbox) or `prod` (live) |
| `WEBULL_REGION_ID` | `us` | `us` or `hk` |
| `WEBULL_MAX_ORDER_NOTIONAL_USD` | `10000` | Max order value (USD) |
| `WEBULL_MAX_ORDER_QUANTITY` | `1000` | Max shares per order |
| `WEBULL_SYMBOL_WHITELIST` | (none) | Comma-separated allowed symbols |
| `WEBULL_CONFIG_DIR` | (none) | **System env var only** (not in `.env`). Moves `.env` lookup and token storage to this directory |
| `WEBULL_TOKEN_DIR` | `<project_root>/conf/` | Token storage directory |
| `WEBULL_AUDIT_LOG_FILE` | (stderr) | Audit log file path |
| `WEBULL_LOG_LEVEL` | `WARNING` | SDK log level |

---

## Region Support

| Feature | US | HK |
|---------|:--:|:--:|
| Stock trading | ✓ | ✓ (US/HK/CN) |
| Options | ✓ | ✓ (US only) |
| Futures | ✓ | ✗ |
| Crypto | ✓ | ✗ |
| Event contracts | ✓ | ✗ |
| Combo orders | ✓ | ✗ |
| Algo orders | ✓ | ✗ |
| Trailing stop loss | ✓ | ✗ |
| Fractional shares | ✓ (US market) | ✗ |

### HK-Specific Notes

- HK stocks use order types: `ENHANCED_LIMIT`, `AT_AUCTION`, `AT_AUCTION_LIMIT`
- CN A-shares (Stock Connect): `LIMIT` only, disabled by default — contact Webull to enable
- Board lot sizes vary by HK stock
- No combo orders, algo orders, futures, crypto, or event contracts in HK region
- HK stock orders (institutional/broker): require `sender_sub_id` and `no_party_ids` (BCAN)
- HK US options (institutional/broker): support `sender_sub_id` only, no BCAN needed

---

## Rate Limits

### US Region
- Market data: 600 req/min
- Order place/replace/cancel: 600 req/min
- Order query: 2 req/2s
- Auth: 10 req/30s

### HK Region
- Market data: 60 req/60s
- Order place: 15 req/s (US stocks), 1 req/s (HK/A-share)
- Order preview: 40 req/10s
- Order query: 40 req/2s

---

## Official API Documentation

- US: https://developer.webull.com/apis/docs/webull-open-api-reference
- HK: https://developer.webull.hk/apis/docs

---

## Disclaimer

The information provided by this tool is for reference only and does not constitute investment advice. Trading involves risk; please make decisions carefully.

Related Skills

We are still matching the closest adjacent skills for this page. In the meantime, continue through the full directory.