How To Trade Options with Alpaca

Easy to use and designed for complex trading strategies, Alpaca's Trading API is an ideal solution for algorithmic traders looking to trade options.

How To Trade Options with Alpaca

Alpaca enables developers to programmatically trade options, stocks, ETFs, and crypto with the ability for manual execution if desired. Being easy to use and designed for complex trading strategies, Trading API serves as an ideal solution for algorithmic traders. This guide covers how to paper trade options with Alpaca based on their preferred methodology.

Initially, we’ll review the dashboard’s paper account setup with an example of placing and closing an options trade. We’ll then cover how to place the associated Trading API calls with both Alpaca-py and Postman. This includes fetching the necessary account and contract data to place an order then closing its associated position.

It's important to note that once we launch commission-free options trading on live accounts, the guide will be expanded to include this.

Getting Started and Using the Dashboard

1. Sign up for an account

Initially, you'll need to create an account with Alpaca. As part of the registration process, open a paper trading account to start right away. If you’d like to open a live trading account, Alpaca may ask you additional details regarding your trading background and your objectives for investing.

Signing up and creating your Trading API account


2. Navigate and find your desired trade

After setting up your account(s), sign into your Dashboard. You will find the option to swap between your live and paper trading accounts. Ensure you’ve selected your paper trading account to practice without the risk of real capital.

You have the ability to monitor your portfolio, access market data, execute trades, and review your trading history within this dashboard. Use the search bar to select the applicable asset ticker symbol.

Searching and selecting SPY from Trading Dashboard


3. Opening an options position

Now, on the asset’s page, toggle “Options” and determine your desired contract type, like calls or puts. After, you’ll also need to select its expiration date from the dropdown.


Once determined, review your order type (such as market, limit, stop limit or trailing stop) and the number of contracts you’d like to purchase. After providing the specifications of your order, proceed to have it filled.

It’s important you double check the order to ensure that you’ve selected the options contract as vs. the underlying asset itself. For example, in this instance, ensure the Symbol field matches SPY240227C00506000 vs just SPY.

Your paper trading account will then mimic the execution of the order as though it were a real transaction, impacting your figurative portfolio as a result.

4. Exercising your position

Exercising a position in options trading involves electing the right provided by an options contract to buy or sell the underlying asset at the agreed-upon price.

If you’d like to exercise, this can be accomplished in the same manner as when it was opened. Find the desired options contract and select “Exercise”. You’ll then be prompted to confirm.

In American-style, only long option positions can be exercised. This can occur at any time before or at expiration.

5. Closing your position

Closing an options position involves selling the options contract that you previously bought (in a long position) or buying back the options contract that you previously sold (in a short position). Either action terminates, or “closes”, your associated position.

If you’d like to close your position, this can be accomplished in the same manner as when it was opened. Find the desired options contract and select “Close Position”. You’ll then be prompted to confirm. You can also liquidate this contract in the “Positions” area of your dashboard.

Options Trading using Alpaca-py

Alpaca-py, Alpaca’s Python library, designed for algorithmic trading, opens up a realm of possibilities for automating trading strategies, especially in the US options market. This will guide you through the essentials of using Alpaca-py for paper trading options.

Note: Check your account to ensure you’ve enabled Options at your desired level. You can verify this by reviewing “Configuration” under the “Account” section on the Dashboard.

Verifying Level 2 Options is enabled in “Configuration” on the Dashboard.

Developing with Alpaca-py:

1. Setup

1.1 First, install Alpaca-py

pip install alpaca-py

1.2 Update Alpaca-py

pip install alpaca-py --upgrade

2. Setup clients

# Initializing connection to Alpaca’s Trading API

TRADE_API_KEY="Your API Key"
TRADE_API_SECRET="Your API Secret"

#### We use paper environment for this example ####
PAPER=True
TRADE_API_URL="https://paper-api.alpaca.markets"
TRADE_API_WSS=None
DATA_API_URL=None
OPTION_STREAM_DATA_WSS=None

api_key = TRADE_API_KEY
secret_key = TRADE_API_SECRET
paper = PAPER
trade_api_url = TRADE_API_URL

trade_client = TradingClient(api_key=api_key, secret_key=secret_key, paper=paper, url_override=trade_api_url)

3. Check trading account

# Checking account related information

acc = trade_client.get_account()

4. Check account configuration

# Checking account configurations

acct_config = trade_client.get_account_configurations()

5. Retrieve list of assets which are options enabled

# We can filter assets by `options_enabled` attribute
# Asset object has `options_enabled` attribute if it is options enabled

req = GetAssetsRequest(
  attributes = "options_enabled"  
)
assets = trade_client.get_all_assets(req)

6. Get list of options contracts for the given symbol (e.g. SPY)

# In this instance, we retrieve the necessary contracts based on the parameters we've configured.

underlying_symbol = "SPY"
req = GetOptionContractsRequest(
    underlying_symbol=[underlying_symbol],                 
# specify underlying symbol
    status=AssetStatus.ACTIVE,                           
# specify asset status: active (default)
    expiration_date=None,                                
# specify expiration date (specified date + 1 day range)
    expiration_date_gte=None,                            
# we can pass date object
    expiration_date_lte=None,                           
 # or string (YYYY-MM-DD)
    root_symbol=None,                                    
# specify root symbol
    type=None,                                           
# specify option type (ContractType.CALL or ContractType.PUT)	
)
		
res = trade_client.get_option_contracts(req)


7. Get options contract by symbol

symbol = res.option_contracts[0].symbol
contract = trade_client.get_option_contract(symbol)


8. Get options contract by id

id = res.option_contracts[0].id
contract = trade_client.get_option_contract(symbol_or_id=id)


9. Get put options contracts

# We can filter the contracts that are relevant to us by specifying various option properties like expiration date range (the contracts which are expiring within a particular time window), strike range (the contracts with strike prices within a given range), style of expiration for the option contract (like American or European), etc.

underlying_symbol = "SPY"

# specify expiration date range
now = datetime.now(tz=ZoneInfo("America/New_York"))
day1 = now + timedelta(days=1)
day60 = now + timedelta(days=60)

req = GetOptionContractsRequest(
    underlying_symbol=[underlying_symbol],                 
# specify underlying symbol
    status=AssetStatus.ACTIVE,                           
# specify asset status: active (default)
    expiration_date=None,                                
# specify expiration date (specified date + 1 day range)
    expiration_date_gte=day1.date(),                        
# we can pass date object
    expiration_date_lte=day60.strftime(format="%Y-%m-%d"),  
# or string
    root_symbol=None,                                    
# specify root symbol
    type="put",                                          
# specify option type: put
    style=ExerciseStyle.AMERICAN,                        
# specify option style: american
    strike_price_gte=None,                               
# specify strike price range
    strike_price_lte=None,                               
# specify strike price range
    limit=100,                                           
# specify limit
    page=None,                                           
# specify page
)
res = trade_client.get_option_contracts(req)

10. Get the highest open interest contract

# Filter contract with the highest open interest

max_open_interest = 0
high_open_interest_contract = None
for contract in res.option_contracts:
    if int(contract.open_interest) > max_open_interest:
        max_open_interest = int(contract.open_interest)
        high_open_interest_contract = contract

11. Explore information about the selected contract

# Check contract information like expiry, expiration style and contract status

#Check option expiry
print(high_open_interest_contract.expiration_date)

#Check option status
print(high_open_interest_contract.status)

#Check option exercise style
print(high_open_interest_contract.style)

12. Place a long put option order

# Execute either a Buy Call or Put option order in accordance with your trading strategy.

req = MarketOrderRequest(
    symbol=high_open_interest_contract.symbol,
    qty=1,
    side=OrderSide.BUY,
    type=OrderType.MARKET,
    time_in_force=TimeInForce.DAY,
)
res = trade_client.submit_order(req)

13. Get list of orders by specifying option contract symbol

req = GetOrdersRequest(
    status=QueryOrderStatus.ALL,
    symbols=[high_open_interest_contract.symbol],
    limit=2,
)
orders = trade_client.get_orders(req)

14. Filter contract with the desired client_order_id and print the status

orders_df = pd.DataFrame([vars(order) for order in orders])

#select order with the corresponding client_order_id
order = orders_df[orders_df['client_order_id'] == client_order_id]

#print order status
print(order.status.iloc[0])

15. Get positions filtered by option contract symbol

# Review all positions or open positions (By symbol or contract ID) in the following way:

15.1 Get all positions

positions = trade_client.get_all_positions()

15.2 Get open positions by symbol

positions = trade_client.get_open_position(
symbol_or_asset_id=high_open_interest_contract.id
)


15.3 Get open positions by contract id

positions = trade_client.get_open_position(
symbol_or_asset_id=high_open_interest_contract.id
)

15.4 check cost basis and unrealized profit/loss

#Show cost basis
print(positions.cost_basis)

# Show unrealized profit/loss
print(positions.unrealized_pl)

16. Close the option position

trade_client.close_position(
    symbol_or_asset_id=high_open_interest_contract.symbol,
    close_options=ClosePositionRequest(qty="1")
)

17. Trade Update (Stream)

# Retrieve real-time live trade update data from the moment the order is placed until execution.
# Subscribe trade updates

trade_stream_client = TradingStream(api_key, secret_key, paper=paper, url_override=TRADE_API_WSS)

async def trade_updates_handler(data):
    print(data)

trade_stream_client.subscribe_trade_updates(trade_updates_handler)
trade_stream_client.run()

18. Market Data (Historical)

# Setup option historical data client

option_historical_data_client = OptionHistoricalDataClient(api_key, secret_key, url_override=DATA_API_URL)

# get option latest quote by symbol
req = OptionLatestQuoteRequest(
    symbol_or_symbols=[high_open_interest_contract.symbol],
)
option_historical_data_client.get_option_latest_quote(req)

# get option latest trade by symbol
req = OptionLatestTradeRequest(
    symbol_or_symbols=[high_open_interest_contract.symbol],
)
option_historical_data_client.get_option_latest_trade(req)


# get option chain by underlying_symbol
req = OptionChainRequest(
    underlying_symbol=high_open_interest_contract.underlying_symbol,
)
option_historical_data_client.get_option_chain(req)

19. Market Data (Stream)

# Live streaming of market data based on a collection of symbols or an individual symbol

option_data_stream_client = OptionDataStream(api_key, secret_key, url_override=OPTION_STREAM_DATA_WSS)

async def option_data_stream_handler(data):
    print(data)

symbols=[
    high_open_interest_contract.symbol,
]

option_data_stream_client.subscribe_quotes(option_data_stream_handler, *symbols) 
option_data_stream_client.subscribe_trades(option_data_stream_handler, *symbols)

option_data_stream_client.run()


Options Trading Using Postman

Using Postman, a popular API client, allows for the straightforward automation and testing of options trading strategies in both simulated and live trading environments. This will navigate you through the initial setup of Postman, establishing a connection with Alpaca’s Trading API, and conducting your first options paper trade.

Installation

  • Download Postman from the official website.
  • Follow the installation instructions for your operating system.

Configure Postman Environment

1. Open Postman

2. Click the "Environment" quick look (eye icon) on the top right and select "Add" to create a new environment.

3. Name your environment (e.g., "Alpaca Trading") and add the following variables:

  • api_key: Your Alpaca API key
  • secret_key: Your Alpaca secret key
  • base_url: Set to https://paper-api.alpaca.markets for paper trading or https://api.alpaca.markets for live trading.

4. Verifying your Authentication

Alpaca uses API keys for authentication. In each request, include the following headers:

  • APCA-API-KEY-ID: Set this to {{api_key}}.
  • APCA-API-SECRET-KEY: Set this to {{secret_key}}.

API Endpoints and Examples

1. Check Trading Account

Endpoint: GET {{base_url}}/v2/account

Description: Retrieves your trading account information.

Example:

  • Set the method to GET.
  • Enter the URL: {{base_url}}/v2/account.
  • Add headers for authentication.
  • Send the request and review the response for option_approved_level and option_trading_level.

2. Get List of Assets Which Are Options Enabled

Endpoint: GET {{base_url}}/v2/assets

Params: status=active and asset_class=us_equity.

Description: Fetches a list of assets that are eligible for options trading.

Example:

  • Method: GET.
  • URL: {{base_url}}/v2/assets?status=active&asset_class=us_equity.
  • Filter the JSON response for assets with "options_enabled": true.

3. Get List of Options Contracts

Endpoint: Custom Endpoint (as Alpaca's direct support for options might vary)

Description: Assume a hypothetical endpoint or method to fetch options contracts.

Example:

  • Since direct options trading might not be fully supported or documented, consult Alpaca’s API documentation for any updates or third-party services that offer options data compatible with Alpaca accounts.

4. Place an Order

Endpoint: POST {{base_url}}/v2/orders

Description: Place an order for an options contract.

Example:

  • Method: POST.
  • URL: {{base_url}}/v2/orders.
  • Body (JSON):
{
  "symbol": "SPY",
  "qty": "1",
  "side": "buy",
  "type": "market",
  "time_in_force": "day"
}
Modify the symbol to the specific options contract symbol

5. Monitor Orders and Positions

  • Orders Endpoint: GET {{base_url}}/v2/orders
  • Positions Endpoint: GET {{base_url}}/v2/positions

Description: Use these endpoints to monitor your active orders and current positions.

Example:

For orders: Use the GET method with the orders endpoint to retrieve a list of filled orders

  1. Click on the REST API under Collections and the GET Request under it.
  2. In the Endpoint section on top, type in “{{base_url}}/v2/orders”
  3. In the “Parameters” section, create a “status” variable and set its value as “filled” to review all filled orders.
  4. In “Headers”, create variables named APCA-API-KEY-ID, APCA-API-SECRET-KEY, and set their values to your api key and api secret respectively
  5. Send the request to retrieve information regarding all filled orders


For positions: Use the GET method with the positions endpoint to view your current holdings.

  1. Click on the REST API under Collections and the GET Request under it.
  2. In the Endpoint section on top, type in “{{base_url}}/v2/positions”
  3. In “Headers”, create variables named APCA-API-KEY-ID, APCA-API-SECRET-KEY, and set their values to your api key and api secret respectively.
  4. Send the request to retrieve information regarding all current positions

Bringing It Together

We empower both algorithmic and manual trading, ensuring flexibility for traders with varying automation preferences. For those interested in manually trading options, the dashboard serves as a centralized hub for trade management, market data access, and more.

For developers focused on using Trading API for options trading, Alpaca has a wide variety of SDKs to utilize, such as Alpaca-py or clients like Postman.

If you’re looking for additional technical resources, our Options for Trading API documentation is the perfect place to start developing and testing your trading algorithms today!


Options trading is not suitable for all investors due to its inherent high risk, which can potentially result in significant losses. Please read Characteristics and Risks of Standardized Options before investing in options.

All investments involve risk and the past performance of a security, or financial product does not guarantee future results or returns. There is no guarantee that any investment strategy will achieve its objectives. Please note that diversification does not assure a profit, or protect against loss. There is always the potential of losing money when you invest in securities, or other financial products. Investors should consider their investment objectives and risks carefully before investing.

The Paper Trading API is offered by AlpacaDB, Inc. and does not require real money or permit a user to conduct real transactions in the market. Providing use of the Paper Trading API is not an offer or solicitation to buy or sell securities, securities derivative or futures products of any kind, or any type of trading or investment advice, recommendation or strategy, given or in any manner endorsed by AlpacaDB, Inc. or any AlpacaDB, Inc. affiliate and the information made available through the Paper Trading API is not an offer or solicitation of any kind in any jurisdiction where AlpacaDB, Inc. or any AlpacaDB, Inc. affiliate (collectively, "Alpaca") is not authorized to do business.

Please note that the content is for informational purposes and is believed to be accurate as of posting date but may be subject to change. All screenshots are for illustrative purposes only.

Securities brokerage services are provided by Alpaca Securities LLC ("Alpaca Securities"), member FINRA/SIPC, a wholly-owned subsidiary of AlpacaDB, Inc. Technology and services are offered by AlpacaDB, Inc.

This is not an offer, solicitation of an offer, or advice to buy or sell securities or open a brokerage account in any jurisdiction where Alpaca Securities are not registered or licensed, as applicable.