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
80 changes: 42 additions & 38 deletions crates/fmp-py/python/fmp/_native/economics/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ class EconomicCalendarEvent:
@property
def currency(self) -> builtins.str: ...
@property
def previous(self) -> builtins.float: ...
def previous(self) -> typing.Optional[builtins.float]: ...
@property
def estimate(self) -> builtins.float: ...
def estimate(self) -> typing.Optional[builtins.float]: ...
@property
def actual(self) -> builtins.float: ...
def actual(self) -> typing.Optional[builtins.float]: ...
@property
def change(self) -> builtins.float: ...
def change(self) -> typing.Optional[builtins.float]: ...
@property
def impact(self) -> builtins.str: ...
@property
def change_percentage(self) -> builtins.float: ...
def change_percentage(self) -> typing.Optional[builtins.float]: ...
@property
def unit(self) -> builtins.str: ...
def unit(self) -> typing.Optional[builtins.str]: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(
cls,
Expand All @@ -60,13 +60,13 @@ class EconomicCalendarEvent:
country: builtins.str,
event: builtins.str,
currency: builtins.str,
previous: builtins.float,
estimate: builtins.float,
actual: builtins.float,
change: builtins.float,
previous: typing.Optional[builtins.float],
estimate: typing.Optional[builtins.float],
actual: typing.Optional[builtins.float],
change: typing.Optional[builtins.float],
impact: builtins.str,
change_percentage: builtins.float,
unit: builtins.str,
change_percentage: typing.Optional[builtins.float],
unit: typing.Optional[builtins.str],
) -> EconomicCalendarEvent: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
Expand All @@ -89,10 +89,14 @@ class EconomicIndicatorObservation:
@property
def date(self) -> datetime.date: ...
@property
def value(self) -> builtins.float: ...
def value(self) -> typing.Optional[builtins.float]: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(
cls, *, name: builtins.str, date: datetime.date, value: builtins.float
cls,
*,
name: builtins.str,
date: datetime.date,
value: typing.Optional[builtins.float],
) -> EconomicIndicatorObservation: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
Expand Down Expand Up @@ -205,46 +209,46 @@ class TreasuryRate:
@property
def date(self) -> datetime.date: ...
@property
def month_1(self) -> builtins.float: ...
def month_1(self) -> typing.Optional[builtins.float]: ...
@property
def month_2(self) -> builtins.float: ...
def month_2(self) -> typing.Optional[builtins.float]: ...
@property
def month_3(self) -> builtins.float: ...
def month_3(self) -> typing.Optional[builtins.float]: ...
@property
def month_6(self) -> builtins.float: ...
def month_6(self) -> typing.Optional[builtins.float]: ...
@property
def year_1(self) -> builtins.float: ...
def year_1(self) -> typing.Optional[builtins.float]: ...
@property
def year_2(self) -> builtins.float: ...
def year_2(self) -> typing.Optional[builtins.float]: ...
@property
def year_3(self) -> builtins.float: ...
def year_3(self) -> typing.Optional[builtins.float]: ...
@property
def year_5(self) -> builtins.float: ...
def year_5(self) -> typing.Optional[builtins.float]: ...
@property
def year_7(self) -> builtins.float: ...
def year_7(self) -> typing.Optional[builtins.float]: ...
@property
def year_10(self) -> builtins.float: ...
def year_10(self) -> typing.Optional[builtins.float]: ...
@property
def year_20(self) -> builtins.float: ...
def year_20(self) -> typing.Optional[builtins.float]: ...
@property
def year_30(self) -> builtins.float: ...
def year_30(self) -> typing.Optional[builtins.float]: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(
cls,
*,
date: datetime.date,
month_1: builtins.float,
month_2: builtins.float,
month_3: builtins.float,
month_6: builtins.float,
year_1: builtins.float,
year_2: builtins.float,
year_3: builtins.float,
year_5: builtins.float,
year_7: builtins.float,
year_10: builtins.float,
year_20: builtins.float,
year_30: builtins.float,
month_1: typing.Optional[builtins.float],
month_2: typing.Optional[builtins.float],
month_3: typing.Optional[builtins.float],
month_6: typing.Optional[builtins.float],
year_1: typing.Optional[builtins.float],
year_2: typing.Optional[builtins.float],
year_3: typing.Optional[builtins.float],
year_5: typing.Optional[builtins.float],
year_7: typing.Optional[builtins.float],
year_10: typing.Optional[builtins.float],
year_20: typing.Optional[builtins.float],
year_30: typing.Optional[builtins.float],
) -> TreasuryRate: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
Expand Down
76 changes: 38 additions & 38 deletions crates/fmp-py/src/models/economics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@ pub(crate) struct TreasuryRate {
#[pyo3(get)]
pub date: ::chrono::NaiveDate,
#[pyo3(get)]
pub month_1: f64,
pub month_1: Option<f64>,
#[pyo3(get)]
pub month_2: f64,
pub month_2: Option<f64>,
#[pyo3(get)]
pub month_3: f64,
pub month_3: Option<f64>,
#[pyo3(get)]
pub month_6: f64,
pub month_6: Option<f64>,
#[pyo3(get)]
pub year_1: f64,
pub year_1: Option<f64>,
#[pyo3(get)]
pub year_2: f64,
pub year_2: Option<f64>,
#[pyo3(get)]
pub year_3: f64,
pub year_3: Option<f64>,
#[pyo3(get)]
pub year_5: f64,
pub year_5: Option<f64>,
#[pyo3(get)]
pub year_7: f64,
pub year_7: Option<f64>,
#[pyo3(get)]
pub year_10: f64,
pub year_10: Option<f64>,
#[pyo3(get)]
pub year_20: f64,
pub year_20: Option<f64>,
#[pyo3(get)]
pub year_30: f64,
pub year_30: Option<f64>,
}

#[gen_stub_pymethods]
Expand All @@ -46,18 +46,18 @@ impl TreasuryRate {
#[pyo3(signature = (*, date, month_1, month_2, month_3, month_6, year_1, year_2, year_3, year_5, year_7, year_10, year_20, year_30))]
fn new(
date: ::chrono::NaiveDate,
month_1: f64,
month_2: f64,
month_3: f64,
month_6: f64,
year_1: f64,
year_2: f64,
year_3: f64,
year_5: f64,
year_7: f64,
year_10: f64,
year_20: f64,
year_30: f64,
month_1: Option<f64>,
month_2: Option<f64>,
month_3: Option<f64>,
month_6: Option<f64>,
year_1: Option<f64>,
year_2: Option<f64>,
year_3: Option<f64>,
year_5: Option<f64>,
year_7: Option<f64>,
year_10: Option<f64>,
year_20: Option<f64>,
year_30: Option<f64>,
) -> Self {
Self {
date,
Expand Down Expand Up @@ -230,7 +230,7 @@ pub(crate) struct EconomicIndicatorObservation {
#[pyo3(get)]
pub date: ::chrono::NaiveDate,
#[pyo3(get)]
pub value: f64,
pub value: Option<f64>,
}

#[gen_stub_pymethods]
Expand All @@ -240,7 +240,7 @@ impl EconomicIndicatorObservation {
#[allow(clippy::too_many_arguments)]
#[allow(clippy::fn_params_excessive_bools)]
#[pyo3(signature = (*, name, date, value))]
fn new(name: String, date: ::chrono::NaiveDate, value: f64) -> Self {
fn new(name: String, date: ::chrono::NaiveDate, value: Option<f64>) -> Self {
Self { name, date, value }
}

Expand Down Expand Up @@ -328,19 +328,19 @@ pub(crate) struct EconomicCalendarEvent {
#[pyo3(get)]
pub currency: String,
#[pyo3(get)]
pub previous: f64,
pub previous: Option<f64>,
#[pyo3(get)]
pub estimate: f64,
pub estimate: Option<f64>,
#[pyo3(get)]
pub actual: f64,
pub actual: Option<f64>,
#[pyo3(get)]
pub change: f64,
pub change: Option<f64>,
#[pyo3(get)]
pub impact: String,
#[pyo3(get)]
pub change_percentage: f64,
pub change_percentage: Option<f64>,
#[pyo3(get)]
pub unit: String,
pub unit: Option<String>,
}

#[gen_stub_pymethods]
Expand All @@ -355,13 +355,13 @@ impl EconomicCalendarEvent {
country: String,
event: String,
currency: String,
previous: f64,
estimate: f64,
actual: f64,
change: f64,
previous: Option<f64>,
estimate: Option<f64>,
actual: Option<f64>,
change: Option<f64>,
impact: String,
change_percentage: f64,
unit: String,
change_percentage: Option<f64>,
unit: Option<String>,
) -> Self {
Self {
date,
Expand Down
17 changes: 14 additions & 3 deletions crates/fmp-py/tests/test_economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_economics_namespace_is_the_generated_type(client: Any) -> None:


def test_treasury_rates_with_no_arguments(client: Any, fixture_server: FixtureServer) -> None:
"""``treasury_rates`` maps to ``/treasury-rates`` with no query string and decodes the curve row."""
"""``treasury_rates`` maps to ``/treasury-rates`` with no query string and decodes a null tenor as ``None``."""
fixture_server.route("/treasury-rates", load_fixture("treasury_rates.json"))
rows = client.economics.treasury_rates()

Expand All @@ -45,6 +45,8 @@ def test_treasury_rates_with_no_arguments(client: Any, fixture_server: FixtureSe
assert isinstance(row, TreasuryRate)
assert row.date == datetime.date(2026, 7, 29)
assert row.month_1 == pytest.approx(3.73)
assert row.month_2 is None
assert row.month_3 == pytest.approx(3.83)
assert row.year_10 == pytest.approx(4.67)
assert row.year_30 == pytest.approx(5.2)

Expand Down Expand Up @@ -91,6 +93,15 @@ def test_indicators_with_a_documented_name(client: Any, fixture_server: FixtureS
assert row.value == pytest.approx(31_422.526)


def test_indicators_decode_a_null_value_as_none(client: Any, fixture_server: FixtureServer) -> None:
"""A ``null`` indicator ``value`` decodes as ``None`` instead of failing the call."""
body = load_fixture("economic_indicators.json")
body[0]["value"] = None
fixture_server.route("/economic-indicators", body)

assert client.economics.indicators("GDP")[0].value is None


def test_indicators_with_every_option(client: Any, fixture_server: FixtureServer) -> None:
"""``indicators`` encodes ``name``, ``from``, ``to`` in that order."""
fixture_server.route("/economic-indicators", load_fixture("economic_indicators.json"))
Expand Down Expand Up @@ -147,11 +158,11 @@ def test_calendar_with_no_arguments(client: Any, fixture_server: FixtureServer)
assert row.currency == "SGD"
assert row.event == "Import Prices YoY (Jun)"
assert row.actual == pytest.approx(13.6)
assert row.estimate == pytest.approx(21.0)
assert row.estimate is None
assert row.change == pytest.approx(-4.9)
assert row.change_percentage == pytest.approx(-26.486)
assert row.impact == "Low"
assert row.unit == "%"
assert row.unit is None


def test_calendar_with_every_option(client: Any, fixture_server: FixtureServer) -> None:
Expand Down
4 changes: 2 additions & 2 deletions crates/fmp-py/tests/typecheck_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,10 @@ def check_economics_contract(client: FmpClient) -> None:
economics: EconomicsNamespace = client.economics
rates: list[TreasuryRate] = economics.treasury_rates(from_=datetime.date(2026, 1, 27), to="2026-04-27")
observed_on: datetime.date = rates[0].date
year_30: float = rates[0].year_30
year_30: float | None = rates[0].year_30
observations: list[EconomicIndicatorObservation] = client.economics.indicators("GDP", from_="2025-04-27")
name: str = observations[0].name
value: float = observations[0].value
value: float | None = observations[0].value
events: list[EconomicCalendarEvent] = client.economics.calendar(
country="US", from_="2026-01-27", to=datetime.date(2026, 4, 27)
)
Expand Down
Loading
Loading