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
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
FMP_API_KEY: ${{ secrets.FMP_API_KEY }}
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
python-version: ["3.11", "3.12", "3.13", "3.14"]

steps:
- uses: actions/checkout@v4
Expand All @@ -37,17 +37,17 @@ jobs:
- name: run tests
run: make tests
- name: upload coverage reports to codecov
if: matrix.python-version == '3.12'
if: matrix.python-version == '3.13'
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./build/coverage.xml
- name: build book
if: ${{ matrix.python-version == '3.12' }}
if: ${{ matrix.python-version == '3.13' }}
run: make book
- name: publish book
if: ${{ matrix.python-version == '3.12' }}
if: ${{ matrix.python-version == '3.13' }}
run: make publish-book
- name: publish
if: ${{ matrix.python-version == '3.12' && github.event.head_commit.message == 'release' }}
if: ${{ matrix.python-version == '3.13' && github.event.head_commit.message == 'release' }}
run: make publish
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"args": [
"-x",
"-vvv",
"quantflow_tests/test_vault.py",
"quantflow_tests/test_data.py::test_fed_yc",
]
},
]
Expand Down
4,504 changes: 2,411 additions & 2,093 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "quantflow"
version = "0.4.2"
version = "0.4.3"
description = "quantitative analysis"
authors = [{ name = "Luca Sbardella", email = "luca@quantmind.com" }]
license = "BSD-3-Clause"
Expand Down Expand Up @@ -42,6 +42,7 @@ ghp-import = "^2.0.2"
ruff = "^0.12.2"
pytest-asyncio = "^1.0.0"
isort = "^6.0.1"
types-python-dateutil = "^2.9.0.20251115"

[tool.poetry.group.book]
optional = true
Expand Down
2 changes: 1 addition & 1 deletion quantflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Quantitative analysis and pricing"""

__version__ = "0.4.1"
__version__ = "0.4.3"
2 changes: 1 addition & 1 deletion quantflow/data/fiscal_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class FiscalData(AioHttpClient):
"""Fiscal Data API client.

THis class is used to fetch data from the
This class is used to fetch data from the
[fiscal data api](https://fiscaldata.treasury.gov/api-documentation/)
"""

Expand Down
49 changes: 23 additions & 26 deletions quantflow_tests/test_data.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from typing import AsyncIterator

import pytest
from aiohttp.client_exceptions import ClientError

from quantflow.data.fed import FederalReserve
from quantflow.data.fiscal_data import FiscalData
from quantflow.data.fmp import FMP
from quantflow_tests.utils import skip_network_issue

pytestmark = pytest.mark.skipif(not FMP().key, reason="No FMP API key found")
skip_fmp = not FMP().key


@pytest.fixture
Expand All @@ -16,49 +16,46 @@ async def fmp() -> AsyncIterator[FMP]:
yield fmp


@pytest.mark.skipif(skip_fmp, reason="No FMP API key found")
def test_client(fmp: FMP) -> None:
assert fmp.url
assert fmp.key


@pytest.mark.skipif(skip_fmp, reason="No FMP API key found")
async def test_historical(fmp: FMP) -> None:
df = await fmp.prices("BTCUSD", fmp.freq.one_hour)
assert df["close"] is not None


@pytest.mark.skipif(skip_fmp, reason="No FMP API key found")
async def test_dividends(fmp: FMP) -> None:
data = await fmp.dividends()
assert data is not None


@skip_network_issue
async def test_fed_yc() -> None:
try:
async with FederalReserve() as fed:
df = await fed.yield_curves()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 12
except (ConnectionError, ClientError) as e:
pytest.skip(f"Skipping test_fed due to network issue: {e}")
async with FederalReserve() as fed:
df = await fed.yield_curves()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 12


@skip_network_issue
async def test_fed_rates() -> None:
try:
async with FederalReserve() as fed:
df = await fed.ref_rates()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 2
except (ConnectionError, ClientError) as e:
pytest.skip(f"Skipping test_fed due to network issue: {e}")
async with FederalReserve() as fed:
df = await fed.ref_rates()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 2


@skip_network_issue
async def __test_fiscal_data() -> None:
try:
async with FiscalData() as fd:
df = await fd.securities()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 2
except (ConnectionError, ClientError) as e:
pytest.skip(f"Skipping test_fed due to network issue: {e}")
async with FiscalData() as fd:
df = await fd.securities()
assert df is not None
assert df.shape[0] > 0
assert df.shape[1] == 2
14 changes: 14 additions & 0 deletions quantflow_tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import cast

import numpy as np
import pytest
from aiohttp.client_exceptions import ClientError

from quantflow.sp.base import StochasticProcess1D
from quantflow.utils.marginal import Marginal1D
Expand Down Expand Up @@ -30,3 +32,15 @@ def analytical_tests(pr: StochasticProcess1D, tol: float = 1e-3):
np.testing.assert_allclose(m.mean(), m.mean_from_characteristic(), tol)
np.testing.assert_allclose(m.std(), m.std_from_characteristic(), tol)
np.testing.assert_allclose(m.variance(), m.variance_from_characteristic(), tol)


def skip_network_issue(func):
"""Decorator to skip tests in case of network issues."""

async def wrapper(*args, **kwargs):
try:
await func(*args, **kwargs)
except (ConnectionError, ClientError) as e:
pytest.skip(f"Skipping {func.__name__} due to network issue: {e}")

return wrapper