{"id":49367147,"url":"https://github.com/alepot55/atlas-mm","last_synced_at":"2026-04-27T20:02:12.839Z","repository":{"id":338404417,"uuid":"1157502629","full_name":"alepot55/atlas-mm","owner":"alepot55","description":"GPU-Accelerated Limit Order Book Simulator with Formally Verified Market Making","archived":false,"fork":false,"pushed_at":"2026-02-14T09:01:15.000Z","size":761,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-14T17:09:16.026Z","etag":null,"topics":["avellaneda-stoikov","formal-verification","gymnasium","market-making","order-book","ppo","python","quantitative-finance","reinforcement-learning","z3-solver"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alepot55.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T22:27:55.000Z","updated_at":"2026-02-14T09:02:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alepot55/atlas-mm","commit_stats":null,"previous_names":["alepot55/atlas-mm"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/alepot55/atlas-mm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alepot55%2Fatlas-mm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alepot55%2Fatlas-mm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alepot55%2Fatlas-mm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alepot55%2Fatlas-mm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alepot55","download_url":"https://codeload.github.com/alepot55/atlas-mm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alepot55%2Fatlas-mm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32352406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T17:12:42.749Z","status":"ssl_error","status_checked_at":"2026-04-27T17:12:41.658Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["avellaneda-stoikov","formal-verification","gymnasium","market-making","order-book","ppo","python","quantitative-finance","reinforcement-learning","z3-solver"],"created_at":"2026-04-27T20:02:10.741Z","updated_at":"2026-04-27T20:02:12.806Z","avatar_url":"https://github.com/alepot55.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# atlas-mm\n\n**Limit Order Book Simulator with Formally Verified Market Making**\n\n![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue)\n![Z3 Verified](https://img.shields.io/badge/Z3-Formally%20Verified-green)\n![License: MIT](https://img.shields.io/badge/License-MIT-yellow)\n![Tests](https://img.shields.io/badge/Tests-85%20passed-brightgreen)\n\n---\n\n## The Problem\n\nMarket makers continuously quote bid and ask prices, profiting from the spread while managing **inventory risk** (adverse price moves on accumulated positions) and **adverse selection** (informed traders picking off stale quotes). Optimal market making requires balancing tighter spreads (more fills, more revenue) against wider spreads (less adverse selection risk) while dynamically adjusting for inventory and volatility.\n\n## The Approach\n\n**atlas-mm** tackles this with three components:\n\n1. **Limit Order Book Engine** -- A from-scratch L2 order book with price-time priority matching, supporting limit orders, market orders, and cancellations. Pure Python throughput: **~134K orders/sec**.\n2. **Avellaneda-Stoikov vs RL Comparison** -- The analytical optimal market making model (Avellaneda \u0026 Stoikov, 2008) as a baseline, compared against a PPO-based reinforcement learning agent trained for 500K timesteps in a Gymnasium environment with GARCH(1,1) price dynamics.\n3. **Z3 Formal Verification** -- Mathematical proofs (not just tests) that critical invariants hold for *all* possible inputs: no crossed book, positive spreads, inventory mean-reversion, and price-time priority.\n\n## Results\n\n### Performance Comparison (5,000 steps, seed=42)\n\n| Metric | Avellaneda-Stoikov | RL Agent (PPO) |\n|---|---|---|\n| Total PnL | -1.69 | -19.23 |\n| Sharpe Ratio | -25.03 | -441.61 |\n| Max Drawdown | 2.99 | 19.23 |\n| Inventory Std | 7.19 | 22.40 |\n| Total Fills | 284 | 1,424 |\n| Fill Rate | 5.68% | 28.48% |\n| Mean Spread | 0.0324 | 0.0514 |\n| PnL/Trade | -0.0060 | -0.0135 |\n\nThe A-S agent demonstrates superior risk management across all metrics. The RL agent trained with PPO (500K timesteps) learns a non-trivial policy -- it controls inventory better than a random baseline (std 22.40 vs 40.97 for random) and quotes adaptive spreads -- but does not outperform the analytical optimum. This is expected: A-S computes the closed-form solution under its model assumptions, while PPO must discover the strategy from noisy reward signals dominated by stochastic price moves (explained variance ~0 throughout training). A structured reward decomposition separating spread capture from inventory mark-to-market would likely close the gap.\n\n### Cumulative PnL\n\n![PnL Comparison](assets/pnl_comparison.png)\n\n### Inventory Distribution\n\n![Inventory Distribution](assets/inventory_distribution.png)\n\n### Spread Dynamics vs Volatility\n\n![Spread Dynamics](assets/spread_dynamics.png)\n\n### Metrics Comparison\n\n![Metrics Comparison](assets/metrics_comparison.png)\n\n### Formal Verification\n\n| Property | Status | Time |\n|---|---|---|\n| No crossed book | PROVED | 2.2ms |\n| A-S spread always positive | PROVED | 5.7ms |\n| A-S inventory mean-reversion | PROVED | 2.1ms |\n| Price-time priority | PROVED | 0.4ms |\n\nAll 4 properties verified for **all possible inputs** using the Z3 SMT solver.\n\n### Engine Benchmark\n\n| Metric | Value |\n|---|---|\n| Throughput | 134K orders/sec |\n| Orders processed | 100,000 |\n| Fill ratio | 50.1% |\n\n\u003e Pure Python implementation. Bottleneck: dict lookup for price levels and linear scan for sorted insertion. A Cython/CUDA implementation would target \u003e10M orders/sec with parallel price-level matching on GPU ([#2](https://github.com/alepot55/atlas-mm/issues/2)).\n\n## Architecture\n\n```\natlas-mm/\n├── src/atlas_mm/\n│   ├── engine/              # Order book + matching engine\n│   │   ├── orders.py        # Order/Fill/Cancel dataclasses\n│   │   ├── orderbook.py     # L2 book with price-time priority\n│   │   └── matching.py      # Engine orchestrator\n│   ├── simulation/          # Market simulation\n│   │   ├── price_process.py # GBM + GARCH(1,1) price dynamics\n│   │   ├── flow_generator.py# Poisson order flow generation\n│   │   ├── environment.py   # Gymnasium RL environment\n│   │   └── agents_zoo.py    # Background agents (noise, momentum, mean-rev)\n│   ├── agents/              # Market making strategies\n│   │   ├── base.py          # Abstract agent interface\n│   │   ├── avellaneda_stoikov.py  # Analytical optimal MM\n│   │   └── rl_agent.py      # PPO-based RL agent\n│   ├── verification/        # Formal verification\n│   │   └── properties.py    # Z3 proofs of book invariants\n│   └── evaluation/          # Performance analysis\n│       ├── metrics.py       # PnL, Sharpe, drawdown, fill rate\n│       └── visualization.py # Publication-quality plots\n├── scripts/\n│   ├── run_simulation.py    # Main entry point\n│   ├── train_rl.py          # RL training with SB3\n│   ├── run_verification.py  # Z3 verification runner\n│   └── benchmark_engine.py  # Engine throughput benchmark\n└── tests/                   # 85 tests across all modules\n```\n\n## Quick Start\n\n### Installation\n\n```bash\ngit clone https://github.com/alepot55/atlas-mm.git\ncd atlas-mm\npip install -e \".[dev]\"\n```\n\n### Run Simulation\n\n```bash\npython scripts/run_simulation.py\n```\n\nGenerates 4 plots in `assets/` and prints a metrics comparison table. If a trained model exists at `models/ppo_mm.zip`, the RL agent uses it; otherwise falls back to a random policy.\n\n### Run Formal Verification\n\n```bash\npython scripts/run_verification.py\n```\n\n### Run Tests\n\n```bash\npytest -v\n```\n\n### Train RL Agent (requires PyTorch)\n\n```bash\npip install -e \".[rl]\"\npython scripts/train_rl.py --timesteps 500000\n```\n\n### Benchmark Matching Engine\n\n```bash\npython scripts/benchmark_engine.py\n```\n\n## How It Works\n\n### Avellaneda-Stoikov Model\n\nThe A-S model computes a **reservation price** and **optimal spread** analytically:\n\n```\nreservation_price = s - q * gamma * sigma^2 * tau\noptimal_spread = gamma * sigma^2 * tau + (2/gamma) * ln(1 + gamma/kappa)\n```\n\nWhere `s` is mid-price, `q` is inventory, `gamma` is risk aversion, `sigma` is volatility, `tau` is time remaining, and `kappa` is order arrival intensity.\n\n**Key insight:** The reservation price shifts *away* from mid when inventory is non-zero. A long position (q \u003e 0) lowers the reservation price, making the ask more attractive and encouraging inventory reduction.\n\n### RL Formulation\n\nThe RL agent uses PPO with:\n- **State:** inventory, volatility, spread, time remaining, order imbalance, PnL (6 features)\n- **Action:** discrete spread level (1-5 ticks) and skew level (-2 to +2 ticks)\n- **Reward:** `step_pnl - lambda * inventory^2` with terminal inventory penalty\n\n### Formal Verification\n\nZ3 SMT solver proves properties hold for *all* parameter combinations, not just tested cases:\n- **No crossed book:** After any matching operation, best_bid \u003c best_ask\n- **Positive spread:** A-S spread formula is strictly positive for all valid parameters\n- **Mean reversion:** Reservation price always pushes quotes toward inventory reduction\n- **Price priority:** Better-priced orders always fill first\n\n## References\n\n1. Avellaneda, M., \u0026 Stoikov, S. (2008). *High-frequency trading in a limit order book.* Quantitative Finance, 8(3), 217-224.\n2. Gueant, O., Lehalle, C. A., \u0026 Fernandez-Tapia, J. (2013). *Dealing with the inventory risk: a solution to the market making problem.* Mathematics and Financial Economics, 7(4), 477-507.\n3. Spooner, T., Fearnley, J., Savani, R., \u0026 Koukorinis, A. (2018). *Market making via reinforcement learning.* AAMAS 2018.\n\n## License\n\nMIT\n\n## Author\n\nAlessandro Potenza ([ap.alessandro.potenza@gmail.com](mailto:ap.alessandro.potenza@gmail.com))\n\n## Citation\n\n```bibtex\n@software{potenza2025atlasmm,\n  author = {Potenza, Alessandro},\n  title = {atlas-mm: LOB Simulator with Formally Verified Market Making},\n  year = {2025},\n  url = {https://github.com/alepot55/atlas-mm}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falepot55%2Fatlas-mm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falepot55%2Fatlas-mm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falepot55%2Fatlas-mm/lists"}