Skip to content

Commit ac06843

Browse files
committed
Better distribution api
1 parent 2d3b9d5 commit ac06843

49 files changed

Lines changed: 378 additions & 148 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ permissions:
1616
jobs:
1717
release:
1818
runs-on: ubuntu-latest
19+
services:
20+
redis:
21+
image: redis:7
22+
ports:
23+
- 6379:6379
24+
options: >-
25+
--health-cmd "redis-cli ping"
26+
--health-interval 10s
27+
--health-timeout 5s
28+
--health-retries 5
1929
env:
2030
PYTHON_ENV: ci
2131
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ app-serve: ## serve app
1313
docs: ## build documentation
1414
@cp docs/index.md readme.md
1515
@uv run ./dev/build-examples
16-
@uv run mkdocs build
16+
@uv run mkdocs build --strict
1717

1818
.PHONY: docs-bib
1919
docs-bib: ## Regenerate docs bibliography

app/api/deps.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import io
22
import json
3+
import logging
4+
import os
35
from collections.abc import Awaitable, Callable
4-
from dataclasses import dataclass
6+
from dataclasses import dataclass, field
57
from typing import Annotated, Generic, TypeVar, cast
68

79
import pandas as pd
810
from fastapi import Depends, FastAPI, Request
9-
from fluid.utils import log
1011
from fluid.utils.redis import FluidRedis
1112
from pydantic import BaseModel
1213
from redis.asyncio import Redis
1314

1415
from quantflow.data.fmp import FMP
1516

1617
M = TypeVar("M", bound=BaseModel)
17-
logger = log.get_logger(__name__)
18+
logger = logging.getLogger(__name__)
1819

1920

2021
def instrument_app(app: FastAPI) -> None:
@@ -44,7 +45,17 @@ class RedisCache(Generic[M]):
4445
redis: Redis
4546
Model: type[M]
4647
key: str
47-
ttl: int = 60
48+
prefix: str = field(
49+
default_factory=lambda: os.getenv(
50+
"QUANTFLOW_REDIS_CACHE_PREFIX", "quantflow:cache"
51+
)
52+
)
53+
ttl: int = field(
54+
default_factory=lambda: int(os.getenv("QUANTFLOW_REDIS_CACHE_TTL", "60"))
55+
)
56+
57+
def __post_init__(self) -> None:
58+
self.key = f"{self.prefix}:{self.key}"
4859

4960
async def from_cache(self, loader: Callable[[], Awaitable[M]]) -> M:
5061
"""Get a value from the cache"""
@@ -53,7 +64,7 @@ async def from_cache(self, loader: Callable[[], Awaitable[M]]) -> M:
5364
return await self.set_cache(await loader())
5465
try:
5566
return self.Model.model_validate_json(value)
56-
except json.JSONDecodeError:
67+
except json.JSONDecodeError: # pragma: no cover
5768
logger.exception(f"Failed to decode cache value for key {self.key}")
5869
return await self.set_cache(await loader())
5970

@@ -63,6 +74,15 @@ async def set_cache(self, value: M) -> M:
6374
await self.redis.set(self.key, payload, ex=self.ttl)
6475
return value
6576

77+
@classmethod
78+
async def clear(cls, redis: Redis) -> int:
79+
"""Delete all cache entries under the prefix"""
80+
cache = cls(redis=redis, Model=BaseModel, key="*")
81+
keys = [key async for key in cache.redis.scan_iter(f"{cache.prefix}:*")]
82+
if not keys:
83+
return 0
84+
return await cache.redis.delete(*keys)
85+
6686

6787
@dataclass
6888
class RedisDataframe:

app/api/heston.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from pydantic import BaseModel, Field
44

55
from app.api.docs import load_description
6+
from quantflow.dists.distributions1d import DoubleExponential
67
from quantflow.options.pricer import OptionPricer
78
from quantflow.sp.heston import HestonJ
89
from quantflow.sp.jump_diffusion import JumpDiffusion
9-
from quantflow.utils.distributions import DoubleExponential
1010

1111
heston_router = APIRouter()
1212

app/api/sampling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
from scipy.stats import chisquare, ks_1samp
55

66
from app.api.docs import load_description
7+
from quantflow.dists.distributions1d import DoubleExponential
78
from quantflow.sp.ou import Vasicek
89
from quantflow.sp.poisson import PoissonProcess
910
from quantflow.ta.paths import Paths
1011
from quantflow.utils import bins
11-
from quantflow.utils.distributions import DoubleExponential
1212

1313
sampling_router = APIRouter()
1414

app/scripts/heston_divfm_fit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from quantflow.options.divfm.trainer import DayData, DIVFMTrainer
2121
from quantflow.options.pricer import OptionPricer
2222
from quantflow.sp.heston import HestonJ
23-
from quantflow.utils.distributions import DoubleExponential
23+
from quantflow.dists.distributions1d import DoubleExponential
2424

2525
# ---------------------------------------------------------------------------
2626
# Grid settings

docs/api/dists/distributions.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Distributions
2+
3+
::: quantflow.dists.Distribution
4+
5+
::: quantflow.dists.MvDistribution
6+
7+
::: quantflow.dists.MeanAndCov
8+
9+
::: quantflow.dists.MvNormal

docs/api/dists/distributions1d.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# 1D Distributions
2+
3+
::: quantflow.dists.Distribution1D
4+
5+
::: quantflow.dists.Normal
6+
7+
::: quantflow.dists.Exponential
8+
9+
::: quantflow.dists.DoubleExponential

docs/api/dists/index.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
# Distributions
22

3-
Probability distributions with a uniform `sample` / `log_pdf` API, used as
4-
return types of the
5-
[StateSpaceModel](../ta/kalman.md#quantflow.ta.kalman.StateSpaceModel)
6-
distribution-level interface.
3+
The `dists` module collects the probability distributions used across quantflow,
4+
both standalone parametric laws and the marginal distributions implied by a
5+
stochastic process at a fixed time horizon.
76

8-
::: quantflow.dists.MeanAndCov
9-
10-
::: quantflow.dists.Distribution
11-
12-
::: quantflow.dists.MvNormal
7+
Every distribution derives from
8+
[Distribution][quantflow.dists.Distribution], which exposes a common
9+
[sample][quantflow.dists.Distribution.sample] method for drawing random variates.

docs/api/dists/marginal1d.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Marginal 1D
2+
3+
::: quantflow.dists.OptionPricingMethod
4+
5+
::: quantflow.dists.OptionPricingResult
6+
7+
::: quantflow.dists.OptionPricingCosResult
8+
9+
::: quantflow.dists.Marginal1D

0 commit comments

Comments
 (0)