Quick Start¶
Get up and running with qldata in minutes. This guide covers the essential operations you'll use most frequently.
Import Convention¶
By convention, we import qldata as qd:
This keeps your code concise while making it clear you're using qldata functions.
Fetching Historical Data¶
The qd.data() function is your gateway to historical market data. It uses a fluent (chainable) API that reads naturally:
Basic Example¶
import qldata as qd
# Fetch last 30 days of hourly BTCUSDT data from Binance
df = qd.data("BTCUSDT", source="binance", category="spot") \
.last(30) \
.resolution("1h") \
.get()
print(df.head())
Output:
open high low close volume
timestamp
2024-11-05 00:00:00+00:00 69500.00 69750.00 69400.00 69600.00 1250.5432
2024-11-05 01:00:00+00:00 69600.00 69800.00 69550.00 69750.00 1180.2341
2024-11-05 02:00:00+00:00 69750.00 69900.00 69700.00 69850.00 1320.8765
...
Understanding the API¶
Let's break down the query:
df = qd.data("BTCUSDT", source="binance", category="spot") # (1)!
.last(30) # (2)!
.resolution("1h") # (3)!
.get() # (4)!
- Create a query for BTCUSDT on Binance spot market
- Set time range to the last 30 days
- Set resolution to 1-hour bars
- Execute the query and return a DataFrame
Different Time Ranges¶
# Last N days (default unit)
df = qd.data("BTCUSDT", source="binance").last(7).resolution("1h").get()
# Explicit time unit
df = qd.data("BTCUSDT", source="binance").last(24, "hours").resolution("1m").get()
# Specific date range
from datetime import datetime
df = qd.data("BTCUSDT", source="binance") \
.range(datetime(2024, 1, 1), datetime(2024, 1, 31)) \
.resolution("1d") \
.get()
Different Resolutions¶
| Resolution | Description |
|---|---|
"1m" | 1-minute bars |
"5m" | 5-minute bars |
"15m" | 15-minute bars |
"1h" | 1-hour bars |
"4h" | 4-hour bars |
"1d" | Daily bars |
"1w" | Weekly bars |
Market Categories¶
| Category | Description |
|---|---|
"spot" | Spot market |
"usdm" | USD-Margined perpetual futures |
| Category | Description |
|---|---|
"spot" | Spot market |
"linear" | Linear perpetual contracts |
Cleaning Data¶
Raw market data often needs cleaning. qldata provides a built-in cleaning pipeline:
# Basic cleaning (removes duplicates, sorts by time)
df = qd.data("BTCUSDT", source="binance") \
.last(30) \
.resolution("1h") \
.clean() \
.get()
# Aggressive cleaning for production
df = qd.data("BTCUSDT", source="binance") \
.last(30) \
.resolution("1h") \
.clean(
remove_invalid_prices=True, # Remove zero/negative prices
validate_ohlc=True, # Ensure high >= low, etc.
remove_outliers=True # Remove statistical outliers
) \
.get()
Fill Missing Data¶
# Forward fill (use last known value)
df = qd.data("BTCUSDT", source="binance") \
.last(30) \
.resolution("1h") \
.clean() \
.fill_forward() \
.get()
# Interpolate (linear interpolation)
df = qd.data("BTCUSDT", source="binance") \
.last(30) \
.resolution("1h") \
.clean() \
.interpolate() \
.get()
Resample Data¶
# Fetch 1-minute data and resample to 1-hour
df = qd.data("BTCUSDT", source="binance") \
.last(1, "days") \
.resolution("1m") \
.clean() \
.resample("1h") \
.get()
Multi-Symbol Queries¶
Fetch data for multiple symbols at once:
# Sequential (default)
data = qd.data(["BTCUSDT", "ETHUSDT", "SOLUSDT"], source="binance") \
.last(7) \
.resolution("1d") \
.get()
# Parallel for faster downloads
data = qd.data(["BTCUSDT", "ETHUSDT", "SOLUSDT"], source="binance") \
.last(7) \
.resolution("1d") \
.get(parallel=True, workers=4)
# Returns a dictionary of DataFrames
for symbol, df in data.items():
print(f"{symbol}: {len(df)} bars")
Live Streaming¶
Stream real-time market data with auto-reconnect and resilience features:
import qldata as qd
import time
def handle_data(df):
"""Called when new data arrives."""
if not df.empty:
latest = df.iloc[-1]
print(f"[{latest['symbol']}] Price: {latest['price']}")
def handle_error(error):
"""Called on errors."""
print(f"Error: {error}")
def handle_close():
"""Called when stream closes."""
print("Stream closed")
# Create and start the stream
stream = qd.stream(["BTCUSDT", "ETHUSDT"], source="binance", category="spot") \
.resolution("tick") \
.on_data(handle_data) \
.on_error(handle_error) \
.on_close(handle_close) \
.get(start=True)
# Stream runs in the background
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
stream.stop()
Stream Resolutions¶
| Resolution | Description |
|---|---|
"tick" | Individual trades (raw) |
"1m" | Aggregated 1-minute bars |
Symbol Information¶
Get metadata about trading pairs:
import qldata as qd
# Get symbol information
info = qd.get_symbol_info("BTCUSDT", source="binance", category="spot")
print(f"Symbol: {info.symbol}")
print(f"Base/Quote: {info.base_asset}/{info.quote_asset}")
print(f"Status: {info.status}")
print(f"Tick Size: {info.filters.tick_size}")
print(f"Min Quantity: {info.filters.min_quantity}")
# Validate prices and quantities
from decimal import Decimal
is_valid = info.validate_price(Decimal("50000.50"))
is_valid = info.validate_quantity(Decimal("0.001"))
List Available Symbols¶
# All active USDT pairs on Binance spot
pairs = qd.list_symbols(
source="binance",
category="spot",
quote_asset="USDT",
active_only=True
)
print(f"Found {len(pairs)} USDT pairs")
# All BTC pairs
btc_pairs = qd.list_symbols(
source="binance",
category="spot",
base_asset="BTC"
)
Exchange Information¶
# Get exchange-level information
exchange = qd.get_exchange_info(source="binance")
print(f"Exchange: {exchange.exchange}")
print(f"Timezone: {exchange.timezone}")
print(f"Total Symbols: {exchange.symbol_count}")
Funding Rates¶
For perpetual futures, get funding rate information:
# Current funding rate
rate = qd.current_funding_rate("BTCUSDT", source="binance", category="usdm")
print(f"Current Rate: {rate}")
What's Next?¶
Now that you know the basics, explore:
- Core Concepts - Understand the architecture
- Historical Data API - Full API reference
- Streaming API - Advanced streaming features
- Cookbook - Real-world examples