shredio / fmp-client
Requires
- php: >=8.3
- halaxa/json-machine: ^1.2
- league/csv: ^9.24
- symfony/http-client: ^7.2
- webmozart/assert: ^1.11
Requires (Dev)
- nette/utils: ^4.0
- phpstan/phpstan: ^2.1
- phpstan/phpstan-webmozart-assert: ^2.0
- phpunit/phpunit: ^12.2
This package is auto-updated.
Last update: 2025-08-17 11:07:40 UTC
README
A high-performance PHP client library for the Financial Modeling Prep (FMP) API, designed to handle large financial datasets efficiently with memory-conscious streaming and asynchronous processing.
Key Features
- Memory Efficient: Large JSON/CSV responses are streamed using JsonMachine and League CSV, not loaded entirely into memory
- Async Support: Non-blocking concurrent API requests using PHP Fibers via FmpPromise
- Strong Typing: All data structures use readonly classes with comprehensive type hints
- Immutable Payloads: All payload objects are immutable with readonly properties
- Validation: Optional strict mode for enhanced data validation
- Bulk Operations: Efficient handling of bulk data endpoints
- Error Handling: Comprehensive exception handling with request URL context
Requirements
- PHP 8.3 or higher
- Symfony HTTP Client
- JsonMachine for efficient JSON parsing
- League CSV for CSV processing
- Webmozart Assert for validation
Installation
Install via Composer:
composer require shredio/fmp-client
Quick Start
use Shredio\FmpClient\FmpClient; use Symfony\Component\HttpClient\HttpClient; // Initialize the client $httpClient = HttpClient::create(); $fmpClient = new FmpClient($httpClient, 'your-api-key-here'); // Get company profile foreach ($fmpClient->companyProfile('AAPL') as $profile) { echo "Company: {$profile->companyName}\n"; echo "Price: ${$profile->price}\n"; echo "Market Cap: {$profile->marketCap}\n"; } // Get stock list (streamed) foreach ($fmpClient->stockList() as $stock) { echo "{$stock->symbol}: {$stock->name}\n"; }
Configuration Options
Strict Mode
Enable strict mode for enhanced validation that throws exceptions on invalid data:
$strictClient = $fmpClient->withStrictMode(true); try { foreach ($strictClient->companyProfile('INVALID') as $profile) { // Process profile } } catch (UnexpectedResponseContentException $e) { echo "Validation error: {$e->getMessage()}\n"; echo "Request URL: {$e->getRequestUrl()}\n"; }
Custom Error Handling
Implement custom error handling for non-strict mode (useful for logging):
use Shredio\FmpClient\Exception\UnexpectedResponseContentExceptionHandler; $handler = new class implements UnexpectedResponseContentExceptionHandler { public function handle(UnexpectedResponseContentException $exception): void { error_log("FMP Client Error: {$exception->getMessage()}"); } }; $fmpClient = new FmpClient($httpClient, 'api-key', $handler);
Usage Examples
Basic Stock Data
// Get available exchanges foreach ($fmpClient->availableExchanges() as $exchange) { echo "{$exchange->name} ({$exchange->code})\n"; } // Get company financials foreach ($fmpClient->balanceSheetStatement('AAPL') as $statement) { echo "Date: {$statement->date}\n"; echo "Total Assets: {$statement->totalAssets}\n"; } // Get dividend history foreach ($fmpClient->dividends('AAPL') as $dividend) { echo "Date: {$dividend->date}, Amount: {$dividend->dividend}\n"; }
Bulk Operations
use DateTimeImmutable; // Bulk company profiles (memory efficient streaming) foreach ($fmpClient->companyProfileBulk() as $profile) { echo "{$profile->symbol}: {$profile->companyName}\n"; } // End of day bulk quotes $date = new DateTimeImmutable('2024-01-15'); foreach ($fmpClient->eodBulkQuotes($date) as $quote) { echo "{$quote->symbol}: Close ${$quote->close}\n"; } // Bulk financial statements foreach ($fmpClient->incomeStatementBulk('2023') as $statement) { echo "{$statement->symbol}: Revenue {$statement->revenue}\n"; }
Calendar Data
use DateTimeImmutable; use Psr\Log\NullLogger; $from = new DateTimeImmutable('2024-01-01'); $to = new DateTimeImmutable('2024-01-31'); $logger = new NullLogger(); // Earnings calendar (automatically paginated) foreach ($fmpClient->earningsCalendar($from, $to, $logger) as $earning) { echo "Date: {$earning->date}\n"; echo "Symbol: {$earning->symbol}\n"; echo "EPS Estimate: {$earning->epsEstimate}\n"; } // Dividends calendar foreach ($fmpClient->dividendsCalendar($from, $to, $logger) as $dividend) { echo "{$dividend->symbol}: {$dividend->dividend} on {$dividend->date}\n"; } // Stock splits calendar foreach ($fmpClient->splitsCalendar($from, $to, $logger) as $split) { echo "{$split->symbol}: {$split->numerator}:{$split->denominator} on {$split->date}\n"; }
Historical Data
use DateTimeImmutable; use Shredio\FmpClient\Enum\TimeInterval; $from = new DateTimeImmutable('2024-01-01'); $to = new DateTimeImmutable('2024-01-31'); // Historical end-of-day prices foreach ($fmpClient->historicalPriceEod('AAPL', $from, $to) as $price) { echo "Date: {$price->date}, Close: ${$price->close}\n"; } // Historical chart data with intervals foreach ($fmpClient->historicalChart('AAPL', TimeInterval::FiveMin, $from, $to) as $data) { echo "Time: {$data->date}, Price: ${$data->close}\n"; }
Financial Metrics and Ratios
use Shredio\FmpClient\Enum\PeriodQuery; // Key metrics foreach ($fmpClient->keyMetrics('AAPL', 10, PeriodQuery::Annual) as $metrics) { echo "Date: {$metrics->date}\n"; echo "P/E Ratio: {$metrics->peRatio}\n"; echo "ROE: {$metrics->roe}\n"; } // TTM (Trailing Twelve Months) metrics foreach ($fmpClient->keyMetricsTtm('AAPL') as $metrics) { echo "Market Cap: {$metrics->marketCapTtm}\n"; echo "Revenue TTM: {$metrics->revenueTtm}\n"; } // Financial ratios foreach ($fmpClient->ratios('AAPL', 5, PeriodQuery::Quarterly) as $ratios) { echo "Current Ratio: {$ratios->currentRatio}\n"; echo "Debt to Equity: {$ratios->debtEquityRatio}\n"; }
Asynchronous Operations
// Execute multiple requests concurrently $companyProfilePromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->companyProfile('AAPL')) ); $dividendsPromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->dividends('AAPL')) ); $keyMetricsPromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->keyMetrics('AAPL')) ); // Wait for all promises to complete $profiles = $companyProfilePromise->wait(); $dividends = $dividendsPromise->wait(); $metrics = $keyMetricsPromise->wait(); echo "Loaded data for: " . $profiles[0]->companyName . "\n"; echo "Dividend count: " . count($dividends) . "\n"; echo "Metrics count: " . count($metrics) . "\n";
Available Endpoints
Company & Stock Data
stockList()
- List all available stockscompanyProfile(string $symbols)
- Company profile informationcompanyProfileBulk()
- Bulk company profiles (streaming)availableExchanges()
- Available stock exchangesgetAllExchangeMarketHours()
- Market hours for all exchanges
Financial Statements
balanceSheetStatement(string $symbol)
- Balance sheet databalanceSheetStatementBulk(string $year, Period $period)
- Bulk balance sheetsincomeStatement(string $symbol)
- Income statement dataincomeStatementBulk(string $year, Period $period)
- Bulk income statementscashFlowStatement(string $symbol)
- Cash flow datacashFlowStatementBulk(string $year, Period $period)
- Bulk cash flow statementslatestFinancialStatements(int $page, int $limit)
- Latest financial statements
Market Data & Quotes
eodBulkQuotes(DateTimeImmutable $date)
- End of day bulk quotesbatchExchangeQuote(string $exchange)
- Exchange quotesbatchExchangeQuoteDetailed(string $exchange)
- Detailed exchange quotesbatchForexQuotes()
- Forex currency quotes
Historical Data
historicalPriceEod(string $symbol, DateTimeImmutable $from, DateTimeImmutable $to)
- Historical priceshistoricalChart(string $symbol, TimeInterval $interval, DateTimeImmutable $from, DateTimeImmutable $to)
- Historical chart data
Analytics & Metrics
keyMetrics(string $symbol, int $limit, PeriodQuery $period)
- Key financial metricskeyMetricsTtm(string $symbol)
- TTM key metricskeyMetricsTtmBulk()
- Bulk TTM key metricsratios(string $symbol, int $limit, PeriodQuery $period)
- Financial ratiosratiosTtm(string $symbol)
- TTM ratiosratiosTtmBulk()
- Bulk TTM ratiosfinancialScores(string $symbol)
- Financial scoresscoresBulk()
- Bulk financial scoresgetAnalystEstimates(string $symbol, string $period, int $page, int $limit)
- Analyst estimates
Calendar Events
earningsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)
- Earnings calendardividendsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)
- Dividends calendarsplitsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)
- Stock splits calendardividends(string $symbol)
- Company dividend history
Other Data
cryptocurrencyList()
- Available cryptocurrenciesindexList()
- Available market indicesfinancialStatementSymbolList()
- Symbols with financial statements
Data Types
All API responses are mapped to strongly-typed readonly payload classes with comprehensive type annotations. Each payload class includes a toArray()
method that returns all properties as an associative array.
Example payload structure:
// CompanyProfile payload readonly class CompanyProfile { public function __construct( public string $symbol, public ?float $price = null, public ?int $marketCap = null, public ?string $companyName = null, // ... more properties ) {} /** * @return array{symbol: string, price: float|null, marketCap: int|null, companyName: string|null, ...} */ public function toArray(): array { // Returns all properties as associative array } }
Testing
Run the test suite:
composer test
Run static analysis:
composer phpstan
The library includes comprehensive tests with real API response fixtures and uses MockHttpClient for reliable testing without API dependencies.
Architecture
The library follows these key design principles:
- Memory Efficiency: Uses streaming parsers (JsonMachine, League CSV) to handle large responses without loading entire datasets into memory
- Async Processing: Leverages PHP Fibers through FmpPromise for concurrent request handling
- Immutable Data: All payload objects are readonly and immutable
- Strong Typing: Comprehensive type hints throughout the codebase
- Error Resilience: Graceful handling of malformed API responses with optional strict validation
Core Components
- FmpClient - Main entry point with all API methods
- FmpPromise - Async operations using PHP Fibers
- LargeResponseParser - Memory-efficient streaming parser
- FmpPayloadMapper - Maps API responses to typed objects
- FmpValidator - Data validation layer
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
composer test
- Run static analysis:
composer phpstan
- Submit a pull request
License
This library is licensed under the MIT License. See the LICENSE file for details.
Financial Modeling Prep API
This library provides a PHP interface to the Financial Modeling Prep API. You'll need an API key from FMP to use this library. Visit their website to sign up and get your API key.