henryhuangh
wealthsimple-python
Python

Wealthsimple trade API library for python based on the new wealthsimple graphql framework

Last updated Jun 23, 2026
18
Stars
5
Forks
1
Issues
0
Stars/day
Attention Score
60
Language breakdown
Python 100.0%
Files click to expand
README

wealthsimple-python

Unofficial Python client for the Wealthsimple Trade platform

Python 3.9+

FeaturesInstallationQuick StartDocumentationExamples


Important Disclaimer

This is an unofficial API client for Wealthsimple Trade. It is not affiliated with, officially maintained by, or endorsed by Wealthsimple. Use at your own risk.

  • No warranty or guarantee is provided
  • Always test with small amounts first
  • Keep your credentials secure
  • API may change without notice

Table of Contents

- Security Search & Quotes - Account Management - Stock Trading - Options Trading - Activity & History - Real-Time WebSocket Subscriptions

Features

Authentication

  • OAuth v2 authentication with automatic token refresh
  • Support for 2FA/OTP
  • Environment variable support for secure credential storage
  • Token expiry management and auto-refresh

Market Data

  • Security search by ticker symbol or company name
  • Real-time quotes with bid/ask spreads
  • Detailed security information (fundamentals, market status)
  • Nearest market open and market buffer lookups
  • Intraday chart quotes from Wealthsimple's native chart API
  • Support for stocks across multiple exchanges (NASDAQ, NYSE, TSX, etc.)
  • WebSocket subscriptions for real-time streaming data
- Real-time security quote updates - Activity feed notifications - Account balance change alerts - Identity and account core updates

Account Management

  • Retrieve all accounts (Personal, TFSA, RRSP, etc.)
  • Account balances and buying power
  • Current account financials and broker-native graph data
  • Current positions with unrealized P/L
  • Activity feed and order history
  • Daily historical portfolio financials with automatic pagination
- Net liquidation value over any date range - Net deposits vs. unrealised gain/loss - Simple return % calculations

Stock Trading

  • Market orders (buy/sell)
  • Limit orders (buy/sell)
  • Stop-limit orders (buy/sell)
  • Good-Till-Cancelled (GTC) and Day orders
  • Custom order creation

Options Trading

  • Full option chain retrieval
  • Available expiry dates
  • Option greeks (delta, gamma, theta, vega, rho)
  • Implied volatility
  • Buy to open/close
  • Sell to open/close (writing covered calls)
  • Transaction fee calculation

Interactive Trading Tool

  • Command-line interface for easy trading
  • Interactive security search
  • Real-time quote viewing
  • Order confirmation before execution
  • Support for both stocks and options

Installation

Requirements

  • Python 3.9 or higher

Install from PyPi using pip

pip install wealthsimple-python

Install directly from GitHub

pip install git+https://github.com/henryhuangh/wealthsimple-python.git

With optional dependencies:

# Secure token storage (highly recommended)
pip install "wealthsimple-python[keyring] @ git+https://github.com/henryhuangh/wealthsimple-python.git"

WebSocket subscriptions

pip install "wealthsimple-python[websockets] @ git+https://github.com/henryhuangh/wealthsimple-python.git"

Everything

pip install "wealthsimple-python[all] @ git+https://github.com/henryhuangh/wealthsimple-python.git"

Or clone and install locally

git clone https://github.com/henryhuangh/wealthsimple-python.git
cd wealthsimple-python
pip install .

With optional dependencies:

# Secure token storage (highly recommended)
pip install ".[keyring]"

WebSocket subscriptions

pip install ".[websockets]"

Everything

pip install ".[all]"

The core package only requires requests. Optional extras:

| Extra | Package | Purpose | |-------|---------|---------| | keyring | keyring | OS-level secure token storage (macOS Keychain, Windows Credential Locker, Linux Secret Service) | | websockets | websockets | Real-time streaming via WebSocket subscriptions | | all | both | Install everything |


Quick Start

Basic Usage

from wealthsimple_python import WealthsimpleV2

Initialize and authenticate

ws = WealthsimpleV2( username='your@email.com', password='yourpassword', otp='123456' # Optional, only if 2FA is enabled )

Search for a security

results = ws.search_securities('AAPL') securityid = ws.getticker_id('AAPL', 'NASDAQ')

Get a real-time quote

quote = ws.getsecurityquote(security_id) print(f"AAPL: ${quote['price']} (Bid: ${quote['bid']}, Ask: ${quote['ask']})")

Get your accounts

accounts = ws.get_accounts() for account in accounts: print(f"{account['nickname']}: {account['id']}")

Place a limit buy order

account_id = accounts[0]['id'] order = ws.limit_buy( accountid=accountid, securityid=securityid, quantity=1, limit_price=150.00 ) print(f"Order placed: {order['orderId']}")

Authentication

Basic Authentication

from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2(username='your@email.com', password='yourpassword')

With 2FA/OTP

If you have two-factor authentication enabled:

ws = WealthsimpleV2(
    username='your@email.com',
    password='yourpassword',
    otp='123456'  # Your 6-digit 2FA code
)

Token Persistence

After successful authentication, tokens are automatically saved securely using the keyring library (if available), which stores credentials in your operating system's secure credential storage:

  • macOS: Keychain
  • Windows: Credential Locker
  • Linux: Secret Service / KWallet
Benefits:
  • Tokens are encrypted by the operating system
  • Tokens persist across terminal sessions and reboots
  • More secure than plain text environment variables
  • Automatic loading on subsequent runs
Fallback: If keyring is not installed, tokens are saved to environment variables (WSACCESSTOKEN and WSREFRESHTOKEN) for the current session only.
# First time - authenticate with credentials
ws = WealthsimpleV2(username='your@email.com', password='yourpassword')

Tokens are now securely saved to keyring (and environment variables as fallback)

Later - even in a new terminal/session - tokens are auto-loaded

ws = WealthsimpleV2() # Automatically uses saved tokens from keyring

Token storage priority:

  • Keyring (secure OS credential storage) - checked first
  • Environment variables - fallback if keyring unavailable
  • Manual tokens - if provided explicitly

Logout / Clear Tokens

To clear all stored tokens:

ws.logout()  # Clears tokens from keyring, environment, and instance

Automatic Token Refresh

The client automatically refreshes expired access tokens:

# No need to manually refresh - it happens automatically
accounts = ws.get_accounts()  # Token is auto-refreshed if expired

When tokens are refreshed, both keyring and environment variables are automatically updated.

Manual Token Refresh

If needed, you can manually refresh:

success = ws.refreshaccesstoken()
if success:
    print("Token refreshed successfully")
    # Keyring and environment variables are automatically updated

Documentation

Security Search & Quotes

Search for Securities

# Search by ticker or company name
results = ws.search_securities('AAPL')

Search with specific security groups

results = ws.searchsecurities('TSLA', securitygroup_ids=['stock', 'adr'])

Display results

for security in results: print(f"{security['stock']['symbol']} - {security['stock']['name']}")

Get Ticker ID

# Get security ID by ticker symbol
securityid = ws.getticker_id('AAPL', 'NASDAQ')
securityid = ws.getticker_id('SHOP', 'TSX')

The ID is required for trading and quotes

print(f"Security ID: {security_id}")

Get Real-Time Quote

# Get quote for a security
quote = ws.getsecurityquote(security_id)

print(f"Price: ${quote['price']}") print(f"Bid: ${quote['bid']} x {quote['bidSize']}") print(f"Ask: ${quote['ask']} x {quote['askSize']}") print(f"High: ${quote['high']} | Low: ${quote['low']}") print(f"Volume: {quote['volume']}") print(f"Market Status: {quote['quoteStatus']}")

Get Detailed Security Information

# Get comprehensive security details
security = ws.getsecurity(securityid)

Access various data points

stock = security['stock'] print(f"Symbol: {stock['symbol']}") print(f"Name: {stock['name']}") print(f"Exchange: {stock['primaryExchange']}") print(f"Currency: {stock['currency']}") print(f"52-Week High: ${stock['high52Week']}") print(f"52-Week Low: ${stock['low52Week']}")

Fundamentals

fundamentals = stock.get('fundamentals', {}) print(f"P/E Ratio: {fundamentals.get('peRatio')}") print(f"Market Cap: ${fundamentals.get('marketCap')}") print(f"Dividend Yield: {fundamentals.get('dividendYield')}%")

Get Nearest Market Open

# Get previous/current/next market session boundaries
marketopen = ws.getnearestmarketopen()

print(f"Exchange: {marketopen['exchangeName']} ({marketopen['mic']})") print(f"Current trade day: {market_open['currentTradeDay']['date']}")

Get Market Buffer

# Get the current market buffer for a country / asset class
buffer = ws.getmarketbuffer(country='CA', is_option=False)
print(f"Market buffer: {buffer}")

Get Security Status

# Check trading status for a security
status = ws.getsecuritystatus(security_id)
print(f"Security status: {status['status']}")

Get Intraday Chart Quotes

# Get Wealthsimple-native chart points
bars = ws.getintradaychart_quotes(
    securityid=securityid,
    period='ONE_DAY',
    trading_session='REGULAR'
)

for bar in bars: print(f"{bar['timestamp']}: {bar['price']}")

Resolve Ticker Market Symbols

# Convert ticker.market symbols into Wealthsimple security IDs
symbol, market = ws.parsetickermarket('TSLA.US')
print(symbol, market)

securityid = ws.resolvesecurity_id('MFC.TO') print(f"Security ID: {security_id}")

Account Management

Get All Accounts

# Retrieve all accounts
accounts = ws.get_accounts()

for account in accounts: print(f"Nickname: {account['nickname']}") print(f"ID: {account['id']}") print(f"Type: {account['accountType']}") print(f"Status: {account['status']}") print("---")

Transfer Funds Between Accounts

# Move idle cash from one Wealthsimple account to another
transfer = ws.createinternaltransfer(
    sourceaccountid='non-registered-xxxxx',
    destinati,
    amount=25.75,
    currency='CAD'
)

print(f"Transfer created: {transfer['id']}")

Get Account Financials

# Get detailed financial information
account_ids = [acc['id'] for acc in accounts]
financials = ws.getaccountfinancials(account_ids)

for financial in financials: print(f"Account: {financial['accountId']}") print(f"Net Worth: ${financial['netWorth']['amount']} {financial['netWorth']['currency']}") print(f"Buying Power: ${financial['buyingPower']['amount']}") print(f"Cash Balance: ${financial['currentCashBalance']['amount']}") print("---")

Get Current Positions

# Get all positions across all accounts
positions = ws.get_positions()

for position in positions: security = position['security'] symbol = security['stock']['symbol'] quantity = position['quantity']

# Market value market_value = position['totalValue']['amount']

# P/L information pnl = position.get('profitLossAmount', {}).get('amount', 0) pnl_pct = position.get('profitLossPercentage', 0)

print(f"{symbol}: {quantity} shares") print(f" Value: ${market_value}") print(f" P/L: ${pnl} ({pnl_pct:.2f}%)")

Filter Positions by Account

# Get positions for specific accounts
account_ids = [accounts[0]['id']]  # Only first account
positions = ws.getpositions(accountids=account_ids)

Get Current Financials

# Get current metrics for a single account
current = ws.getaccountcurrentfinancials(accountid)

print(f"Net liquidation value: {current['netLiquidationValueV2']['amount']}") print(f"Net deposits: {current['netDeposits']['amount']}") print(f"Total withdrawals: {current['totalWithdrawals']['amount']}")

Get Account Graph Data

# Get broker-native graph data for charting
graph = ws.getaccountgraph_data(
    accountid=accountid,
    currency='CAD',
    timerange='ONEDAY',
    market_session='REGULAR'
)

for point in graph.get('data', []): print(f"{point['dateTime']}: {point['netLiquidationValue']['amount']}")

Stock Trading

Market Orders

# Market buy
order = ws.market_buy(
    accountid=accountid,
    securityid=securityid,
    quantity=10
)

Market sell

order = ws.market_sell( accountid=accountid, securityid=securityid, quantity=10 )

print(f"Order ID: {order['orderId']}") print(f"Status: {order['status']}")

Limit Orders

# Limit buy - buy at or below limit price
order = ws.limit_buy(
    accountid=accountid,
    securityid=securityid,
    quantity=5,
    limit_price=150.00
)

Limit sell - sell at or above limit price

order = ws.limit_sell( accountid=accountid, securityid=securityid, quantity=5, limit_price=160.00 )

Stop-Limit Orders

# Stop-limit buy

When price rises to $155, place limit buy at $156

order = ws.stoplimitbuy( accountid=accountid, securityid=securityid, quantity=5, limit_price=156.00, stop_price=155.00 )

Stop-limit sell (stop loss)

When price drops to $145, place limit sell at $144

order = ws.stoplimitsell( accountid=accountid, securityid=securityid, quantity=5, limit_price=144.00, stop_price=145.00 )

Custom Order Creation

# Create a custom order with all parameters
order = ws.create_order(
    accountid=accountid,
    securityid=securityid,
    quantity=10,
    limit_price=150.00,
    ordertype='BUYQUANTITY',
    ordersubtype='LIMIT',
    timeinforce='GTC',  # Good-Till-Cancelled
    stop_price=None
)

Cancel Orders

# Place an order and get the external ID
order = ws.limit_buy(
    accountid=accountid,
    securityid=securityid,
    quantity=5,
    limit_price=150.00
)

Get the external ID from the order response

external_id = order.get('externalCanonicalId') or order.get('externalId') if external_id: # Cancel the order cancelresponse = ws.cancelorder(external_id) print(f"Order {external_id} cancelled successfully") else: print("Could not find external ID in order response")

Note: The external_id is the unique identifier for the order (typically in the format order-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). It is returned in the order response when you create an order, or can be retrieved from pending orders or activity history.

Options Trading

Get Option Expiry Dates

# Get available expiry dates for an underlying security
expirydates = ws.getoptionexpirydates(security_id)

print(f"Available expiry dates: {len(expiry_dates)}") for date in expiry_dates[:5]: # Show first 5 print(f" {date}")

Get Option Chain

# Get call options for a specific expiry
options = ws.getoptionchain(
    securityid=securityid,
    expirydate=expirydates[0],
    opti
)

Display option chain

for option in options: symbol = option['optionSymbol'] strike = option['strikePrice']['amount']

# Greeks greeks = option.get('greeks', {}) delta = greeks.get('delta') gamma = greeks.get('gamma') theta = greeks.get('theta') vega = greeks.get('vega') iv = greeks.get('impliedVolatility')

# Quote quote = option.get('quote', {}) bid = quote.get('bid') ask = quote.get('ask')

print(f"{symbol}") print(f" Strike: ${strike}") print(f" Bid: ${bid} | Ask: ${ask}") print(f" Delta: {delta:.4f} | IV: {iv:.2%}") print("---")

Get Put Options

# Get put options
puts = ws.getoptionchain(
    securityid=securityid,
    expirydate=expirydates[0],
    opti
)

Filter Options by Strike Price

# Get options near a specific strike price
options = ws.getoptionchain(
    securityid=securityid,
    expirydate=expirydates[0],
    opti,
    min_strike=145.00,
    max_strike=155.00
)

Buy Options (Long Position)

# Buy to open a call option
order = ws.buy_option(
    accountid=accountid,
    option_id=options[0]['id'],
    quantity=1,  # 1 contract = 100 shares
    limit_price=2.50  # Premium per share ($250 total)
)

Buy to close a short position

order = ws.buy_option( accountid=accountid, optionid=optionid, quantity=1, limit_price=2.50, ordersubtype='LIMIT' )

Sell Options (Short Position or Close Long)

# Sell to open (write a covered call)
order = ws.sell_option(
    accountid=accountid,
    optionid=optionid,
    quantity=1,
    limit_price=2.50
)

Sell to close a long position

order = ws.sell_option( accountid=accountid, optionid=optionid, quantity=1, limit_price=2.50, ordersubtype='LIMIT' )

Calculate Option Fees

# Calculate transaction fees for buying options
fees = ws.getoptiontransaction_fees(
    side='BUY',
    premium=2.50,  # Price per share
    quantity=1,    # Number of contracts
    currency='USD'
)

print(f"Premium: ${fees['premium']['amount']}") print(f"Commission: ${fees['commission']['amount']}") print(f"Total Cost: ${fees['totalCost']['amount']}")

Activity & History

Get Activity Feed

# Get recent activities
activities = ws.get_activities(limit=50)

for activity in activities: activity_type = activity['type'] symbol = activity.get('assetSymbol', 'N/A') date = activity.get('occurredAt')

print(f"{date}: {activity_type} - {symbol}")

Filter Activities by Type

# Get only buy/sell activities
activities = ws.get_activities(
    types=['buy', 'sell'],
    limit=20
)

Filter Activities by Account

# Get activities for specific account
activities = ws.get_activities(
    accountids=[accountid],
    limit=50
)

Real-Time WebSocket Subscriptions

The library supports real-time data streaming via WebSocket subscriptions. This enables you to receive live updates without polling the API.

Prerequisites

Subscriptions require the websockets library:

pip install websockets

Basic Usage

import asyncio
from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2()

async def stream_quotes(): # Get security ID securityid = ws.getticker_id('AAPL')

# Connect and subscribe async with ws.subscribe() as sub: async for msg in sub.streamquotes([securityid]): quote_data = msg['payload']['data']['securityQuoteUpdates']['quoteV2'] print(f"AAPL Price: ${quote_data['price']}") print(f"Bid: ${quotedata['bid']}, Ask: ${quotedata['ask']}")

Run the async function

asyncio.run(stream_quotes())

Stream Real-Time Quotes

Monitor live price updates for one or more securities:

async def watch_stocks():
    ws = WealthsimpleV2()

# Get security IDs aaplid = ws.getticker_id('AAPL') tslaid = ws.getticker_id('TSLA')

async with ws.subscribe() as sub: async for msg in sub.streamquotes([aaplid, tsla_id]): quote_data = msg['payload']['data']['securityQuoteUpdates'] securityid = quotedata['id'] quote = quote_data['quoteV2']

print(f"{security_id}: ${quote['price']} " f"(Bid: ${quote['bid']}, Ask: ${quote['ask']})")

asyncio.run(watch_stocks())

Stream Activity Feed Updates

Get notified when new activities occur (orders, trades, deposits, etc.):

async def monitor_activity():
    ws = WealthsimpleV2()

async with ws.subscribe() as sub: async for msg in sub.streamactivityupdates(): update = msg['payload']['data']['activityFeedUpdates'] print(f"New activity on account {update['accountId']}") print(f"Activity ID: {update['activityId']}") print(f"Updated at: {update['updatedAt']}")

asyncio.run(monitor_activity())

Stream Account Balance Changes

Monitor cash balance changes in custodian accounts:

async def watch_balances():
    ws = WealthsimpleV2()

# Get custodian account IDs from your accounts accounts = ws.get_accounts() custodian_ids = [] for account in accounts: for custodian in account.get('custodianAccounts', []): custodian_ids.append(custodian['id'])

if custodian_ids: async with ws.subscribe() as sub: async for msg in sub.streambalancechanges(custodian_ids): print("Balance change detected!") print(json.dumps(msg, indent=2))

asyncio.run(watch_balances())

Stream Identity and Account Updates

Get notified of account or identity changes:

async def watchaccountupdates():
    ws = WealthsimpleV2()

async with ws.subscribe() as sub: async for msg in sub.streamidentityupdates(): update = msg['payload']['data']['identityAccountCoreUpdates'] print(f"Update type: {update['__typename']}") print(f"Event: {update.get('eventName', 'N/A')}") print(f"ID: {update.get('id', 'N/A')}")

asyncio.run(watchaccountupdates())

Multiple Subscriptions Concurrently

You can run multiple subscriptions at the same time:

async def multi_stream():
    ws = WealthsimpleV2()
    securityid = ws.getticker_id('AAPL')

async with ws.subscribe() as sub: # Create tasks for multiple subscriptions tasks = []

# Stream quotes async def quotes(): async for msg in sub.streamquotes([securityid]): quote = msg['payload']['data']['securityQuoteUpdates']['quoteV2'] print(f"Quote: ${quote['price']}") tasks.append(asyncio.create_task(quotes()))

# Stream activity async def activity(): async for msg in sub.streamactivityupdates(): print(f"Activity: {msg['payload']['data']['activityFeedUpdates']['activityId']}") tasks.append(asyncio.create_task(activity()))

# Run both concurrently await asyncio.gather(*tasks)

asyncio.run(multi_stream())

Keep Connection Alive

The subscription client automatically handles connection management. You can also send ping messages:

async with ws.subscribe() as sub:
    # Send ping to keep connection alive
    await sub.ping()

# Stream quotes async for msg in sub.streamquotes([securityid]): # Process messages pass

Error Handling

async def safe_stream():
    ws = WealthsimpleV2()

try: async with ws.subscribe() as sub: async for msg in sub.streamquotes([securityid]): # Process message pass except Exception as e: print(f"Subscription error: {e}") # Connection will be automatically closed

asyncio.run(safe_stream())

Subscription Message Structure

All subscription messages follow this structure:

{
    "type": "next",  # or "error", "complete"
    "id": "subscription-id",
    "payload": {
        "data": {
            # Subscription-specific data
        }
    }
}

For quote updates, the payload structure is:

{
    "payload": {
        "data": {
            "securityQuoteUpdates": {
                "id": "sec-s-xxxxx",
                "quoteV2": {
                    "price": 150.25,
                    "bid": 150.20,
                    "ask": 150.30,
                    "currency": "USD",
                    "marketStatus": "OPEN",
                    # ... more fields
                }
            }
        }
    }
}

Testing Subscriptions

A test script is included to demonstrate subscription functionality:

# Stream quotes for a ticker
python test_sub.py --ticker AAPL

Stream activity updates

python test_sub.py --activity

Multiple subscriptions

python test_sub.py --ticker AAPL --activity --seconds 60

For more options, see test_sub.py --help.


Interactive Trading Tool

An interactive command-line interface is included for easy testing and trading:

python interactive_trade.py

Features

  • Interactive Authentication: Enter credentials securely
  • Security Search: Search by ticker or browse popular stocks
  • Real-Time Quotes: View detailed security information
  • Stock Trading: Place market and limit orders
  • Options Trading: Browse option chains and trade options
  • Account Selection: Choose from your trading accounts
  • Order Confirmation: Review before executing

Usage

The script will guide you through:

  • Authentication - Login with your credentials
  • Security Search - Find stocks or options
  • Quote Display - View real-time data
  • Account Selection - Choose your trading account
  • Trade Type - Select stocks or options
  • Order Placement - Execute with confirmation

Examples

Example 1: Portfolio Summary

from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2()

Get all positions

positions = ws.get_positions()

total_value = 0 print("Your Portfolio:") print("=" * 60)

for position in positions: symbol = position['security']['stock']['symbol'] quantity = position['quantity'] value = position['totalValue']['amount'] pnl = position.get('profitLossAmount', {}).get('amount', 0)

total_value += value

print(f"{symbol:6s} | Qty: {quantity:>6} | Value: ${value:>10.2f} | P/L: ${pnl:>8.2f}")

print("=" * 60) print(f"Total Portfolio Value: ${total_value:,.2f}")

Example 2: Buy Stock with Quote Check

from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2()

Define trade parameters

ticker = 'AAPL' exchange = 'NASDAQ' quantity = 10

Get security ID and current quote

securityid = ws.getticker_id(ticker, exchange) quote = ws.getsecurityquote(security_id)

current_price = quote['price'] print(f"Current price of {ticker}: ${current_price}")

Calculate limit price (1% below current)

limitprice = round(currentprice * 0.99, 2) print(f"Placing limit buy at ${limit_price}")

Get account

accounts = ws.get_accounts() account_id = accounts[0]['id']

Place order

order = ws.limitbuy(accountid, securityid, quantity, limitprice) print(f"Order placed: {order['orderId']}") print(f"Status: {order['status']}")

Example 3: Sell Covered Call

from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2()

Get security (stock you own)

ticker = 'AAPL' securityid = ws.getticker_id(ticker, 'NASDAQ')

Get option expiry dates

expirydates = ws.getoptionexpirydates(security_id) nearestexpiry = expirydates[0]

print(f"Expiry date: {nearest_expiry}")

Get call options

calls = ws.getoptionchain(securityid, nearestexpiry, 'CALL')

Find out-of-the-money call (strike > current price)

quote = ws.getsecurityquote(security_id) current_price = quote['price']

otmcalls = [c for c in calls if c['strikePrice']['amount'] > currentprice]

if otm_calls: selectedcall = otmcalls[0] # Nearest OTM strike

strike = selected_call['strikePrice']['amount'] optionid = selectedcall['id']

# Get bid price bid = selected_call['quote']['bid']

print(f"Selling covered call at ${strike} strike for ${bid} premium")

# Sell to open accountid = ws.getaccounts()[0]['id'] order = ws.selloption(accountid, optionid, quantity=1, limitprice=bid)

print(f"Order placed: {order['orderId']}")

Example 4: Monitor Multiple Positions

from wealthsimple_python import WealthsimpleV2
import time

ws = WealthsimpleV2()

def display_portfolio(): positions = ws.get_positions() print("\n" + "=" * 80) print(f"{'Symbol':<10} {'Qty':<8} {'Value':<12} {'P/L $':<12} {'P/L %':<10}") print("=" * 80)

for pos in positions: symbol = pos['security']['stock']['symbol'] qty = pos['quantity'] value = pos['totalValue']['amount'] pnl_amt = pos.get('profitLossAmount', {}).get('amount', 0) pnl_pct = pos.get('profitLossPercentage', 0)

print(f"{symbol:<10} {qty:<8} ${value:<11.2f} ${pnlamt:<11.2f} {pnlpct:>7.2f}%")

Display portfolio every 60 seconds

while True: display_portfolio() time.sleep(60)

Example 5: Real-Time Price Monitor

from wealthsimple_python import WealthsimpleV2
import asyncio

ws = WealthsimpleV2()

async def monitor_price(): # Get security ID securityid = ws.getticker_id('AAPL')

print("Monitoring AAPL price... (Ctrl+C to stop)") print("=" * 60)

async with ws.subscribe() as sub: async for msg in sub.streamquotes([securityid]): quote = msg['payload']['data']['securityQuoteUpdates']['quoteV2'] price = quote['price'] bid = quote['bid'] ask = quote['ask'] spread = ask - bid if bid and ask else None

print(f"\rAAPL: ${price:.2f} | Bid: ${bid:.2f} | Ask: ${ask:.2f} | " f"Spread: ${spread:.2f}" if spread else f"AAPL: ${price:.2f}", end='', flush=True)

asyncio.run(monitor_price())

Example 6: Real-Time Order Monitor

from wealthsimple_python import WealthsimpleV2
import asyncio

ws = WealthsimpleV2()

async def watch_orders(): print("Monitoring for new activities...") print("=" * 60)

async with ws.subscribe() as sub: async for msg in sub.streamactivityupdates(): update = msg['payload']['data']['activityFeedUpdates'] print(f"\nNew activity detected!") print(f" Account: {update['accountId']}") print(f" Activity ID: {update['activityId']}") print(f" Updated: {update['updatedAt']}")

# You can fetch full activity details using get_activities() # activities = ws.get_activities(limit=1) # if activities: # print(f" Type: {activities[0].get('type')}")

asyncio.run(watch_orders())

Example 7: Historical Portfolio Chart

from datetime import date, timedelta
from wealthsimple_python import WealthsimpleV2

ws = WealthsimpleV2()

Fetch one year of daily data

start_date = (date.today() - timedelta(days=365)).isoformat() result = ws.getidentityhistorical_financials( startdate=startdate, currency="CAD", includesimplereturns=True, )

edges = result.get("edges", []) print(f"Retrieved {len(edges)} daily records")

for edge in edges: node = edge["node"] date = node["date"] value = float(node["netLiquidationValueV2"]["amount"]) deposits = float(node["netDepositsV2"]["amount"]) ret = node.get("simpleReturns", {}) print(rate) rate = float(ret.get("rate", 0)) print(f"{date}: value=${value:,.2f} deposits=${deposits:,.2f} return={rate:.2f}%")


Advanced Usage

Custom GraphQL Queries

# Execute custom GraphQL queries
query = """
    query CustomQuery($securityId: ID!) {
        security(id: $securityId) {
            id
            stock {
                symbol
                name
                currency
            }
        }
    }
"""

variables = {"securityId": security_id} result = ws.graphql_query("CustomQuery", query, variables)

Error Handling

from wealthsimple_python import WealthsimpleV2

try: ws = WealthsimpleV2(username='user@email.com', password='wrong_password') except Exception as e: print(f"Authentication failed: {e}")

try: securityid = ws.gettickerid('INVALIDTICKER', 'NASDAQ') if not security_id: print("Security not found") except Exception as e: print(f"Error: {e}")

Token Management

Tokens are automatically saved to and loaded from keyring (secure OS credential storage):

# Authenticate once - tokens are securely saved to keyring
ws = WealthsimpleV2(username='your@email.com', password='yourpassword')

Tokens stored in macOS Keychain / Windows Credential Locker / Linux Secret Service

Later sessions (even after reboot) - tokens are automatically loaded

ws = WealthsimpleV2() # Automatically uses saved tokens from keyring

Logout and clear all tokens

ws.logout() # Removes tokens from keyring and environment

Or manually provide tokens (overrides keyring and environment variables)

ws = WealthsimpleV2(accesstoken='yourtoken', refreshtoken='yourrefresh')

Security Note: Using keyring is highly recommended as it provides OS-level encryption and secure storage. Tokens are never stored in plain text files.


API Reference

Class: WealthsimpleV2

Initialization

ws = WealthsimpleV2(
    username=None,
    password=None,
    otp=None,
    client_id=None,
    access_token=None,
    refresh_token=None
)

Authentication Methods

| Method | Description | | -------------------------------------------- | --------------------------------------------- | | authenticate(username, password, otp=None) | Authenticate with username/password | | refreshaccesstoken() | Manually refresh the access token | | logout() | Clear all tokens from keyring and environment |

Security Methods

| Method | Description | | --------------------------------------------------- | --------------------------------------- | | searchsecurities(query, securitygroup_ids=None) | Search for securities by ticker or name | | getsecurity(securityid, currency=None) | Get detailed security information | | getsecurityquote(security_id, currency=None) | Get real-time quote | | getnearestmarket_open() | Get nearest market open details | | getmarketbuffer(country='CA', is_option=False) | Get the market buffer multiplier | | getsecuritystatus(security_id) | Get security trading status | | getintradaychart_quotes(...) | Get broker-native intraday chart quotes | | gettickerid(ticker, exchange=None) | Get security ID from ticker symbol | | parsetickermarket(ticker_market) | Split TICKER.MARKET into parts | | isus_exchange(exchange) | Check whether an exchange is US-listed | | iscanadian_exchange(exchange) | Check whether an exchange is CA-listed | | resolvesecurityid(ticker_market) | Resolve TICKER.MARKET to a security ID |

Account Methods

| Method | Description | | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | | getaccounts(identityid=None) | Get all accounts | | createinternaltransfer(sourceaccountid, destinationaccountid, amount, currency='CAD') | Transfer funds between accounts | | getaccountfinancials(account_ids, currency='CAD') | Get account balances | | getaccountcurrentfinancials(accountid, currency='CAD', start_date=None) | Get current account financials | | getaccountgraphdata(accountid, currency='CAD', timerange='ONEDAY', marketsession='REGULAR', includesimple_returns=False) | Get account graph data | | getpositions(identityid=None, accountids=None, securitytypes=None) | Get current positions | | getactivities(accountids=None, types=None, limit=50) | Get activity feed | | getidentity(identityid=None) | Get user identity information | | getidentityhistoricalfinancials(identityid=None, currency='CAD', startdate=None, enddate=None, accountids=None, includesimple_returns=False, ...) | Get daily historical portfolio financials |

Stock Trading Methods

| Method | Description | | ----------------------------------------------------------------------------- | ------------------------ | | marketbuy(accountid, security_id, quantity) | Place market buy order | | marketsell(accountid, security_id, quantity) | Place market sell order | | limitbuy(accountid, securityid, quantity, limitprice) | Place limit buy order | | limitsell(accountid, securityid, quantity, limitprice) | Place limit sell order | | stoplimitbuy(accountid, securityid, quantity, limitprice, stopprice) | Place stop-limit buy | | stoplimitsell(accountid, securityid, quantity, limitprice, stopprice) | Place stop-limit sell | | createorder(accountid, security_id, quantity, ...) | Create custom order | | cancelorder(externalid) | Cancel an existing order |

Options Trading Methods

| Method | Description | | -------------------------------------------------------------------- | -------------------------- | | getoptionchain(securityid, expirydate, option_type, ...) | Get option chain | | getoptionexpirydates(securityid, mindate=None, maxdate=None) | Get available expiry dates | | getoptiontransaction_fees(side, premium, quantity, currency) | Calculate option fees | | buyoption(accountid, optionid, quantity, limitprice, ...) | Buy option contract | | selloption(accountid, optionid, quantity, limitprice, ...) | Sell option contract |

Subscription Methods

| Method | Description | | ------------------------------------------------------------ | -------------------------------------- | | subscribe(device_id=None) | Create a WebSocket subscription client | | WealthsimpleSubscriptions.streamquotes(securityids, ...) | Stream real-time quote updates | | WealthsimpleSubscriptions.streamactivityupdates() | Stream activity feed updates | | WealthsimpleSubscriptions.streamidentityupdates(...) | Stream identity/account updates | | WealthsimpleSubscriptions.streambalancechanges(...) | Stream balance change notifications | | WealthsimpleSubscriptions.ping() | Send keep-alive ping |

Utility Methods

| Method | Description | | ------------------------------------------------------ | ---------------------------- | | graphqlquery(operationname, query, variables=None) | Execute custom GraphQL query |

Class: WealthsimpleSubscriptions

WebSocket subscription client for real-time data streaming. Created via ws.subscribe().

Context Manager Usage

async with ws.subscribe() as sub:
    # Use subscription methods
    async for msg in sub.streamquotes([securityid]):
        # Process messages
        pass

Methods

| Method | Description | | ----------------------------------------------- | ---------------------------------------- | | connect() | Establish WebSocket connection | | close() | Close WebSocket connection | | streamquotes(securityids, currency=None) | Stream real-time quotes for securities | | streamactivityupdates() | Stream activity feed notifications | | streamidentityupdates(identity_id=None) | Stream identity/account core updates | | streambalancechanges(custodianaccountids) | Stream custodian account balance changes | | ping() | Send ping to keep connection alive |


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Areas for Improvement

  • Add unit tests
  • Implement rate limiting
  • Support for multi-leg option strategies
  • Enhanced error handling and retry logic
  • CLI improvements

Resources


Support

For questions, issues, or feature requests, please open an issue on GitHub.


Legal

This project is not affiliated with, officially maintained by, or endorsed by Wealthsimple. All trademarks are the property of their respective owners.

USE AT YOUR OWN RISK. This software is provided "as is" without warranty of any kind. The authors are not responsible for any financial losses or damages resulting from the use of this software.

Always verify orders before executing and start with small amounts when testing.


Legacy API

The original REST API (archive/wealthsimple.py) is still available but uses deprecated Trade API endpoints. It is strongly recommended to migrate to the v2 GraphQL API for new projects.

Legacy API Quick Reference

The legacy API provided basic functionality:

# Legacy API (deprecated)
from archive.wealthsimple import wealthsimple

ws = wealthsimple('email', 'password', MFA='123456') accounts = ws.accounts() tickid = ws.tickid('AAPL', 'NASDAQ') ws.limitbuy(tickid, 10, 140)

For legacy API documentation, see archive/README.md.

🔗 More in this category

© 2026 GitRepoTrend · henryhuangh/wealthsimple-python · Updated daily from GitHub