Skip to content

Commit 38c2571

Browse files
committed
wiring deployment
1 parent eb5656f commit 38c2571

File tree

15 files changed

+799
-1387
lines changed

15 files changed

+799
-1387
lines changed

.dockerignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
dist/
2+
build/
3+
4+
__marimo__
5+
__pycache__
6+
*.pyc
7+
*.pyo
8+
*.pyd
9+
.data
10+
.env
11+
.venv
12+
.mypy_cache
13+
.ruff_cache
14+
.pytest_cache
15+
.codebuild
16+
.gihub

.github/workflows/build.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,17 @@ jobs:
5151
- name: publish
5252
if: ${{ matrix.python-version == '3.13' && github.event.head_commit.message == 'release' }}
5353
run: make publish
54+
55+
deploy:
56+
runs-on: ubuntu-latest
57+
needs:
58+
- build
59+
env:
60+
PYTHON_ENV: ci
61+
FMP_API_KEY: ${{ secrets.FMP_API_KEY }}
62+
63+
steps:
64+
- name: Checkout repo
65+
uses: actions/checkout@v4
66+
- name: install rops
67+
run: curl -L https://raw.githubusercontent.com/quantmind/rops/main/dev/install-rops | bash

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ dist
3434
*.ipynb
3535
.ipynb_checkpoints
3636
_build
37+
38+
# builds
39+
app/docs

app/__main__.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
from typing import Annotated, Callable, Coroutine
2-
from fastapi.responses import HTMLResponse, RedirectResponse
31
import marimo
4-
from fastapi import FastAPI, Form, Request, Response
2+
from fastapi.staticfiles import StaticFiles
3+
from fastapi import FastAPI
4+
from pathlib import Path
5+
6+
APP_PATH = Path(__file__).parent
57

68

79
def crate_app() -> FastAPI:
810
# Create a marimo asgi app
9-
server = (
10-
marimo.create_asgi_app()
11-
.with_app(path="/supersmoother", root="./app/supersmoother.py")
12-
)
11+
server = marimo.create_asgi_app()
12+
for path in APP_PATH.glob("*.py"):
13+
if path.name.startswith("_"):
14+
continue
15+
dashed = path.stem.replace("_", "-")
16+
server = server.with_app(path=f"/{dashed}", root=f"./app/{path.name}")
1317
# Create a FastAPI app
1418
app = FastAPI()
15-
app.mount("/", server.build())
19+
app.mount("/examples", server.build())
20+
app.mount("/", StaticFiles(directory=APP_PATH / "docs", html=True), name="static")
1621
return app
1722

1823
# Run the server
1924
if __name__ == "__main__":
2025
import uvicorn
21-
uvicorn.run(crate_app(), host="localhost", port=8001)
26+
uvicorn.run(crate_app(), host="0.0.0.0", port=8001)

app/gaussian_sampling.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import marimo
2+
3+
__generated_with = "0.19.7"
4+
app = marimo.App(width="medium")
5+
6+
7+
@app.cell
8+
def _():
9+
import marimo as mo
10+
from app.utils import nav_menu
11+
12+
nav_menu()
13+
return (mo,)
14+
15+
16+
@app.cell
17+
def _(mo):
18+
mo.md(r"""
19+
# Gaussian Sampling
20+
21+
Here we sample the gaussian OU process for different mean reversion speed and number of paths.
22+
""")
23+
return
24+
25+
26+
@app.cell
27+
def _(mo):
28+
import inspect
29+
from quantflow.sp.ou import Vasicek
30+
import pandas as pd
31+
32+
def simulate_vasicek(kappa: float, samples: int) -> pd.DataFrame:
33+
pr = Vasicek(rate=0.5, kappa=kappa)
34+
paths = pr.sample(samples, 1, 1000)
35+
pdf = paths.pdf(num_bins=50)
36+
pdf["simulation"] = pdf["pdf"]
37+
pdf["analytical"] = pr.marginal(1).pdf(pdf.index)
38+
return pdf
39+
40+
# 1. Get the source code of your function
41+
# Note: The function must be defined in a previous cell or imported
42+
try:
43+
source_code = inspect.getsource(simulate_vasicek)
44+
except OSError:
45+
source_code = "# Code not available (source file not found)"
46+
47+
# 2. Display it inside an accordion so it doesn't clutter the view
48+
mo.accordion({
49+
"Show Simulation Code": mo.md(f"```python\n{source_code}\n```")
50+
})
51+
return (simulate_vasicek,)
52+
53+
54+
@app.cell
55+
def _(mo):
56+
samples = mo.ui.slider(start=100, stop=10000, step=100, value=1000, debounce=True, full_width=True)
57+
kappa = mo.ui.slider(start=0.1, stop=5, step=0.1, debounce=True, full_width=True)
58+
59+
def input_label(text):
60+
return mo.Html(f"<span style='width: 250px; display: inline-block; font-weight: 500;'>{text}</span>")
61+
62+
controls = mo.vstack([
63+
mo.hstack([input_label("Samples:"), samples], align="center"),
64+
mo.hstack([input_label("Kappa (Mean reversion):"), kappa], align="center")
65+
])
66+
controls
67+
return kappa, samples
68+
69+
70+
@app.cell
71+
def _(kappa, samples, simulate_vasicek):
72+
df = simulate_vasicek(kappa=kappa.value, samples=samples.value)
73+
return (df,)
74+
75+
76+
@app.cell
77+
def _(df):
78+
import plotly.graph_objects as go
79+
simulation = go.Bar(x=df.index, y=df["simulation"], name="simulation")
80+
analytical = go.Scatter(x=df.index, y=df["analytical"], name="analytical")
81+
fig = go.Figure(data=[simulation, analytical])
82+
fig
83+
return
84+
85+
86+
@app.cell
87+
def _():
88+
return
89+
90+
91+
if __name__ == "__main__":
92+
app.run()

app/supersmoother.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ def _(mo):
1515
@app.cell
1616
def _():
1717
import marimo as mo
18-
19-
app = mo.App(
20-
requirements=["quantflow"]
21-
)
2218
return (mo,)
2319

2420

@@ -55,11 +51,15 @@ def _(mo):
5551
def _(data, period):
5652
from quantflow.ta.supersmoother import SuperSmoother
5753
from quantflow.ta.ewma import EWMA
54+
# create the filters
5855
smoother = SuperSmoother(period=period.value)
5956
ewma = EWMA(period=period.value)
60-
sm = data[["date", "close"]].copy()
61-
sm["supersmoother"] = data["close"].apply(smoother.update)
62-
sm["ewma"] = data["close"].apply(ewma.update)
57+
ewma_min = EWMA(period=period.value, tau=0.5)
58+
# sort dates ascending
59+
sm = data[["date", "close"]].copy().sort_values("date", ascending=True).reset_index(drop=True)
60+
sm["supersmoother"] = sm["close"].apply(smoother.update)
61+
sm["ewma"] = sm["close"].apply(ewma.update)
62+
sm["ewma_min"] = sm["close"].apply(ewma_min.update)
6363
return (sm,)
6464

6565

@@ -68,7 +68,7 @@ def _(alt, sm):
6868
# Melt the dataframe to a long format suitable for Altair
6969
sm_long = sm.melt(
7070
id_vars=['date'],
71-
value_vars=['close', 'supersmoother', "ewma"],
71+
value_vars=['close', 'supersmoother', "ewma", "ewma_min"],
7272
var_name='Signal',
7373
value_name='Price'
7474
)
@@ -79,8 +79,8 @@ def _(alt, sm):
7979
y=alt.Y('Price:Q', title='Price (USD)', scale=alt.Scale(zero=False)),
8080
color=alt.Color('Signal:N', title='Signal',
8181
scale=alt.Scale(
82-
domain=['close', 'supersmoother', 'ewma'],
83-
range=['#4c78a8', '#f58518', '#e45756']) # Vega-Lite default palette
82+
domain=['close', 'supersmoother', 'ewma', "ewma_min"],
83+
range=['#4c78a8', '#f58518', '#e45756', '#e45756']) # Vega-Lite default palette
8484
),
8585
tooltip=[
8686
alt.Tooltip('date:T', title='Date'),

app/utils/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import marimo as mo
2+
3+
def nav_menu():
4+
return mo.nav_menu(
5+
{
6+
"/": "Quantflow",
7+
"/api": "API Reference",
8+
}
9+
)

docs/api/sp/cir.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
================
2-
CIR
3-
================
1+
# CIR
42

53
The Cox–Ingersoll–Ross (CIR) model
64

7-
.. currentmodule:: quantflow.sp.cir
8-
9-
.. autoclass:: CIR
10-
:members:
11-
:member-order: groupwise
12-
:autosummary:
13-
:autosummary-nosignatures:
14-
5+
::: quantflow.sp.cir.CIR

docs/api/sp/compound_poisson.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
===================
2-
Compound Poisson
3-
===================
4-
5-
.. currentmodule:: quantflow.sp.poisson
6-
7-
.. autoclass:: CompoundPoissonProcess
8-
:members:
9-
:member-order: groupwise
10-
:autosummary:
11-
:autosummary-nosignatures:
1+
# Compound Poisson
122

3+
::: quantflow.sp.poisson.CompoundPoissonProcess

docs/api/sp/ou.md

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
1-
================
2-
OU Processes
3-
================
1+
# OU Processes
42

53
These are the classes that implement gaussian and non-gaussian
6-
`Ornstein-Uhlenbeck <https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process>`_ process.
4+
[Ornstein-Uhlenbeck](https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process) process.
75

86

9-
.. currentmodule:: quantflow.sp.ou
7+
## Gaussian OU process
108

11-
.. autoclass:: Vasicek
12-
:members:
13-
:member-order: groupwise
14-
:autosummary:
15-
:autosummary-nosignatures:
9+
::: quantflow.sp.ou.Vasicek
1610

11+
## Non-Gaussian OU process
1712

18-
.. autoclass:: GammaOU
19-
:members:
20-
:member-order: groupwise
21-
:autosummary:
22-
:autosummary-nosignatures:
13+
::: quantflow.sp.ou.GammaOU

0 commit comments

Comments
 (0)