Pricing Endpoint¶
OANDA Reference: Pricing Endpoints
Account pricing snapshots, sampled price streams and account-specific candles.
The top-level pricing time and since parameter are wire strings; nested price
and candle time attributes are Python datetimes. Supply a since value in the
client's selected datetime format.
The examples below illustrate calls and response access. Helpers run only when called. Examples that create, update, cancel or close resources change account state; use a dedicated practice account and inspect each response. Local validation and HTTPX transport exceptions can occur in addition to the API errors listed.
get_pricing¶
Get current prices for instruments.
OANDA Endpoint: GET /v3/accounts/{accountID}/pricing
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get current pricing for multiple instruments
result = await client.pricing.get_pricing(
account_id=client.account_id,
instruments=["EUR_USD", "GBP_USD"], # Change to your instruments
include_units_available=True,
)
print(f"Got {len(result['prices'])} prices at {result['time']}")
# homeConversions is optional, only present if include_home_conversions=True
if "homeConversions" in result:
print(f"Got {len(result['homeConversions'])} home conversions")
asyncio.run(main())
🔗 OANDA Documentation: Get Pricing
🔗 Source: pricing.get_pricing
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account ID |
instruments |
list[str] | ✅ | List of instruments to get prices for |
* |
Keyword-only parameters below | ||
since |
str | None | âž– | Only get prices changed since this time |
include_units_available |
bool | âž– | Include units available info (default: True). Deprecated by OANDA; will be removed in a future API update |
include_home_conversions |
bool | âž– | Include home currency conversions (default: False) |
Returns: GetPricingResponse - Dictionary containing prices (list[ClientPrice]), time (str), and optionally homeConversions (list[HomeConversions])
Raises:
FiveTwentyError - API errors:
- 400: Invalid request parameters (check
e.status == 400) - 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited)
get_pricing_stream¶
Stream real-time pricing data.
OANDA Endpoint: GET /v3/accounts/{accountID}/pricing/stream
import asyncio
from contextlib import aclosing
from dotenv import load_dotenv
from fivetwenty import AsyncClient
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Stream real-time pricing data for instruments
count = 0
stream = client.pricing.get_pricing_stream(
account_id=client.account_id,
instruments=["EUR_USD", "GBP_USD"], # Change to your instruments
snapshot=True,
)
async with aclosing(stream):
async for price in stream:
print(f"Price update: {price}")
count += 1
if count >= 5: # Stop after 5 updates for testing
break
asyncio.run(main())
🔗 OANDA Documentation: Stream Pricing
🔗 Source: pricing.get_pricing_stream
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account ID |
instruments |
list[str] | ✅ | List of instruments to stream |
* |
Keyword-only parameters below | ||
snapshot |
bool | âž– | Include initial snapshot (default: True) |
include_home_conversions |
bool | âž– | Include home currency conversion factors (default: False) |
stall_timeout |
float | âž– | Timeout for detecting stream stalls in seconds (default: 30.0) |
Returns: AsyncIterator[ClientPrice | PricingHeartbeat] - Async iterator yielding ClientPrice or PricingHeartbeat objects
Raises:
FiveTwentyError - API errors:
- 400: Invalid request parameters (check
e.status == 400) - 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited)
StreamStall - On a detected stream stall; HTTPX transport errors can also propagate
get_account_instrument_candles¶
Get account-specific historical candle data for an instrument.
OANDA Endpoint: GET /v3/accounts/{accountID}/instruments/{instrument}/candles
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get historical candlestick data for an instrument
candles = await client.pricing.get_account_instrument_candles(
account_id=client.account_id,
instrument="EUR_USD", # Change to your instrument
granularity="H1", # Change to desired granularity (S5, M1, H1, D, etc.)
count=100, # Number of candles to retrieve (omit count when both time boundaries are supplied)
)
print(f"Got {len(candles['candles'])} candles for {candles['instrument']}")
asyncio.run(main())
🔗 OANDA Documentation: Get Candles
🔗 Source: pricing.get_account_instrument_candles
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account ID |
instrument |
str | ✅ | Instrument to get candles for |
* |
Keyword-only parameters below | ||
price |
str | âž– | Price type ("M", "B", "A", "BA", "BM", "AM", "BAM") (default: "M") |
granularity |
str | âž– | Granularity of candles (default: "S5") |
count |
int | None | âž– | Number of candles to return (max 5000) |
from_time |
datetime | None | âž– | Start time for candle range |
to_time |
datetime | None | âž– | End time for candle range |
smooth |
bool | âž– | Smooth candles (default: False) |
include_first |
bool | âž– | Include first candle (default: True, only used with from_time) |
daily_alignment |
int | âž– | Daily alignment hour (default: 17) |
alignment_timezone |
str | âž– | Timezone for alignment (default: "America/New_York") |
weekly_alignment |
str | âž– | Weekly alignment day (default: "Friday") |
units |
Decimal | int | str | âž– | Position size for volume-weighted bid/ask prices (default: 1) |
Returns: CandlesResponse - Dictionary containing instrument, granularity, and list of candlesticks
Raises:
FiveTwentyError - API errors:
- 400: Invalid request parameters (check
e.status == 400) - 401/403: Authentication failed (check
e.is_authentication_error) - 404: Instrument or account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited)
ValueError - If count and both from_time and to_time are specified
get_latest_candles¶
Get latest candles for multiple instruments.
OANDA Endpoint: GET /v3/accounts/{accountID}/candles/latest
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get latest candles for multiple instrument/granularity combinations
result = await client.pricing.get_latest_candles(
account_id=client.account_id,
# Format: instrument:granularity:price_type
candle_specifications=["EUR_USD:S5:BM", "GBP_USD:M1:BM"],
units=50, # Position size used for volume-weighted bid/ask prices
)
for candle_data in result["latestCandles"]:
print(f"{candle_data['instrument']}: {len(candle_data['candles'])} candles")
asyncio.run(main())
🔗 OANDA Documentation: Get Latest Candles
🔗 Source: pricing.get_latest_candles
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account ID |
candle_specifications |
list[str] | ✅ | List of candle specifications (instrument:granularity:price) |
* |
Keyword-only parameters below | ||
units |
Decimal | int | str | âž– | Position size for volume-weighted bid/ask prices (default: 1) |
smooth |
bool | âž– | Smooth candles (default: False) |
daily_alignment |
int | âž– | Daily alignment hour (default: 17) |
alignment_timezone |
str | âž– | Timezone for alignment (default: "America/New_York") |
weekly_alignment |
str | âž– | Weekly alignment day (default: "Friday") |
Returns: LatestCandlesResponse - Dictionary containing latest candle data for multiple instruments
Raises:
FiveTwentyError - API errors:
- 400: Invalid request parameters (check
e.status == 400) - 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited)
ValueError - On invalid parameters
stream_pricing_with_retries¶
Stream pricing with automatic reconnection and configuration.
OANDA Endpoint: GET /v3/accounts/{accountID}/pricing/stream
import asyncio
from contextlib import aclosing
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.models.streaming import (
ReconnectionPolicy,
StreamingConfiguration,
StreamState,
)
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Configure automatic reconnection for robust streaming
config = StreamingConfiguration(
reconnection_policy=ReconnectionPolicy(
max_attempts=5,
delay_seconds=2.0, # Retry up to 5 times with 2s delay
)
)
# Stream pricing with automatic reconnection on failures
count = 0
stream = client.pricing.stream_pricing_with_retries(
account_id=client.account_id,
instruments=["EUR_USD", "GBP_USD"], # Change to your instruments
config=config,
)
async with aclosing(stream):
async for price_data, state in stream:
if state == StreamState.RECONNECTING:
print("Connection lost, retrying...")
elif state == StreamState.CONNECTED:
print(f"Price update: {price_data}")
count += 1
if count >= 5: # Stop after 5 updates for testing
break
asyncio.run(main())
🔗 OANDA Documentation: Stream Pricing
🔗 Source: pricing.stream_pricing_with_retries
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account ID |
instruments |
list[str] | ✅ | List of instruments to stream |
* |
Keyword-only parameters below | ||
snapshot |
bool | âž– | Include snapshot of current prices (default: True) |
include_home_conversions |
bool | âž– | Include home currency conversions (default: False) |
config |
StreamingConfiguration | None | âž– | Streaming configuration with reconnection policy |
Returns: AsyncIterator[tuple[ClientPrice | PricingHeartbeat, StreamState]] - Async iterator yielding tuples of (price_data, stream_state)
Raises:
FiveTwentyError - API errors:
- 400: Invalid request parameters (check
e.status == 400) - 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited)
The final stream or transport exception propagates when the retry budget is exhausted