Quant
High-performance standardized financial data API for Elixir with Explorer DataFrames
Fetch financial data from multiple providers with universal parameters and identical output schemas for seamless analysis and maximum performance.
โจ Key Features
๐ฏ Universal API Design
- Standardized Interface: Same parameters work across ALL providers
- Identical Schemas: Every DataFrame has exactly 12 columns regardless of provider
- Cross-Asset Ready: Stocks, crypto, forex all use unified structure
- Provider Agnostic: Switch providers without changing your analysis code
๐ Mathematical Indicators (Python-Validated)
| Indicator | Name | Accuracy vs Python | Key Features |
|---|---|---|---|
| RSI | Relative Strength Index | 100% (0.0% diff) | Wilder's smoothing method |
| DEMA | Double Exponential MA | 99.96% (0.04% diff) | Enhanced responsiveness |
| HMA | Hull Moving Average | 100% (0.0% diff) | Reduced lag, 4-step algorithm |
| KAMA | Kaufman Adaptive MA | 100% (0.0% diff) | Market condition adaptation |
| TEMA | Triple Exponential MA | 99.9988% (0.0016 diff) | Maximum responsiveness |
| WMA | Weighted Moving Average | 100% (0.0% diff) | Linear weight distribution |
๐ฏ Trading Strategies & Backtesting
- Strategy Framework: Modular strategy composition with indicators
- Backtesting Engine: Portfolio performance analysis with metrics
- Signal Generation: Buy/sell signals from multiple indicators
- Composite Strategies: Combine multiple strategies for advanced analysis
- Volatility Strategies: Bollinger Bands and mean reversion systems
๐ง Parameter Optimization (vectorbt-like)
Systematic parameter tuning with vectorbt-equivalent functionality:
# Get historical data
{:ok, df} = Quant.Explorer.history("AAPL", provider: :yahoo_finance, period: "1y")
# Define parameter ranges (like vectorbt.simulate_all_params())
param_ranges = %{
fast_period: 5..20, # SMA fast period range
slow_period: 20..50 # SMA slow period range
}
# Run optimization across all combinations - equivalent to vectorbt
{:ok, results} = Quant.Strategy.Optimization.run_combinations(df, :sma_crossover, param_ranges)
# Find best parameters (equivalent to results.idxmax())
best_params = Quant.Strategy.Optimization.find_best_params(results, :total_return)
# => %{fast_period: 12, slow_period: 26, total_return: 0.2847}๐ Advanced Features:
| Feature | Description | Performance | Use Case |
|---|---|---|---|
| Parallel Processing | Multi-core parameter testing | 4x faster on 4-core | Large parameter spaces |
| Streaming Results | Memory-efficient processing | Constant memory usage | 1000+ combinations |
| Walk-Forward Analysis | Out-of-sample validation | Prevents overfitting | Robust parameter selection |
| CSV/JSON Export | Results export & analysis | Full precision | Research & reporting |
| Performance Benchmarking | Optimization profiling | Scaling analysis | System optimization |
๐ฏ Production-Ready Optimization:
# Parallel processing for speed (uses all CPU cores)
{:ok, results} = Quant.Strategy.Optimization.run_combinations_parallel(
df, :sma_crossover, param_ranges,
concurrency: System.schedulers_online()
)
# Walk-forward optimization for robustness
{:ok, wf_results} = Quant.Strategy.Optimization.walk_forward_optimization(
df, :sma_crossover, param_ranges,
window_size: 252, # 1 year training
step_size: 63 # Quarterly reoptimization
)
# Memory-efficient streaming for large parameter spaces
results_stream = Quant.Strategy.Optimization.run_combinations_stream(
df, :sma_crossover, %{period: 5..100}, chunk_size: 20
)
# Export results for analysis
:ok = Quant.Strategy.Optimization.Export.to_csv(results, "optimization_results.csv")
:ok = Quant.Strategy.Optimization.Export.to_json(results, "results.json", precision: 6)๐ Comprehensive Analysis Tools:
- Parameter Correlation: Find relationships between parameters and performance
- Performance Metrics: Total return, Sharpe ratio, max drawdown, win rate
- Ranking & Filtering: Sort by any metric, filter by constraints
- Statistical Summary: Mean, std dev, percentiles of parameter performance
- Cross-Validation: Walk-forward, expanding window validation methods
๐งช Python Cross-Validation Framework
| Validation Type | Description | Coverage | Results |
|---|---|---|---|
| Mathematical Accuracy | Final value comparison vs pandas/numpy | All 6 indicators | 99.96%+ accuracy |
| Algorithm Verification | Step-by-step calculation comparison | Core algorithms | Perfect methodology match |
| Behavioral Testing | Responsiveness and trend adaptation | Market scenarios | Expected behavior confirmed |
| Methodology Confirmation | Correct implementation verification | Industry standards | Wilder's RSI, Hull algorithm |
| Test Suite | Comprehensive cross-language validation | Python validation | 100% pass rate |
๐ Multi-Provider Support
| Provider | Data Types | API Key | Cost | Key Features |
|---|---|---|---|---|
| Yahoo Finance | Stocks, Crypto, Options | โ No | ๐ Free | Historical data, real-time quotes, company info |
| Alpha Vantage | Stocks, Forex | โ Required | ๐ฐ Freemium | Premium intraday data, fundamentals |
| Binance | Cryptocurrency | โ No | ๐ Free | Real-time crypto data, all trading pairs |
| CoinGecko | Cryptocurrency | โ No | ๐ Free | Market data, historical prices, market cap |
| Twelve Data | Stocks, Forex, Crypto | โ Required | ๐ฐ Premium | High-frequency data, global markets |
โก Performance & Reliability
- Explorer/Polars Backend: Optimized for high-throughput analysis
- NX Mathematical Computing: High-performance numerical operations
- Zero External HTTP Deps: Uses built-in Erlang
:httpc - Advanced Rate Limiting: ETS/Redis backends with provider-specific patterns
- Streaming Support: Handle large datasets efficiently
- Comprehensive Test Coverage: Full validation suite with cross-language verification
๐ก๏ธ Production Ready
- Type Safety: Full Dialyzer specifications
- Error Handling: Comprehensive error types and graceful degradation
- Flexible Configuration: Environment variables, runtime config, inline API keys
- Livebook Ready: Perfect for data science and research workflows
๐ฏ Standardized API - Built for Performance
Quant.Explorer provides a completely standardized interface across all financial data providers with identical 12-column output schemas:
# Universal parameters work with ALL providers - identical output schemas!
{:ok, yahoo_df} = Quant.Explorer.history("AAPL",
provider: :yahoo_finance, interval: "1d", period: "1y")
{:ok, binance_df} = Quant.Explorer.history("BTCUSDT",
provider: :binance, interval: "1d", period: "1y")
# Both DataFrames have IDENTICAL 12-column schemas!
#Explorer.DataFrame<
# Polars[365 x 12] # โ
Always exactly 12 columns
# ["symbol", "timestamp", "open", "high", "low", "close", "volume",
# "adj_close", "market_cap", "provider", "currency", "timezone"]
# Seamless high-performance cross-asset analysis
DataFrame.concat_rows(yahoo_df, binance_df)
|> DataFrame.group_by("provider")
|> DataFrame.summarise(avg_price: mean(close), total_volume: sum(volume))โ
ACHIEVED: Complete Schema Standardization Across All Providers
โ
TESTED: Works with Yahoo Finance, Binance, Alpha Vantage, CoinGecko, Twelve Data
โ
VALIDATED: Cross-asset analysis (stocks + crypto) in unified DataFrames
๐ Complete Standardization Guide โ
๐ STANDARDIZATION SUCCESS STORY
Problem Solved: Financial data providers return inconsistent schemas, making cross-provider analysis painful.
Before Quant.Explorer:
# Binance: 16 inconsistent columns
[\"symbol\", \"open_time\", \"close_time\", \"quote_volume\", \"taker_buy_volume\", ...]
# Yahoo Finance: 7 different columns
[\"Date\", \"Open\", \"High\", \"Low\", \"Close\", \"Adj Close\", \"Volume\"]
# Result: Impossible to combine data sources! ๐After Quant.Explorer:
# ALL providers: Identical 12-column schema
[\"symbol\", \"timestamp\", \"open\", \"high\", \"low\", \"close\", \"volume\",
\"adj_close\", \"market_cap\", \"provider\", \"currency\", \"timezone\"]
# Result: Seamless cross-asset analysis! ๐
combined_df = DataFrame.concat_rows([binance_btc, yahoo_aapl, alpha_msft])๐ Standardization Stats:
- โ 5 Providers Standardized: Yahoo Finance, Binance, Alpha Vantage, CoinGecko, Twelve Data
- โ 100% Schema Consistency: Every DataFrame has identical structure
- โ 50+ Parameter Translations: Universal parameters work with all providers
- โ Cross-Asset Ready: Stocks, crypto, forex all compatible
- โ Production Tested: Real APIs, live data, 1000+ data points validated
Installation & Setup
Elixir Library
# Add to mix.exs
def deps do
[
{:quant, github: "the-nerd-company/quant"}
]
endPython Dependencies (For Cross-Language Validation)
The library includes comprehensive Python validation tests that compare results against pandas/numpy standards for mathematical accuracy.
Quick Setup with UV (Recommended)
# Run the automated setup script
./scripts/setup_python.sh
# Or use Makefile
make python-setupManual UV Installation
# Install UV (much faster than pip)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
uv pip install --system -e .
# or
uv pip install --system -r requirements.txtTraditional pip (Legacy)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtRunning Tests
# All tests
mix test
# Python validation tests only (requires Python setup)
mix test --include python_validation
make python-test
# Coverage report
mix coveralls.lcovQuick Start
โ ๏ธ Important: Provider Must Be Explicit
All functions require an explicit provider: parameter. There are no default providers to avoid confusion about which API is being called.
# โ
Correct - explicit provider
{:ok, df} = Quant.Explorer.history("AAPL", provider: :yahoo_finance, period: "1y")
# โ Error - will return {:error, :provider_required}
{:ok, df} = Quant.Explorer.history("AAPL", period: "1y")# Add to mix.exs
def deps do
[
{:quant, github: "the-nerd-company/quant"}
]
endStandardized API - Universal Parameters
# Universal parameters work with ALL providers - perfect for analysis!
# Stock data - Yahoo Finance (free, no API key)
{:ok, df} = Quant.Explorer.history("AAPL",
provider: :yahoo_finance, interval: "1d", period: "1y")
# Stock data - Alpha Vantage (premium, requires API key)
{:ok, df} = Quant.Explorer.history("AAPL",
provider: :alpha_vantage, interval: "1d", period: "1y", api_key: "your_key")
# Crypto data - Binance (free, no API key)
{:ok, df} = Quant.Explorer.history("BTCUSDT",
provider: :binance, interval: "1d", period: "1y")
# Crypto data - CoinGecko (free, no API key)
{:ok, df} = Quant.Explorer.history("bitcoin",
provider: :coin_gecko, interval: "1d", period: "1y", currency: "usd")
# Stock data - Twelve Data (premium, requires API key)
{:ok, df} = Quant.Explorer.history("AAPL",
provider: :twelve_data, interval: "1d", period: "1y", api_key: "your_key")
# ALL DataFrames have IDENTICAL schemas - combine for analysis!
all_data = [yahoo_df, alpha_df, binance_df, coingecko_df, twelve_df]
|> Enum.reduce(&DataFrame.concat_rows/2)
|> DataFrame.group_by("provider")
|> DataFrame.summarise(avg_price: mean(close), data_points: count())Universal Parameters - Work with ANY Provider
# Standard intervals (auto-translated per provider)
intervals = ["1m", "5m", "15m", "30m", "1h", "1d", "1w", "1mo"]
# Standard periods (auto-translated per provider)
periods = ["1d", "5d", "1mo", "3mo", "6mo", "1y", "2y", "5y", "10y", "max"]
# Standard currencies (crypto providers)
currencies = ["usd", "eur", "btc", "eth"]
# Real-time quotes with universal parameters
{:ok, df} = Quant.Explorer.quote(["AAPL", "MSFT"], provider: :yahoo_finance)
{:ok, df} = Quant.Explorer.quote(["BTCUSDT", "ETHUSDT"], provider: :binance)
{:ok, df} = Quant.Explorer.quote("AAPL", provider: :alpha_vantage, api_key: "key")
# Symbol search with universal parameters
{:ok, df} = Quant.Explorer.search("Apple", provider: :yahoo_finance)
{:ok, df} = Quant.Explorer.search("Bitcoin", provider: :coin_gecko)
{:ok, df} = Quant.Explorer.search("Microsoft", provider: :alpha_vantage, api_key: "key")
# Company info
{:ok, info} = Quant.Explorer.info("AAPL", provider: :yahoo_finance)
{:ok, info} = Quant.Explorer.info("bitcoin", provider: :coin_gecko)Backward Compatibility
# fetch/2 is now an alias for history/2 - same standardized output
{:ok, df} = Quant.Explorer.fetch("AAPL", provider: :yahoo_finance, interval: "1d", period: "1y")
# Identical to:
{:ok, df} = Quant.Explorer.history("AAPL", provider: :yahoo_finance, interval: "1d", period: "1y")# Multiple symbols at once
{:ok, df} = Quant.Explorer.fetch(["AAPL", "MSFT", "GOOGL"], provider: :yahoo_finance, period: "1mo")# Real-time quotes
{:ok, df} = Quant.Explorer.quote(["AAPL", "MSFT"], provider: :yahoo_finance)
{:ok, df} = Quant.Explorer.quote(["BTCUSDT", "ETHUSDT"], provider: :binance)
{:ok, df} = Quant.Explorer.quote(["bitcoin", "ethereum"], provider: :coin_gecko)
{:ok, df} = Quant.Explorer.quote("AAPL", provider: :alpha_vantage)
{:ok, df} = Quant.Explorer.quote("AAPL", provider: :twelve_data)# Symbol search
{:ok, df} = Quant.Explorer.search("Apple", provider: :yahoo_finance)
{:ok, df} = Quant.Explorer.search("BTC", provider: :binance)
{:ok, df} = Quant.Explorer.search("bitcoin", provider: :coin_gecko)
{:ok, df} = Quant.Explorer.search("Microsoft", provider: :alpha_vantage)
{:ok, df} = Quant.Explorer.search("Apple", provider: :twelve_data)Parameter Optimization Quick Start
vectorbt-like parameter optimization for systematic strategy tuning:
# 1. Get historical data
{:ok, df} = Quant.Explorer.history("AAPL", provider: :yahoo_finance, period: "1y")
# 2. Define parameter ranges to test
param_ranges = %{
fast_period: 5..15, # Test fast SMA periods 5-15
slow_period: 20..30 # Test slow SMA periods 20-30
}
# 3. Run optimization (tests all combinations)
{:ok, results} = Quant.Strategy.Optimization.run_combinations(df, :sma_crossover, param_ranges)
# 4. Find best parameters
best = Quant.Strategy.Optimization.find_best_params(results, :total_return)
# => %{fast_period: 8, slow_period: 24, total_return: 0.187, sharpe_ratio: 1.43}
# 5. Export results for analysis
:ok = Quant.Strategy.Optimization.Export.to_csv(results, "optimization_results.csv")๐ Advanced optimization features:
# Parallel processing (4x faster)
{:ok, results} = Quant.Strategy.Optimization.run_combinations_parallel(
df, :sma_crossover, param_ranges, concurrency: 4
)
# Walk-forward optimization (prevents overfitting)
{:ok, wf_results} = Quant.Strategy.Optimization.walk_forward_optimization(
df, :sma_crossover, param_ranges, window_size: 252, step_size: 63
)
# Memory-efficient streaming (for large parameter spaces)
results_stream = Quant.Strategy.Optimization.run_combinations_stream(
df, :sma_crossover, %{period: 5..100}, chunk_size: 20
)Features
- ๐ฏ Standardized Interface: Universal parameters and identical schemas across ALL providers
- โก High Performance: Built on Explorer's Polars backend with optimized data transformations
- ๐ Multi-Provider: Yahoo Finance, Alpha Vantage, Binance, CoinGecko, Twelve Data
- ๐ฐ Crypto Support: Native cryptocurrency data with standardized schemas
- ๐ Seamless Analysis: Combine data from multiple providers effortlessly
- ๐ง Parameter Optimization: vectorbt-like functionality for systematic strategy tuning
- ๐ Parallel Processing: Multi-core optimization with walk-forward validation
- ๐ฏ Advanced Rate Limiting: Weighted rate limiting per provider with ETS/Redis backends
- ๐ ๏ธ Zero External Dependencies: Uses built-in Erlang
:httpcfor maximum reliability - ๐ Flexible API Keys: Pass API keys inline or configure globally
- ๐ Analysis Ready: Perfect for Livebook, production systems, and research
Standardization Benefits - PRODUCTION READY โ
๐ฏ Universal Parameters: interval: "1d" works with ALL providers - TESTED & VERIFIED
๐ Identical Schemas: All DataFrames have exactly 12 columns regardless of provider
โก Automatic Translation: Provider-specific formats handled internally (Binance "1h" โ Yahoo "1h" โ Alpha Vantage "60min")
๐ Rich Metadata: Provider, currency, and timezone columns for complete traceability
๐ก๏ธ Type Safety: Strong typing and validation throughout the standardization pipeline
๐ Performance: Optimized transformations for high-throughput analysis (tested with 1000+ data points)
Standardization Achievements:
- โ Schema Filtering: Eliminated provider-specific columns (Binance: 16โ12 columns)
- โ Universal Columns: All providers return identical column names and types
- โ Cross-Asset Ready: Stocks, crypto, forex all use same schema for seamless analysis
-
โ
Null Handling: Consistent
nilvalues for unavailable data (e.g.,market_capin historical data) - โ Metadata Consistency: Provider atoms converted to strings, currency normalization
- โ Production Tested: Working with real APIs and live data
Identical Output Schemas - GUARANTEED ๐ฏ
Every provider returns these exact schemas - no exceptions:
Historical Data (12 columns exactly)
["symbol", "timestamp", "open", "high", "low", "close", "volume",
"adj_close", "market_cap", "provider", "currency", "timezone"]
# Real example from ANY provider:
#Explorer.DataFrame<
# Polars[100 x 12] # Always exactly 12 columns
# symbol string ["BTCUSDT", "AAPL", ...]
# timestamp datetime[ฮผs, Etc/UTC] [2025-09-21 19:00:00.000000Z, ...]
# open f64 [115530.89, 150.25, ...]
# close f64 [115480.05, 151.30, ...]
# market_cap null/f64 [nil, 2.5e12, ...] # nil for crypto historical, populated for stocks
# provider string ["binance", "yahoo_finance", ...]Quote Data (12 columns exactly)
["symbol", "price", "change", "change_percent", "volume", "high_24h",
"low_24h", "market_cap", "timestamp", "provider", "currency", "market_state"]Search Results (11 columns exactly)
["symbol", "name", "type", "exchange", "currency", "country",
"sector", "industry", "market_cap", "provider", "match_score"]How Standardization Works ๐ง
Parameter Translation Engine
# Your input: Universal parameters
Quant.Explorer.history("AAPL", provider: :alpha_vantage, interval: "1h")
# Automatic translation:
# Quant.Explorer โ Alpha Vantage API
# "1h" โ "60min"
# "1d" โ "daily"
# "1w" โ "weekly"Schema Standardization Pipeline
# 1. Raw provider data (varies by provider)
Binance: ["symbol", "open_time", "close_time", "quote_volume", ...] # 16 columns
Yahoo: ["Date", "Open", "High", "Adj Close", ...] # 7 columns
# 2. Standardization engine processes:
# - Normalizes column names: "open_time" โ "timestamp"
# - Filters provider-specific columns: removes "close_time", "quote_volume"
# - Adds missing columns: ensures "market_cap" exists (nil if not available)
# - Adds metadata: "provider", "currency", "timezone"
# 3. Final output (IDENTICAL across all providers):
["symbol", "timestamp", "open", "high", "low", "close", "volume",
"adj_close", "market_cap", "provider", "currency", "timezone"] # Always 12Cross-Asset Consistency
# Stocks: market_cap from company data, adj_close properly calculated
# Crypto: market_cap = nil (honest about availability), adj_close = close
# All: Universal OHLCV structure enables cross-asset analysis๐ Supported Data & Endpoints
| Provider | Historical | Real-time Quotes | Symbol Search | Company Info | Options Data | Crypto Support |
|---|---|---|---|---|---|---|
| Yahoo Finance | โ All periods | โ Multi-symbol | โ Full search | โ Fundamentals | โ Options chains | โ Major pairs |
| Alpha Vantage | โ Premium data | โ Real-time | โ Symbol lookup | โ Company data | โ Not available | โ Stocks only |
| Binance | โ All intervals | โ 24hr stats | โ Pair search | โ Crypto only | โ Not applicable | โ All pairs |
| CoinGecko | โ Historical | โ Live prices | โ Coin search | โ Market data | โ Not applicable | โ Full coverage |
| Twelve Data | โ Global markets | โ Real-time | โ Advanced search | โ Fundamentals | โ Not available | โ Major pairs |
Cryptocurrency Support
Get crypto data from Binance with full support for:
# Bitcoin historical data
{:ok, df} = Quant.Explorer.fetch("BTCUSDT", provider: :binance, interval: "1h", limit: 100)
# Multiple crypto pairs
{:ok, df} = Quant.Explorer.quote(["BTCUSDT", "ETHUSDT", "ADAUSDT", "DOTUSDT"], provider: :binance)
# Search crypto pairs
{:ok, df} = Quant.Explorer.search("ETH", provider: :binance)
# All available trading pairs
{:ok, df} = Quant.Explorer.Providers.Binance.get_all_symbols()
# Custom time ranges for crypto analysis
{:ok, df} = Quant.Explorer.Providers.Binance.history_range("BTCUSDT", "5m", start_time, end_time)Supported Binance intervals: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
Advanced Usage
# Stream large datasets
stream = Quant.Explorer.Providers.YahooFinance.history_stream("AAPL", period: "max")
df = stream |> Enum.to_list() |> List.first()
# Custom date ranges
{:ok, df} = Quant.Explorer.fetch("AAPL",
start_date: ~D[2023-01-01],
end_date: ~D[2023-12-31],
interval: "1d"
)
# Options chain
{:ok, options} = Quant.Explorer.Providers.YahooFinance.options("AAPL")
# Alpha Vantage premium data (requires API key)
{:ok, df} = Quant.Explorer.Providers.AlphaVantage.history("MSFT", interval: "5min", outputsize: "full")
{:ok, df} = Quant.Explorer.Providers.AlphaVantage.quote("MSFT")
{:ok, df} = Quant.Explorer.Providers.AlphaVantage.search("Apple")
# Crypto klines with custom intervals
{:ok, df} = Quant.Explorer.Providers.Binance.history("BTCUSDT", interval: "15m", limit: 500)
# All crypto trading pairs
{:ok, df} = Quant.Explorer.Providers.Binance.get_all_symbols()
# Crypto 24hr statistics
{:ok, df} = Quant.Explorer.Providers.Binance.quote(["BTCUSDT", "ETHUSDT", "ADAUSDT"])Parameter Optimization - Advanced Examples
# Complex multi-parameter optimization
{:ok, df} = Quant.Explorer.history("AAPL", provider: :yahoo_finance, period: "2y")
# Test RSI + Bollinger Bands strategy
param_ranges = %{
rsi_period: 10..20,
rsi_overbought: 70..80,
rsi_oversold: 20..30,
bb_period: 15..25,
bb_std_dev: 1.5..2.5
}
# Parallel optimization across all combinations
{:ok, results} = Quant.Strategy.Optimization.run_combinations_parallel(
df, :rsi_bollinger, param_ranges,
concurrency: System.schedulers_online(),
initial_capital: 10_000.0,
commission: 0.001
)
# Analyze parameter correlations
correlations = Quant.Strategy.Optimization.Results.parameter_correlation(
results, :total_return, [:rsi_period, :bb_period]
)
# Walk-forward optimization for robustness
{:ok, wf_results} = Quant.Strategy.Optimization.walk_forward_optimization(
df, :rsi_bollinger, param_ranges,
window_size: 252, # 1 year training window
step_size: 21, # Monthly reoptimization
min_trades: 10 # Require minimum trades
)
# Export comprehensive results
:ok = Quant.Strategy.Optimization.Export.to_csv(results, "full_optimization.csv",
delimiter: ",", precision: 4)
:ok = Quant.Strategy.Optimization.Export.to_json(wf_results, "walkforward_results.json")
# Generate summary report
:ok = Quant.Strategy.Optimization.Export.summary(results, "optimization_summary.txt",
include_correlations: true, top_n: 10)
# Memory-efficient streaming for very large parameter spaces
large_ranges = %{
fast_period: 5..50, # 46 values
slow_period: 51..200, # 150 values
signal_period: 5..20 # 16 values
}
# Total: 46 * 150 * 16 = 110,400 combinations!
# Process in chunks to avoid memory issues
results_stream = Quant.Strategy.Optimization.run_combinations_stream(
df, :triple_sma, large_ranges, chunk_size: 1000
)
# Process results as they come in
best_so_far = results_stream
|> Stream.map(fn {:ok, chunk_df} ->
chunk_df
|> DataFrame.filter(col("total_return") > 0.1) # Filter profitable combinations
|> DataFrame.slice_head(10) # Keep top 10 per chunk
end)
|> Stream.reject(&(DataFrame.n_rows(&1) == 0)) # Skip empty chunks
|> Enum.reduce(fn chunk, acc ->
DataFrame.concat_rows([acc, chunk])
|> DataFrame.sort_by(desc(col("total_return")))
|> DataFrame.slice_head(50) # Keep top 50 overall
end)Configuration
Alpha Vantage API Key
To use Alpha Vantage (premium financial data), set your API key:
export ALPHA_VANTAGE_API_KEY="your_api_key_here"
export TWELVE_DATA_API_KEY="your_api_key_here"Or in your application config:
config :quant,
api_keys: %{
alpha_vantage: "your_api_key_here",
twelve_data: "your_api_key_here"
# coin_gecko: "your_pro_api_key" # Optional for CoinGecko Pro
}โ ๏ธ Alpha Vantage Free Tier Limitations:
- 5 requests per minute, 500 requests per day
- Some symbols may not be available in free tier
- Premium endpoints require paid subscription
- Use popular symbols like "AAPL", "MSFT", "GOOGL" for better results
API Keys in Function Calls
For Livebook, multi-client applications, or dynamic API key management, you can pass API keys directly in function calls instead of configuring them globally:
# Pass API keys directly (great for Livebook!)
{:ok, df} = Quant.Explorer.fetch("AAPL",
provider: :alpha_vantage,
api_key: "your_alpha_vantage_key"
)
{:ok, df} = Quant.Explorer.quote("AAPL",
provider: :twelve_data,
api_key: "your_twelve_data_key"
)
{:ok, df} = Quant.Explorer.search("Apple",
provider: :alpha_vantage,
api_key: "your_api_key"
)
# Works with all provider functions
{:ok, info} = Quant.Explorer.info("AAPL",
provider: :twelve_data,
api_key: "your_api_key"
)Multi-Client Scenarios
This is particularly useful when serving multiple clients with different API keys:
defmodule TradingService do
def get_stock_data(symbol, client_id) do
api_key = get_api_key_for_client(client_id)
Quant.Explorer.fetch(symbol,
provider: :alpha_vantage,
api_key: api_key,
interval: "daily"
)
end
defp get_api_key_for_client(client_id) do
# Fetch from database, environment, etc.
MyApp.Repo.get_client_api_key(client_id)
end
endLivebook Examples
Perfect for data science and research in Livebook:
# Cell 1: Setup
Mix.install([{:quant, github: "the-nerd-company/quant"}])
# Cell 2: Get data with inline API key
api_key = "your_alpha_vantage_api_key"
{:ok, aapl} = Quant.Explorer.fetch("AAPL",
provider: :alpha_vantage,
api_key: api_key,
interval: "daily",
outputsize: "compact"
)
{:ok, msft} = Quant.Explorer.fetch("MSFT",
provider: :twelve_data,
api_key: "your_twelve_data_key",
interval: "1day",
outputsize: 50
)
# Cell 3: Analyze with Explorer
Explorer.DataFrame.describe(aapl)Benefits of inline API keys:
- โ No global configuration needed
- โ Perfect for Livebook notebooks
- โ Support multiple clients/keys
- โ Override config on a per-call basis
- โ Better for testing different keys
Troubleshooting
Common API Issues
Alpha Vantage {:error, :symbol_not_found}:
- Free tier has limited symbol coverage
- Try popular symbols: "AAPL", "MSFT", "GOOGL", "TSLA"
- Verify your API key is valid (not "demo" key)
- Check rate limits (5 requests/minute for free tier)
Alpha Vantage {:error, {:api_key_error, "Demo API key detected..."}}:
- You're using the default "demo" API key
- Get a free API key at https://www.alphavantage.co/support/#api-key
-
Set
ALPHA_VANTAGE_API_KEYenvironment variable - Or configure in your application config
Twelve Data RuntimeError: API key is required:
-
Set
TWELVE_DATA_API_KEYenvironment variable -
Or configure in
config/config.exswith your API key
CoinGecko slow responses:
- Free tier has 10-30 calls/minute limit
- Consider upgrading to Pro tier for higher limits
Rate limiting errors:
- Each provider has different rate limits
- Free tiers are more restrictive than paid plans
- Wait between requests or implement backoff logic
Error Handling Examples
# Handle API errors gracefully
case Quant.Explorer.quote("AAPL", provider: :alpha_vantage) do
{:ok, df} ->
IO.puts("Got data!")
df
{:error, :provider_required} ->
IO.puts("Provider must be specified explicitly - no defaults!")
{:error, :symbol_not_found} ->
IO.puts("Symbol not found - try a different symbol")
{:error, {:api_key_error, msg}} ->
IO.puts("API key issue: #{msg}")
# Common message: "Demo API key detected. Please get a free API key at https://www.alphavantage.co/support/#api-key"
{:error, :rate_limited} ->
IO.puts("Rate limited - wait and try again")
{:error, reason} ->
IO.puts("Other error: #{inspect(reason)}")
end
# Fallback to different providers
def get_quote(symbol) do
case Quant.Explorer.quote(symbol, provider: :yahoo_finance) do
{:ok, df} -> {:ok, df}
{:error, _} ->
# Try Alpha Vantage as fallback
Quant.Explorer.quote(symbol, provider: :alpha_vantage)
end
endTesting
Quant.Explorer includes both fast mocked tests and integration tests:
# Run default tests (mocked, fast, no API calls)
mix test # ~0.3s, all mocked tests
# Run integration tests (real API calls, slower)
mix test --include integration # Real HTTP requests to APIs
# Run specific test type
mix test --only mocked # Only mocked tests
mix test --only integration # Only real API testsDefault behavior:
- โ Mocked tests run by default - Fast, reliable, no external dependencies
- โ Integration tests excluded by default - Require API keys and internet
See TESTING.md for detailed testing documentation.
License
This project is licensed under CC BY-NC 4.0, which means:
โ You can:
- Use for personal projects, research, and education
- Share, copy, and redistribute the code
- Modify and build upon the code
- Use in academic and non-profit contexts
โ You cannot:
- Use for commercial purposes without permission
- Sell products or services based on this code
- Use in commercial trading systems or financial products
This ensures the library remains free for the community while protecting against unauthorized commercial exploitation.