# Market Data API Reference
This document provides complete reference documentation for market data operations in the Ostium Rust SDK.
## Overview
The market data API provides access to:
- Real-time price information
- Trading pair details
- Market hours and status
- Historical data (planned)
- Market statistics
All market data operations are read-only and don't require authentication.
## Price Data
### Getting Current Prices
#### `get_price`
Retrieves current price information for a trading pair.
```rust
pub async fn get_price(&self, symbol: &str) -> Result<Price>
```
**Parameters:**
- `symbol: &str` - Trading pair symbol (e.g., "BTC/USD", "ETH/USD")
**Returns:**
- `Result<Price>` - Current price information
**Price Structure:**
```rust
pub struct Price {
pub symbol: String, // Trading pair symbol
pub mark_price: Decimal, // Current mark price
pub index_price: Decimal, // Index price
pub last_price: Decimal, // Last traded price
pub bid: Decimal, // Best bid price
pub ask: Decimal, // Best ask price
pub high_24h: Decimal, // 24-hour high
pub low_24h: Decimal, // 24-hour low
pub volume_24h: Decimal, // 24-hour volume
pub change_24h: Decimal, // 24-hour price change
pub change_24h_percent: Decimal, // 24-hour percentage change
pub funding_rate: Option<Decimal>, // Current funding rate
pub next_funding: Option<u64>, // Next funding timestamp
pub open_interest: Decimal, // Total open interest
pub timestamp: u64, // Price timestamp
}
```
**Example:**
```rust
let price = client.get_price("BTC/USD").await?;
println!("BTC/USD Price Information:");
println!(" Mark Price: ${}", price.mark_price);
println!(" 24h High: ${}", price.high_24h);
println!(" 24h Low: ${}", price.low_24h);
println!(" 24h Volume: {}", price.volume_24h);
println!(" 24h Change: {}%", price.change_24h_percent);
if let Some(funding_rate) = price.funding_rate {
println!(" Funding Rate: {}%", funding_rate * 100);
}
```
### Batch Price Queries
#### `get_prices`
Retrieves prices for multiple trading pairs in a single request.
```rust
pub async fn get_prices(&self, symbols: &[&str]) -> Result<Vec<Price>>
```
**Example:**
```rust
let symbols = ["BTC/USD", "ETH/USD", "SOL/USD"];
let prices = client.get_prices(&symbols).await?;
for price in prices {
println!("{}: ${} ({}%)",
price.symbol,
price.mark_price,
price.change_24h_percent);
}
```
## Trading Pairs
### Getting Available Pairs
#### `get_pairs`
Retrieves all available trading pairs and their details.
```rust
pub async fn get_pairs(&self) -> Result<Vec<TradingPair>>
```
**Returns:**
- `Result<Vec<TradingPair>>` - List of available trading pairs
**TradingPair Structure:**
```rust
pub struct TradingPair {
pub symbol: String, // Trading pair symbol
pub base_asset: String, // Base asset (e.g., "BTC")
pub quote_asset: String, // Quote asset (e.g., "USD")
pub is_active: bool, // Whether trading is active
pub min_order_size: Decimal, // Minimum order size
pub max_order_size: Decimal, // Maximum order size
pub tick_size: Decimal, // Minimum price increment
pub step_size: Decimal, // Minimum quantity increment
pub max_leverage: Decimal, // Maximum allowed leverage
pub maker_fee: Decimal, // Maker fee rate
pub taker_fee: Decimal, // Taker fee rate
pub funding_interval: u64, // Funding interval in seconds
pub contract_size: Decimal, // Contract size multiplier
pub settlement_asset: String, // Settlement asset
}
```
**Example:**
```rust
let pairs = client.get_pairs().await?;
println!("Available Trading Pairs:");
for pair in pairs {
if pair.is_active {
println!(" {} - Max Leverage: {}x, Min Size: {}",
pair.symbol,
pair.max_leverage,
pair.min_order_size);
}
}
// Filter for specific assets
let btc_pairs: Vec<_> = pairs.iter()
.filter(|p| p.base_asset == "BTC")
.collect();
```
### Getting Pair Details
#### `get_pair_info`
Retrieves detailed information for a specific trading pair.
```rust
pub async fn get_pair_info(&self, symbol: &str) -> Result<TradingPair>
```
**Example:**
```rust
let pair_info = client.get_pair_info("BTC/USD").await?;
println!("BTC/USD Trading Information:");
println!(" Min Order Size: {}", pair_info.min_order_size);
println!(" Max Order Size: {}", pair_info.max_order_size);
println!(" Max Leverage: {}x", pair_info.max_leverage);
println!(" Maker Fee: {}%", pair_info.maker_fee * 100);
println!(" Taker Fee: {}%", pair_info.taker_fee * 100);
```
## Market Status
### Trading Hours
#### `get_trading_hours`
Checks trading hours and market status for a specific pair.
```rust
pub async fn get_trading_hours(&self, symbol: &str) -> Result<TradingHours>
```
**TradingHours Structure:**
```rust
pub struct TradingHours {
pub symbol: String, // Trading pair symbol
pub is_open: bool, // Whether market is currently open
pub next_open: Option<u64>, // Next opening timestamp
pub next_close: Option<u64>, // Next closing timestamp
pub timezone: String, // Market timezone
pub trading_sessions: Vec<TradingSession>, // Trading sessions
}
pub struct TradingSession {
pub day_of_week: u8, // 0 = Sunday, 6 = Saturday
pub open_time: String, // Opening time (HH:MM format)
pub close_time: String, // Closing time (HH:MM format)
}
```
**Example:**
```rust
let hours = client.get_trading_hours("BTC/USD").await?;
if hours.is_open {
println!("✅ {} market is OPEN", hours.symbol);
} else {
println!("❌ {} market is CLOSED", hours.symbol);
if let Some(next_open) = hours.next_open {
let next_open_time = chrono::DateTime::from_timestamp(next_open as i64, 0);
println!(" Reopens at: {:?}", next_open_time);
}
}
// Check multiple pairs
let crypto_pairs = ["BTC/USD", "ETH/USD", "SOL/USD"];
for symbol in crypto_pairs {
let hours = client.get_trading_hours(symbol).await?;
println!("{}: {}", symbol, if hours.is_open { "OPEN" } else { "CLOSED" });
}
```
## Market Statistics
### Getting Market Summary
#### `get_market_summary`
Retrieves overall market statistics and summary.
```rust
pub async fn get_market_summary(&self) -> Result<MarketSummary>
```
**MarketSummary Structure:**
```rust
pub struct MarketSummary {
pub total_volume_24h: Decimal, // Total 24h volume across all pairs
pub total_open_interest: Decimal, // Total open interest
pub active_pairs: u32, // Number of active trading pairs
pub total_traders: u32, // Total number of active traders
pub top_gainers: Vec<PriceChange>, // Top gaining pairs
pub top_losers: Vec<PriceChange>, // Top losing pairs
pub funding_rates: Vec<FundingRate>, // Current funding rates
}
pub struct PriceChange {
pub symbol: String,
pub price: Decimal,
pub change_24h_percent: Decimal,
}
pub struct FundingRate {
pub symbol: String,
pub rate: Decimal,
pub next_funding: u64,
}
```
**Example:**
```rust
let summary = client.get_market_summary().await?;
println!("Market Summary:");
println!(" 24h Volume: ${}", summary.total_volume_24h);
println!(" Open Interest: ${}", summary.total_open_interest);
println!(" Active Pairs: {}", summary.active_pairs);
println!("\nTop Gainers:");
for gainer in summary.top_gainers.iter().take(5) {
println!(" {}: +{}%", gainer.symbol, gainer.change_24h_percent);
}
println!("\nTop Losers:");
for loser in summary.top_losers.iter().take(5) {
println!(" {}: {}%", loser.symbol, loser.change_24h_percent);
}
```
## Historical Data (Planned)
### Candlestick Data
#### `get_klines`
Retrieves historical candlestick data.
```rust
pub async fn get_klines(
&self,
symbol: &str,
interval: KlineInterval,
start_time: Option<u64>,
end_time: Option<u64>,
limit: Option<u32>
) -> Result<Vec<Kline>>
```
**KlineInterval Enum:**
```rust
pub enum KlineInterval {
OneMinute,
FiveMinutes,
FifteenMinutes,
ThirtyMinutes,
OneHour,
FourHours,
OneDay,
OneWeek,
}
```
**Kline Structure:**
```rust
pub struct Kline {
pub open_time: u64,
pub close_time: u64,
pub open: Decimal,
pub high: Decimal,
pub low: Decimal,
pub close: Decimal,
pub volume: Decimal,
pub trades: u32,
}
```
## Real-time Data Streaming (Planned)
### Price Streams
#### `subscribe_to_prices`
Subscribe to real-time price updates.
```rust
pub async fn subscribe_to_prices(
&self,
symbols: &[&str]
) -> Result<impl Stream<Item = Price>>
```
**Example:**
```rust
use futures::StreamExt;
let mut price_stream = client.subscribe_to_prices(&["BTC/USD", "ETH/USD"]).await?;
while let Some(price) = price_stream.next().await {
println!("Price Update: {} = ${}", price.symbol, price.mark_price);
}
```
## Utility Functions
### Price Calculations
```rust
// Calculate percentage change
fn calculate_percentage_change(old_price: Decimal, new_price: Decimal) -> Decimal {
((new_price - old_price) / old_price) * dec!(100)
}
// Calculate volatility
fn calculate_volatility(prices: &[Decimal]) -> Decimal {
if prices.len() < 2 {
return dec!(0);
}
let mean = prices.iter().sum::<Decimal>() / Decimal::from(prices.len());
let variance = prices.iter()
.map(|price| (price - mean).powi(2))
.sum::<Decimal>() / Decimal::from(prices.len() - 1);
variance.sqrt().unwrap_or(dec!(0))
}
// Check if price is within range
fn is_price_in_range(price: Decimal, target: Decimal, tolerance_percent: Decimal) -> bool {
let tolerance = target * tolerance_percent / dec!(100);
price >= (target - tolerance) && price <= (target + tolerance)
}
```
### Market Analysis Helpers
```rust
// Detect market trend
fn detect_trend(prices: &[Decimal]) -> Trend {
if prices.len() < 3 {
return Trend::Sideways;
}
let first_third = &prices[0..prices.len()/3];
let last_third = &prices[2*prices.len()/3..];
let first_avg = first_third.iter().sum::<Decimal>() / Decimal::from(first_third.len());
let last_avg = last_third.iter().sum::<Decimal>() / Decimal::from(last_third.len());
let change_percent = ((last_avg - first_avg) / first_avg) * dec!(100);
if change_percent > dec!(2) {
Trend::Upward
} else if change_percent < dec!(-2) {
Trend::Downward
} else {
Trend::Sideways
}
}
pub enum Trend {
Upward,
Downward,
Sideways,
}
```
## Error Handling
### Common Market Data Errors
```rust
match client.get_price("INVALID/PAIR").await {
Ok(price) => println!("Price: ${}", price.mark_price),
Err(OstiumError::GraphQL(msg)) if msg.contains("not found") => {
eprintln!("Trading pair not found");
// Check available pairs with get_pairs()
}
Err(OstiumError::Network(msg)) => {
eprintln!("Network error: {}", msg);
// Retry with exponential backoff
}
Err(e) => eprintln!("Unexpected error: {}", e),
}
```
## Best Practices
### 1. Cache Market Data Appropriately
```rust
use std::collections::HashMap;
use std::time::{Duration, Instant};
struct PriceCache {
cache: HashMap<String, (Price, Instant)>,
ttl: Duration,
}
impl PriceCache {
fn new(ttl_seconds: u64) -> Self {
Self {
cache: HashMap::new(),
ttl: Duration::from_secs(ttl_seconds),
}
}
async fn get_price(&mut self, client: &OstiumClient, symbol: &str) -> Result<Price> {
if let Some((price, timestamp)) = self.cache.get(symbol) {
if timestamp.elapsed() < self.ttl {
return Ok(price.clone());
}
}
let price = client.get_price(symbol).await?;
self.cache.insert(symbol.to_string(), (price.clone(), Instant::now()));
Ok(price)
}
}
```
### 2. Handle Rate Limits
```rust
use tokio::time::{sleep, Duration};
async fn get_prices_with_rate_limit(
client: &OstiumClient,
symbols: &[&str]
) -> Result<Vec<Price>> {
let mut prices = Vec::new();
for symbol in symbols {
match client.get_price(symbol).await {
Ok(price) => prices.push(price),
Err(OstiumError::Network(msg)) if msg.contains("rate limit") => {
println!("Rate limited, waiting...");
sleep(Duration::from_secs(1)).await;
// Retry
let price = client.get_price(symbol).await?;
prices.push(price);
}
Err(e) => return Err(e),
}
// Small delay between requests
sleep(Duration::from_millis(100)).await;
}
Ok(prices)
}
```
### 3. Validate Market Data
```rust
fn validate_price_data(price: &Price) -> Result<()> {
// Check for reasonable price values
if price.mark_price <= dec!(0) {
return Err(OstiumError::validation("Invalid mark price"));
}
// Check bid/ask spread
let spread_percent = ((price.ask - price.bid) / price.mark_price) * dec!(100);
if spread_percent > dec!(5) {
println!("Warning: Large bid/ask spread: {}%", spread_percent);
}
// Check for stale data (older than 1 minute)
let now = chrono::Utc::now().timestamp() as u64;
if now - price.timestamp > 60 {
println!("Warning: Price data is {} seconds old", now - price.timestamp);
}
Ok(())
}
```
## See Also
- [Client API Reference](client.md) - Main client interface
- [Types Reference](types.md) - Data structures and enums
- [Trading API Reference](trading.md) - Trading operations
- [Market Data Guide](../guides/market-data.md) - Advanced market data usage