Skip to main content

Futures Trading

Webull's Futures API enables developers to trade and query over HTTP. For more details, please refer to the Trading API Reference.

Before calling the Trading API, you need to have an App Key and secret. For more information, please refer to the Individual Application Process.

Base URLs

  • Production Environment: https://api.webull.com/
  • Test Environment: http://us-openapi-alb.uat.webullbroker.com/

Supported Futures Contracts

Webull provides futures contracts for indices, interest rates, currencies, agriculture, metals, energies, and cryptocurrencies.

Contract trading codes

Contract codes are often one to three letter codes identifying the asset that is attached to a specific contract. For example, E-mini S&P 500 futures' contract code is ES. Make note that these codes could vary across platforms. Following the contract code should be a letter and a number, for example, ESG8. The G represents a month (February) and the 8 represents a year (2018). Each month has its own letter. So, as in the example listed above, ESG8 would represent an E-mini S&P 500 futures contract expiring in February of 2018.

Jan.Feb.Mar.Apr.MayJun.Jul.Aug.Sep.Oct.Nov.Dec.
FGHJKMNQUVXZ

To retrieve all available futures contracts, please use the API call below:

from webull.data.common.category import Category
from webull.data.common.contract_type import ContractType
from webull.data.common.timespan import Timespan
from webull.core.client import ApiClient
from webull.data.data_client import DataClient

optional_api_endpoint = "<api_endpoint>" # PRD env host: api.webull.com; Test env host: us-openapi-alb.uat.webullbroker.com
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
region_id = "us"
api_client = ApiClient(your_app_key, your_app_secret, region_id)
api_client.add_endpoint(region_id, optional_api_endpoint)

if __name__ == '__main__':
data_client = DataClient(api_client)

res = data_client.futures_market_data.get_futures_quotes("SILZ5", Category.US_FUTURES.name, depth=1)
if res.status_code == 200:
print('get_futures_quotes:', res.json())

res = data_client.futures_market_data.get_futures_history_bars('SILZ5,6BM6', Category.US_FUTURES.name, Timespan.M1.name)
if res.status_code == 200:
print('get_futures_history_bars:', res.json())

res = data_client.futures_market_data.get_futures_tick("SILZ5", Category.US_FUTURES.name, count=10)
if res.status_code == 200:
print('get_futures_tick:', res.json())

res = data_client.futures_market_data.get_futures_snapshot("SILZ5,6BM6", Category.US_FUTURES.name)
if res.status_code == 200:
print('get_futures_snapshot:', res.json())

res = data_client.instrument.get_futures_products(Category.US_FUTURES.name)
if res.status_code == 200:
print('get_futures_products:', res.json())

res = data_client.instrument.get_futures_instrument("ESZ5", Category.US_FUTURES.name)
if res.status_code == 200:
print('get_futures_instrument:', res.json())

res = data_client.instrument.get_futures_instrument_by_code("ES", Category.US_FUTURES.name, ContractType.MONTHLY.name)
if res.status_code == 200:
print('get_futures_instrument_by_code:', res.json())

Futures Orders

Trading Hours

The market for futures is open virtually 24 hrs. a day and 6 days a week. However, each product has its own specific hours of trading.

Order Types

Futures trading supports only the following order types:

Values
MARKET
LIMIT
STOP_LOSS
STOP_LOSS_LIMIT
TRAILING_STOP_LOSS
Note

Combo Orders are not supported for futures trading at this time.

TIF

Futures trading supports only the following time in force:

Values
DAY
GTC

Margin

  • Initial margin is the cash you must deposit to open a position; it is usually three to twelve percent of the contract value.
  • Intraday margin is available between 9:30 a.m. and 4:00 p.m. Eastern Time and is lower than overnight margin.
  • Maintenance margin is the lowest equity you may keep while the position is open; it is lower than the initial margin. If your equity falls below maintenance margin you will receive a margin call; you will be asked to provide sufficient funds to bring the account back up to the initial margin requirement or your position will be liquidated.

Settlement & Expiry

  • The majority of traders do not take physical delivery. They offset their positions before expiration by entering an opposite trade, canceling out their obligation. Physical delivery is not permitted at Webull.
  • If a position is not closed by expiration, then the contract holder is required to either accept or provide the physical delivery of the underlying commodity. Most traders close their position before expiration to avoid taking physical delivery.

Code Example

import json
import uuid
from time import sleep

from webull.core.client import ApiClient
from webull.trade.trade_client import TradeClient

optional_api_endpoint = "<api_endpoint>" # PRD env host: api.webull.com; Test env host: us-openapi-alb.uat.webullbroker.com
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
region_id = "hk"
account_id = "<your_account_id>" # Use account_list interface to get account info
api_client = ApiClient(your_app_key, your_app_secret, region_id)
api_client.add_endpoint(region_id, optional_api_endpoint)

if __name__ == '__main__':
trade_client = TradeClient(api_client)

# normal futures order
normal_futures_client_order_id = uuid.uuid4().hex
print('futures client order id:', normal_futures_client_order_id)
new_normal_futures_orders = [
{
"combo_type": "NORMAL",
"client_order_id": normal_futures_client_order_id,
"symbol": "ESZ5",
"instrument_type": "FUTURES",
"market": "US",
"order_type": "LIMIT",
"limit_price": "4500",
"quantity": "1",
"side": "BUY",
"time_in_force": "DAY",
"entrust_type": "QTY"
}
]
res = trade_client.order_v3.place_order(account_id, new_normal_futures_orders)
if res.status_code == 200:
print('place normal futures order res:', res.json())
sleep(3)

# normal futures order replace
replace_normal_futures_orders = [
{
"client_order_id": normal_futures_client_order_id,
"quantity": "2",
"limit_price": "4550"
}
]
res = trade_client.order_v3.replace_order(account_id, replace_normal_futures_orders)
if res.status_code == 200:
print('replace normal futures order res:', res.json())
sleep(3)

# normal futures order cancel
res = trade_client.order_v3.cancel_order(account_id, normal_futures_client_order_id)
if res.status_code == 200:
print('cancel normal futures order res:', res.json())

# get futures order detail
res = trade_client.order_v3.get_order_detail(account_id, normal_futures_client_order_id)
if res.status_code == 200:
print('get futures order detail res:', res.json())

# get futures open orders
res = trade_client.order_v3.get_order_open(account_id, page_size=10)
if res.status_code == 200:
print("order_open_res=" + json.dumps(res.json(), indent=4))

# get futures order history
res = trade_client.order_v3.get_order_history(account_id, page_size=10)
if res.status_code == 200:
print('get order history res:', res.json())

Futures Market Data

Webull's Futures Market Data API offers futures market data access over HTTP. For more details, please refer to the Futures Market Data API Reference.

Note

Currently, access to futures data via the OpenAPI requires a paid market-data subscription, which grants the necessary authorization. This subscription module is under active development and will be released soon—please stay tuned.

Futures Trading Fees

Please refer to the Webull's fee Schedule