fmp-rs 0.1.1

Production-grade Rust client for Financial Modeling Prep API with intelligent caching, rate limiting, and comprehensive endpoint coverage
Documentation

📈 FMP-RS: Production-Grade Rust Client for Financial Modeling Prep

Crates.io Documentation License: MIT OR Apache-2.0 Build Status

A comprehensive, production-ready Rust wrapper for the Financial Modeling Prep (FMP) API. Designed for high-performance financial applications with enterprise-grade reliability features.

🚀 Features

📊 Comprehensive API Coverage

  • 186 API endpoints across all FMP categories
  • Complete data models with full type safety
  • Real-time and historical financial data
  • Stocks, ETFs, Forex, Crypto, and Commodities

🏗️ Production-Grade Architecture

  • ⚡ Intelligent Caching - Smart TTL strategies per endpoint
  • 🛡️ Advanced Retry Logic - Exponential backoff with jitter
  • 📊 Rate Limiting - Token bucket algorithm (300 req/sec default)
  • 🔗 Connection Pooling - Optimized HTTP/2 connections
  • 📈 Performance Monitoring - Built-in metrics and health checks
  • 🧠 Memory Optimization - Chunked bulk data processing

� Developer Experience

  • Zero Configuration - Sensible defaults, full customization
  • Async/Await Native - Built on Tokio for maximum performance
  • Type Safety - Full Rust type system leverage
  • Comprehensive Examples - Real-world usage patterns
  • Rich Error Handling - Detailed error context and recovery

Installation

Add this to your Cargo.toml:

[dependencies]

fmp-rs = "0.1"

tokio = { version = "1.0", features = ["full"] }

Quick Start

Set your FMP API key as an environment variable:

export FMP_API_KEY="your_api_key_here"

Or in PowerShell:

$env:FMP_API_KEY = "your_api_key_here"

Then use the client:

use fmp_rs::FmpClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create client (reads FMP_API_KEY from environment)
    let client = FmpClient::new()?;
    
    // Get a stock quote
    let quotes = client.quote().get_quote("AAPL").await?;
    println!("Apple stock price: ${}", quotes[0].price);
    
    // Get company profile
    let profiles = client.company_info().get_profile("AAPL").await?;
    println!("Company: {}", profiles[0].company_name);
    
    // Get financial statements
    let income_statements = client
        .financials()
        .get_income_statement("AAPL", Period::Annual, Some(5))
        .await?;
    
    for statement in income_statements {
        println!("Year {}: Revenue = ${}", statement.calendar_year, statement.revenue);
    }
    
    Ok(())
}

Usage Examples

Company Search

// Search by name
let results = client.company_search()
    .search("Apple", Some(10), None)
    .await?;

// Search by ticker
let results = client.company_search()
    .search_symbol("AAPL", None, None)
    .await?;

// Search by CIK
let results = client.company_search()
    .search_cik("0000320193", None)
    .await?;

Stock Quotes

// Single quote
let quote = client.quote().get_quote("AAPL").await?;

// Batch quotes
let quotes = client.quote()
    .get_quote_batch(&["AAPL", "MSFT", "GOOGL"])
    .await?;

// Exchange quotes
let nyse_quotes = client.quote()
    .get_exchange_quotes("NYSE")
    .await?;

// Price change data
let changes = client.quote()
    .get_price_change("AAPL")
    .await?;

Financial Statements

use fmp_rs::models::common::Period;

// Income statement
let income = client.financials()
    .get_income_statement("AAPL", Period::Annual, Some(5))
    .await?;

// Balance sheet
let balance = client.financials()
    .get_balance_sheet("AAPL", Period::Quarter, Some(8))
    .await?;

// Cash flow statement
let cash_flow = client.financials()
    .get_cash_flow_statement("AAPL", Period::Annual, None)
    .await?;

// Key metrics
let metrics = client.financials()
    .get_key_metrics("AAPL", Period::Annual, Some(5))
    .await?;

// Financial ratios
let ratios = client.financials()
    .get_ratios("AAPL", Period::Annual, Some(5))
    .await?;

Historical Prices

use fmp_rs::models::common::Timeframe;

// Daily historical prices
let daily = client.charts()
    .get_historical_prices("AAPL", Some("2023-01-01"), Some("2023-12-31"))
    .await?;

// Intraday prices
let intraday_1min = client.charts()
    .get_1min_prices("AAPL", None, None)
    .await?;

let intraday_5min = client.charts()
    .get_5min_prices("AAPL", None, None)
    .await?;

// Custom timeframe
let custom = client.charts()
    .get_intraday_prices("AAPL", Timeframe::OneHour, None, None)
    .await?;

Company Information

// Full company profile
let profile = client.company_info()
    .get_profile("AAPL")
    .await?;

// Key executives
let executives = client.company_info()
    .get_executives("AAPL")
    .await?;

// Market cap
let market_cap = client.company_info()
    .get_market_cap("AAPL")
    .await?;

// Share float
let float = client.company_info()
    .get_share_float("AAPL")
    .await?;

// Stock peers
let peers = client.company_info()
    .get_peers("AAPL")
    .await?;

Custom Configuration

use std::time::Duration;

let client = FmpClient::builder()
    .api_key("your_api_key")
    .base_url("https://custom.api.endpoint")  // For testing
    .timeout(Duration::from_secs(60))
    .build()?;

Testing

The library is designed to be testable without making actual API requests.

Running Tests

# Run unit tests (no API key required)

cargo test


# Run integration tests (requires FMP_API_KEY)

cargo test -- --ignored


# Run specific test module

cargo test company_search

Writing Tests with Mocks

The library is structured to allow easy mocking. You can override the base URL to point to a mock server:

#[cfg(test)]
mod tests {
    use fmp_rs::FmpClient;

    #[tokio::test]
    async fn test_with_mock_server() {
        // Set up your mock server (e.g., with wiremock or mockito)
        let mock_server = setup_mock_server();
        
        let client = FmpClient::builder()
            .api_key("test_key")
            .base_url(&mock_server.url())
            .build()
            .unwrap();
        
        // Test your code without hitting the real API
        let result = client.quote().get_quote("AAPL").await;
        assert!(result.is_ok());
    }
}

API Coverage

This library provides comprehensive coverage of the FMP API:

✅ Implemented

  • Company Search (search, CIK, CUSIP, ISIN)
  • Stock Quotes (single, batch, exchange)
  • Company Information (profile, executives, market cap, peers)
  • Financial Statements (income, balance sheet, cash flow)
  • Financial Ratios and Key Metrics
  • Historical Price Charts (daily and intraday)
  • News and Press Releases (general news, company-specific, press releases)
  • Analyst Estimates and Ratings (estimates, grades, price targets, consensus)
  • SEC Filings (10-K, 10-Q, 8-K, proxy statements, insider transactions)
  • Insider Trading (trades, statistics, RSS feeds)
  • ETF and Mutual Fund Data (holdings, performance, expense ratios, country allocations)
  • Market Performance Indicators (sector performance, market hours, gainers/losers)
  • Technical Indicators (RSI, EMA, SMA, Williams %R, ADX, and more)
  • Economics Data (treasury rates, economic indicators, commodities)
  • Institutional Ownership (Form 13F filings, institutional holders)
  • Corporate Actions (stock splits, dividends, mergers & acquisitions)
  • Cryptocurrency & Forex data
  • Congress Trading (members' trades and statistics)
  • ESG Scores and ratings
  • Bulk data processing capabilities

Error Handling

The library uses a custom Error type that covers common failure scenarios:

use fmp_rs::{FmpClient, Error};

match client.quote().get_quote("INVALID").await {
    Ok(quotes) => println!("Got quotes: {:?}", quotes),
    Err(Error::NotFound(msg)) => println!("Symbol not found: {}", msg),
    Err(Error::RateLimitExceeded) => println!("Rate limit hit, try again later"),
    Err(Error::Api { status, message }) => println!("API error {}: {}", status, message),
    Err(e) => println!("Other error: {}", e),
}

Contributing

Contributions are welcome! The API is extensive, and help implementing additional endpoints would be greatly appreciated.

Adding New Endpoints

  1. Add the response model to src/models/
  2. Implement the endpoint in the appropriate file under src/endpoints/
  3. Add tests in the endpoint module
  4. Update the README

License

This project is licensed under either of:

at your option.

Disclaimer

This library is not officially associated with or endorsed by Financial Modeling Prep. Use of the FMP API is subject to their terms of service and API usage limits.

Links