Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/requirements-build.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
# floor bump (or a newer compatible release) is enough to pick up updates.
# Builds then run `python -m build --no-isolation` so PEP 517 isolation
# cannot pull a different backend than what we just installed.
build>=1.5.0
hatchling>=1.31.0
build>=1.6.1
hatchling>=1.32.0
hatch-vcs>=0.5.0
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ jobs:
python-version: ${{ matrix.python }}

- name: ⚡ Install uv (with cache)
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: true

- name: ▶️ Run Tests
Expand Down Expand Up @@ -88,9 +88,9 @@ jobs:
python-version: "3.14"

- name: ⚡ Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"

- name: 📊 Run all tests with coverage
env:
Expand Down Expand Up @@ -145,9 +145,9 @@ jobs:
python-version: "3.14"

- name: ⚡ Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"

- name: 📊 Extras coverage gate (lc / mcp / Redis)
env:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ jobs:
persist-credentials: false

- name: 🔍 Initialize CodeQL
uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
languages: python
build-mode: none

- name: 📈 Perform CodeQL Analysis
uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
category: "/language:python"
4 changes: 2 additions & 2 deletions .github/workflows/dev-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}

- name: ⚡ Install uv (with cache)
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: true

- name: 📦 Install build frontend and backend (version floors)
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/document.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: true

- name: Cache uv dependencies
Expand Down Expand Up @@ -132,7 +132,7 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1

- name: Generate deployment summary
env:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/publish-testpypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}

- name: ⚡ Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: false

- name: 📦 Install build frontend and backend (version floors)
Expand Down Expand Up @@ -321,9 +321,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}

- name: ⚡ Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: false

- name: 📦 Build wheel & sdist
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}

- name: ⚡ Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.12.3"
version: "0.12.13"
enable-cache: false

- name: 📦 Install build frontend and backend (version floors)
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ repos:
# ───────── Ruff (lint / fix / format) ────────────────────────────────────
# Ruff replaces black here: black 24.x and ruff's formatter disagree on
# assert-with-message wrapping, so running both fights over the same lines.
# Keep this rev in sync with the ruff pin in uv.lock.
# Keep this rev in sync with the ruff floor in pyproject.toml.
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.2
rev: v0.16.7
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- **Optional FMP parameters across 27 sync/async method pairs (Refs #396).**
Add holiday date ranges, market-hours timestamps, exchange-list expansion,
screener average-volume bounds, share-float pagination, CIK/employee limits,
historical market-cap dates and limits, symbol-change filters, extended
intraday hours, earnings report-time inclusion, economic indicator dates and
calendar country filters, beneficial-ownership limits, calendar pagination,
ESG benchmark years, Senate/House pagination, alternative-asset intraday
dates, and SIC industry/code filters. Both custom DCF methods expose all 18
documented numeric assumptions. Existing tool schemas and parameter hints
include the controls; a provider-derived fixture and catalog guard detect
missing optional parameters. See `docs/api/optional-parameters.md` for the
complete Python-to-FMP mapping.

### Changed

- **Preserve existing signatures and requests.** New arguments are keyword-only
with `None` defaults and are omitted before request validation. Existing
positional calls, types, return shapes, and endpoint defaults remain intact,
including CIK search's limit of 50. Explicit `False` and `0` are forwarded.
- **Refresh every dependency group to current stable releases (2026-09-13).**
Upgrade Pydantic 2.13.4 → 2.13.5; MCP 2.0.0 → 2.2.0; langchain-core
1.5.3 → 1.6.3; langchain-openai 1.4.2 → 1.6.2; LangGraph 1.2.10 → 1.2.11;
OpenAI 2.53.0 → 3.13.0; tiktoken 0.13.0 → 0.14.0; and tomli 2.0.1 → 2.4.1.
OpenAI 3 uses HTTPX2 internally; FMP requests continue through HTTPX 0.28.1.
The MCP compatibility loader retains its 1.x fallback while type-checking
against the 2.2 stubs. The package still supports Python 3.10–3.14.
- **Build, development, documentation, and CI tools.** Upgrade Hatchling
1.31.0 → 1.32.0, build 1.5.0 → 1.6.1, uv 0.12.3 → 0.12.13, Ruff
0.16.2 → 0.16.7 (including the hook), mypy 2.3.0 → 2.3.1, nox
2026.7.11 → 2026.8.17, coverage 7.15.4 → 7.16.0, pre-commit 4.6.1 → 4.6.2,
python-dotenv 1.2.2 → 1.2.3, responses 0.26.2 → 0.26.3, and
mkdocstrings-python 2.0.5 → 2.0.8. Align the security session's Bandit floor
with 1.9.4. Dependencies already at the latest stable release are retained;
prereleases are excluded and `uv.lock` remains uncommitted.
- **SHA-pinned GitHub Actions.** setup-uv 10.0.1 → 10.1.0, deploy-pages
5.0.0 → 5.0.1, and CodeQL 4.37.7 → 4.38.0; other actions and hooks were
checked and remain at their latest stable versions.

### Fixed

- **Exchange-variant queries use `symbol`.** Keep the public
`search_exchange_variants(query)` signature while mapping it to FMP's
`symbol` key. The old wire name could silently return Apple variants for a
Microsoft query.
- **Restore `make ci` and `make check-all`.** Add the missing `ci_check` nox
aggregator for the existing lint, typing, security, core/extras coverage,
and import-smoke gates. Coverage thresholds and hosted CI policy are unchanged.
- **Document remaining provider qualification.** Date filters do not repair
NYSE 2027/2028 calendar completeness, GDP date-filter behavior, SEC profile
identifier behavior, or overlapping pages. These remain tracked in #396;
the SDK does not alter provider records or infer completeness from HTTP 200.

## [2.7.1] - 2026-08-20

Patch of leftover 2.7.0 CI, docs, and tests that landed unlabeled on
Expand Down
125 changes: 125 additions & 0 deletions docs/api/optional-parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Optional request parameters

The sync and async clients accept the same filters. The additions below are
keyword-only and default to `None`. Existing argument order, positional calls,
defaults, and return types are preserved. Unset additions are omitted before
request validation, so existing endpoint defaults still apply: for example,
`market.search_by_cik("320193")` still requests `limit=50`.

Pass `False` or `0` explicitly when needed; neither is treated as unset. Limits
and pages are sent to FMP as requested. The SDK does not automatically paginate,
deduplicate overlapping pages, widen date ranges, or repair calendar records.

```python
from datetime import date

from fmp_data import FMPDataClient

with FMPDataClient.from_env() as client:
holidays = client.market.get_holidays_by_exchange(
"NYSE", from_date=date(2026, 1, 1), to_date=date(2026, 12, 31)
)
companies = client.market.search_by_cik("320193", limit=2)
prices = client.company.get_intraday_prices(
"AAPL",
"5min",
from_date=date(2026, 9, 10),
to_date=date(2026, 9, 11),
extended=False,
)
valuation = client.fundamental.get_custom_discounted_cash_flow(
"MSFT", risk_free_rate=3.5, revenue_growth_pct=5.0
)
```

Use `await client.<group>.<method>(...)` with `AsyncFMPDataClient` and the same
arguments. Dates are `datetime.date`; timestamps are Unix seconds. Country and
SIC codes are strings. FMP documents `invalid` as a string, so use `"false"` or
`"true"` rather than a Python boolean. Country values follow FMP's vocabulary;
the audit verified `US` and `UK`, while `GB` returned no rows.

## Added controls

Provider documentation checked on 2026-09-13. Each row links to its source.

| Client method | New Python arguments | FMP query keys |
| --- | --- | --- |
| [`market.get_holidays_by_exchange`](https://site.financialmodelingprep.com/developer/docs/stable/holidays-by-exchange) | `from_date`, `to_date` | `from`, `to` |
| [`market.get_company_screener`](https://site.financialmodelingprep.com/developer/docs/stable/search-company-screener) | `avg_volume_more_than`, `avg_volume_less_than` | `avgVolumeMoreThan`, `avgVolumeLowerThan` |
| [`market.get_market_hours`](https://site.financialmodelingprep.com/developer/docs/stable/exchange-market-hours) | `timestamp` | `timestamp` |
| [`market.get_all_exchange_market_hours`](https://site.financialmodelingprep.com/developer/docs/stable/all-exchange-market-hours) | `timestamp` | `timestamp` |
| [`market.get_all_shares_float`](https://site.financialmodelingprep.com/developer/docs/stable/all-shares-float) | `page`, `limit` | `page`, `limit` |
| [`market.get_available_exchanges`](https://site.financialmodelingprep.com/developer/docs/stable/available-exchanges) | `extended` | `extended` |
| [`market.search_by_cik`](https://site.financialmodelingprep.com/developer/docs/stable/search-cik) | `limit` | `limit` |
| [`company.get_employee_count`](https://site.financialmodelingprep.com/developer/docs/stable/employee-count) | `limit` | `limit` |
| [`company.get_historical_market_cap`](https://site.financialmodelingprep.com/developer/docs/stable/historical-market-cap) | `from_date`, `to_date`, `limit` | `from`, `to`, `limit` |
| [`company.get_symbol_changes`](https://site.financialmodelingprep.com/developer/docs/stable/symbol-changes-list) | `invalid`, `limit` | `invalid`, `limit` |
| [`company.get_intraday_prices`](https://site.financialmodelingprep.com/developer/docs/stable/intraday-5-min) | `extended` | `extended` |
| [`company.get_earnings`](https://site.financialmodelingprep.com/developer/docs/stable/earnings-company) | `include_report_times` | `includeReportTimes` |
| [`economics.get_economic_indicators`](https://site.financialmodelingprep.com/developer/docs/stable/economics-indicators) | `start_date`, `end_date` | `from`, `to` |
| [`economics.get_economic_calendar`](https://site.financialmodelingprep.com/developer/docs/stable/economics-calendar) | `country` | `country` |
| [`fundamental.get_custom_discounted_cash_flow`](https://site.financialmodelingprep.com/developer/docs/stable/custom-dcf-advanced) | 18 custom DCF assumptions (below) | Corresponding camelCase keys (below) |
| [`fundamental.get_custom_levered_dcf`](https://site.financialmodelingprep.com/developer/docs/stable/custom-dcf-levered) | 18 custom DCF assumptions (below) | Corresponding camelCase keys (below) |
| [`institutional.get_beneficial_ownership`](https://site.financialmodelingprep.com/developer/docs/stable/acquisition-ownership) | `limit` | `limit` |
| [`intelligence.get_earnings_calendar`](https://site.financialmodelingprep.com/developer/docs/stable/earnings-calendar) | `page` | `page` |
| [`intelligence.get_dividends_calendar`](https://site.financialmodelingprep.com/developer/docs/stable/dividends-calendar) | `page` | `page` |
| [`intelligence.get_stock_splits_calendar`](https://site.financialmodelingprep.com/developer/docs/stable/splits-calendar) | `page` | `page` |
| [`intelligence.get_esg_benchmark`](https://site.financialmodelingprep.com/developer/docs/stable/esg-benchmark) | `year` | `year` |
| [`intelligence.get_senate_trading`](https://site.financialmodelingprep.com/developer/docs/stable/senate-trading) | `page`, `limit` | `page`, `limit` |
| [`intelligence.get_house_disclosure`](https://site.financialmodelingprep.com/developer/docs/stable/house-trading) | `page`, `limit` | `page`, `limit` |
| [`alternative.get_crypto_intraday`](https://site.financialmodelingprep.com/developer/docs/stable/cryptocurrency-intraday-1-hour) | `start_date`, `end_date` | `from`, `to` |
| [`alternative.get_forex_intraday`](https://site.financialmodelingprep.com/developer/docs/stable/forex-intraday-1-hour) | `start_date`, `end_date` | `from`, `to` |
| [`alternative.get_commodity_intraday`](https://site.financialmodelingprep.com/developer/docs/stable/commodities-intraday-1-hour) | `start_date`, `end_date` | `from`, `to` |
| [`sec.get_sic_codes`](https://site.financialmodelingprep.com/developer/docs/stable/industry-classification-list) | `industry_title`, `sic_code` | `industryTitle`, `sicCode` |

## Custom DCF assumptions

Both custom DCF methods expose all 18 assumptions as `float | None`. Values are
forwarded without unit conversion; percentage fields use the units documented
by FMP. Omitting an assumption leaves its selection to the provider.

| Python argument | FMP query key |
| --- | --- |
| `revenue_growth_pct` | `revenueGrowthPct` |
| `ebitda_pct` | `ebitdaPct` |
| `depreciation_and_amortization_pct` | `depreciationAndAmortizationPct` |
| `cash_and_short_term_investments_pct` | `cashAndShortTermInvestmentsPct` |
| `receivables_pct` | `receivablesPct` |
| `inventories_pct` | `inventoriesPct` |
| `payable_pct` | `payablePct` |
| `ebit_pct` | `ebitPct` |
| `capital_expenditure_pct` | `capitalExpenditurePct` |
| `operating_cash_flow_pct` | `operatingCashFlowPct` |
| `selling_general_and_administrative_expenses_pct` | `sellingGeneralAndAdministrativeExpensesPct` |
| `tax_rate` | `taxRate` |
| `long_term_growth_rate` | `longTermGrowthRate` |
| `cost_of_debt` | `costOfDebt` |
| `cost_of_equity` | `costOfEquity` |
| `market_risk_premium` | `marketRiskPremium` |
| `beta` | `beta` |
| `risk_free_rate` | `riskFreeRate` |

## Tool integrations

Existing LangChain and MCP catalog entries expose these optional controls with
matching types and hints. The catalog inventory is unchanged: the screener,
available-exchanges, and company earnings convenience methods remain SDK-only;
applications can wrap their public methods explicitly. The intelligence earnings
tool already exposed `include_report_times`.

`market.search_exchange_variants(query)` retains its public argument name, but
now sends FMP's required `symbol` query key. For example, pass `"MSFT"` to search
Microsoft's exchange variants. The old `query=MSFT` wire request returned Apple
variants in the live audit.

## Provider qualification

Exposing a filter is separate from verifying the returned dataset. The audit
found overlapping calendar pages, an empty date-bounded GDP response despite
an in-range row in the unbounded series, and unresolved SEC profile identifier
behavior. NYSE 2027/2028 holiday and early-close completeness also remains under
investigation. No calendar flags, provider payloads, or date boundaries are
rewritten. An empty successful response does not establish completeness.

See [issue #396](https://github.com/MehdiZare/fmp-data/issues/396) for the provider
evidence and remaining qualification work.
5 changes: 5 additions & 0 deletions docs/api/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ batch bulk accept only `PeriodFiscal`. Some company series take only
`structure=` takes `Structure` (`flat` / `nested`); live `/stable`
returns the same list-of-objects for both.

## Optional request filters

See [optional request parameters](optional-parameters.md) for the new filters,
backward-compatible defaults, custom DCF assumptions, and provider limitations.

## Main Clients

### Sync Client
Expand Down
2 changes: 2 additions & 0 deletions docs/mcp/tools.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# FMP Data MCP Tools Reference

For optional filters and defaults, see [request parameters](../api/optional-parameters.md).

This document lists the MCP tools available in this release.
Tools are organized by client module and include descriptions.

Expand Down
Loading