Touched up notebooks + webapp

This commit is contained in:
2026-07-31 17:05:14 -04:00
commit 8e6c98945b
31 changed files with 10824 additions and 0 deletions
+195
View File
@@ -0,0 +1,195 @@
# Adaptive Barrier Monitor
A five-notebook quantitative-finance project connecting random walks, Brownian
motion, geometric Brownian motion, first-passage times, Brownian bridges, and
state-dependent monitoring.
The motivating question is:
> A stock is monitored for a large move over a short window. Continuous polling
> is expensive. What probability model describes a hidden barrier crossing, and
> how can that model inform a sampling schedule?
The project is written for a mathematically mature reader who wants to see how
Gaussian processes, conditioning, stochastic calculus, and Monte Carlo methods
appear in a practical monitoring problem.
## Core results and scope
Under geometric Brownian motion,
$$
\frac{dS_t}{S_t}=\mu\,dt+\sigma\,dW_t,
$$
the relative log-price $X_t=\log(S_t/S_0)$ is arithmetic Brownian motion. A
10% drop corresponds to the lower log barrier $B=\log(0.9)$.
For zero drift, the probability of touching the barrier by time $T$ is
$$
P(\tau_B\leq T)=2\Phi\!\left(\frac{B}{\sigma\sqrt{T}}\right).
$$
At 30% annualised volatility, a 10% move in five trading minutes is roughly a
49-standard-deviation diffusion event. Pure GBM therefore assigns it probability
below ordinary floating-point resolution; jumps and market microstructure are
essential for realistic extreme-move modelling.
Conditional on two observations $x_0,x_T>B$, the Brownian-bridge probability
that the hidden path crossed the barrier is
$$
P_{\mathrm{cross}}
=\exp\!\left(
-\frac{2(x_0-B)(x_T-B)}{\sigma^2\Delta t}
\right).
$$
If both endpoint distances are set equal to $D$, inversion gives
$$
\Delta t_{\mathrm{sym}}
=\frac{2D^2}{\sigma^2\log(1/\varepsilon)}.
$$
This inversion is exact **conditional on both endpoints being known**. In a
live scheduler, the future endpoint is unknown; the implementation substitutes
the current distance for both endpoints. Thus $\varepsilon$ is a local
diffusion-design parameter, not an unconditional miss guarantee, and it does
not control jumps. A hard maximum polling interval remains necessary.
## Notebooks
| # | Notebook | Main topics |
|---|---|---|
| 01 | [Random walks to Brownian motion](notebooks/01_random_walks_to_brownian_motion.ipynb) | Log returns, the $\min(s,t)$ covariance kernel, Cholesky sampling, Brownian scaling |
| 02 | [GBM and Itô's lemma](notebooks/02_geometric_brownian_motion_and_ito.ipynb) | Multiplicative prices, exact GBM simulation, Itô correction |
| 03 | [First passage and reflection](notebooks/03_first_passage_and_reflection_principle.ipynb) | Reflection principle, BachelierLévy formula, hitting-time diagnostics |
| 04 | [Brownian bridges and hidden crossings](notebooks/04_brownian_bridges_and_miss_probability.ipynb) | Gaussian conditioning, Schur complements, bridge crossing probabilities |
| 05 | [Adaptive barrier monitoring](notebooks/05_adaptive_barrier_monitor.ipynb) | Unit-consistent scheduler, practical polling cap, controlled jump stress test, model-risk discussion |
The analytical formulae are checked against Monte Carlo simulation in the
notebooks.
## Interactive web application
The FastAPI/Plotly demo compares two sampling schedules on the **same simulated
paths**. The adaptive schedule uses the local symmetric-endpoint bridge proxy,
while the fixed baseline can run in either of two modes:
- **Equal budget:** the fixed schedule receives exactly the adaptive schedule's
sample count on each path, isolating where observations are placed.
- **Fixed cadence:** the fixed schedule samples at a user-selected interval, so
detection quality, lag, and total observation cost can be compared directly.
A barrier event counts as detected only if a sampled point remains beyond the
barrier within a configurable number of simulation steps. The comparison is
therefore explicit and reproducible rather than based on an unrestricted
"eventually detected" definition.
The demo supports GBM and an optional Merton jump-diffusion stress mode. When
jumps are enabled, the interface explicitly warns that the Brownian diffusion
parameter $\varepsilon$ does not bound jump-event misses.
### Run locally
```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[webapp]"
python -m uvicorn webapp.app:app --host 127.0.0.1 --port 8055
```
Open `http://127.0.0.1:8055`.
### Docker
```bash
docker compose -f docker-compose.webapp.yml up --build
```
For an existing Caddy Docker network:
```bash
docker compose -f docker-compose.webapp.proxy.yml up --build -d
```
The container runs as a non-root user and includes an HTTP health check.
## Run the notebooks
```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[notebooks]"
jupyter lab notebooks/
```
Notebooks that request market data cache successful downloads under
`data/cache/`. Their analytical and simulation sections remain usable when the
network fetch is unavailable.
## Tests
```bash
pip install -e ".[dev,webapp]"
pytest
```
The test suite covers:
- inversion of the Brownian-bridge formula;
- vectorised interval calculations and input validation;
- consistent time/volatility units in the adaptive schedule;
- enforcement of the detection deadline;
- exact per-path sample-budget equality;
- equivalence of zero-intensity jump diffusion and GBM;
- aggregate simulation invariants.
## Project structure
```text
adaptive-barrier-monitor/
├── notebooks/ # five executed research notebooks
├── src/adaptive_barrier/
│ ├── __init__.py
│ └── engine.py # samplers, closed forms, scheduler, evaluation
├── tests/
│ └── test_engine.py
├── webapp/
│ ├── app.py # FastAPI API
│ ├── Dockerfile
│ └── static/ # vanilla JS, Plotly, CSS
├── .github/workflows/tests.yml
├── pyproject.toml
├── requirements.txt
├── requirements-webapp.txt
├── requirements-dev.txt
├── bibliography.md
├── LICENSE
└── webapp.md
```
## Model limitations
- **Online endpoint uncertainty:** the bridge crossing formula is conditional on
both endpoints; the scheduler uses a local approximation before the next
endpoint exists.
- **Jump risk:** diffusion-derived polling cannot guarantee detection of sudden
jump-and-recovery events.
- **No market microstructure model:** bidask bounce, asynchronous feeds,
exchange halts, queueing, and packet latency are not represented.
- **Simulation-grid dependence:** the web demo's detection deadline is measured
in simulated grid steps; changing `n_steps` changes its physical duration.
- **Educational calibration:** jump parameters in the sandbox are user-controlled
stress parameters, not production estimates.
## Tech stack
Python, NumPy, SciPy, pandas, SymPy, Matplotlib, FastAPI, Pydantic, Uvicorn,
Plotly.js, Docker, pytest, and GitHub Actions.
## License
MIT — see [`LICENSE`](LICENSE).