Skip to content

Phase 0: Project Scaffold

Status: ✅ Complete
Duration: ~2 hours
Date: February 24, 2026


Objectives

Phase 0 established the complete project infrastructure before any business logic implementation:

  1. ✅ Git repository initialization
  2. ✅ Python environment with uv
  3. ✅ Full directory scaffold with module stubs
  4. ✅ Configuration system (TOML + Doppler secrets)
  5. ✅ Dev tooling (ruff, pre-commit, pytest)
  6. ✅ CI/CD pipelines (GitHub Actions)
  7. ✅ Deployment configuration (Heroku)
  8. ✅ Documentation scaffold (MkDocs)
  9. ✅ Initial commit and remote push

Deliverables

Repository Structure

quant-portfolio-monitor/
├── .devcontainer/          # GitHub Codespaces config
├── .github/workflows/      # CI/CD pipelines
├── bin/                    # Heroku post-compile hook
├── docs/                   # MkDocs documentation
├── quant_monitor/          # Main package
│   ├── agent/              # Fusion, optimizer, risk, alerts
│   ├── backtest/           # Walk-forward engine
│   ├── dashboard/          # Streamlit app
│   ├── data/               # Pipeline, cache, sources
│   ├── features/           # MA, volatility, sentiment
│   ├── models/             # Tech, fund, sentiment, macro
│   └── spiders/            # Scrapy spiders for Zyte
├── scripts/                # Utility scripts
├── tests/                  # pytest test suite
├── pyproject.toml          # uv project config
├── uv.lock                 # Dependency lockfile
├── Procfile                # Heroku process definitions
├── doppler.yaml            # Doppler project config
└── README.md               # Project overview

Dependencies Installed

188 packages resolved in uv.lock, including:

Category Packages
Data Sources alpaca-py, requests, feedparser
Database duckdb, diskcache
NLP/ML transformers, sentence-transformers, torch
Portfolio pyportfolioopt
Data Processing pandas, numpy, scipy
Dashboard streamlit, plotly, matplotlib
Scheduling apscheduler
Alerts python-telegram-bot
Backend appwrite
Scraping scrapy
Dev Tools pytest, ruff, mypy, pre-commit, mkdocs-material

Configuration

config.toml contains all non-secret configuration: - 15 portfolio holdings with qty, price_paid, sector - Cache TTL values per data type - Regime-weighted fusion weights (5 regimes × 4 models) - Risk parameters per macro regime - Signal thresholds (confidence, drift, kill switch) - Moving average periods - Volatility classifier parameters - Sentiment model config - Macro model thresholds

Doppler manages secrets: - ALPACA_API_KEY / ALPACA_SECRET_KEY - FRED_API_KEY - TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID - APPWRITE_ENDPOINT / APPWRITE_PROJECT_ID / APPWRITE_API_KEY - ZYTE_API_KEY - SEC_EDGAR_USER_AGENT

Module Stubs

Every module has a stub with: - Docstring explaining purpose - Class/function signatures - # TODO Phase N markers - Type hints for all parameters/returns

Example from quant_monitor/agent/fusion.py:

class SignalFusion:
    """Fuses 4 model signals with dynamic regime-dependent weights."""

    def fuse(
        self,
        technical: float,
        fundamental: float,
        sentiment: float,
        macro: float,
        regime: str,
    ) -> dict:
        """Compute fused signal for a single ticker.

        Returns:
            dict with keys: fused_score, confidence, action, dominant_model
        """
        # TODO Phase 6
        raise NotImplementedError

Tests

6 tests passing:

Test Purpose
test_config_toml_exists Verify config.toml is present and parseable
test_config_loader Verify config.py loads TOML + env vars
test_all_holdings_have_required_fields Validate all 15 holdings have required fields
test_pipeline_placeholder Placeholder for Phase 1
test_moving_averages_placeholder Placeholder for Phase 2
test_technical_model_placeholder Placeholder for Phase 3

CI/CD

ci.yml: - Triggers on push/PR to main - Installs uv, syncs deps - Runs ruff check + format check - Runs mypy (non-blocking) - Runs pytest

deploy.yml: - Triggers on push to main - Generates requirements.txt from uv - Deploys to Heroku via action - Builds and deploys MkDocs to GitHub Pages

Heroku Configuration

  • Procfile: web (Streamlit) + worker (APScheduler)
  • runtime.txt: Python 3.11.11
  • bin/post_compile: Installs uv in Heroku buildpack

Verification

All checks passed:

# Package imports
$ uv run python -c "import quant_monitor; print('OK')"
OK

# Config loads
$ uv run python -c "from quant_monitor.config import cfg; print(len(cfg.tickers))"
15

# Main runs
$ uv run python -m quant_monitor.main
2026-02-24 13:54:56 | Quant Portfolio Monitor starting
2026-02-24 13:54:56 | Tracking 15 positions | Benchmark: SPY
2026-02-24 13:54:56 | Scheduler not yet implemented — exiting cleanly

# Lint clean
$ uv run ruff check .
All checks passed!

# Tests pass
$ uv run pytest tests/ -v
6 passed in 0.11s

Git History

commit 4240600
Author: Kartavya Jharwal <kjisgreatforever@gmail.com>
Date:   Mon Feb 24 13:55:00 2026

    Initial scaffold: 5-layer quant portfolio monitoring system

    - uv project with 188 resolved deps
    - config.toml with all 15 holdings, regime weights, risk params
    - Full module stubs: data, features, models, agent, backtest, dashboard
    - Dev tooling: ruff, pre-commit, mypy, pytest (6 tests passing)
    - CI/CD: GitHub Actions for lint/test/deploy
    - Heroku: Procfile + runtime.txt + bin/post_compile
    - MkDocs docs scaffold for post-sunset archive
    - Scrapy Cloud config for Zyte spider deployment

    68 files changed, 6244 insertions(+)

Lessons Learned

  1. torch download time: 108MB download took significant time. Fixed by:
  2. Setting UV_CACHE_DIR to D: drive (avoids cross-drive copies)
  3. Keeping torch as transitive dependency (via transformers)
  4. Using pytorch-cpu index to avoid CUDA bloat

  5. uv packaging warning: Needed [build-system] in pyproject.toml for entry points

  6. Scrapy ClassVar: Ruff's RUF012 rule requires ClassVar annotation for mutable class attributes in Scrapy spiders

  7. StrEnum migration: Ruff's UP042 recommends enum.StrEnum over (str, Enum) inheritance


Next Steps

Phase 1: Data Pipeline - Implement Alpaca feed (real-time prices + news) - Implement FRED feed (macro indicators) - Implement Appwrite client (read/write) - Implement diskcache wrapper - Implement pipeline orchestrator with failover - Deploy SEC EDGAR + Google RSS spiders to Scrapy Cloud


Phase 0 completed: February 24, 2026