# znzhao/etfregulus architecture

> Architecture diagram of the GitHub repository znzhao/etfregulus, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/znzhao/etfregulus
- Repository: https://github.com/znzhao/etfregulus

## Overview

ETFRegulus is a framework for researching dynamic ETF allocation under market-regime signals and trading constraints. Its visible workflow is staged: fetch market and macro data, curate it onto trading sessions with quality checks, build features, then simulate allocations and assess results. The simulator applies risk and feasibility controls before next-open execution, with a ledger and holding locks tracking portfolio state. The README describes reinforcement learning, but the supplied tree has no evident policy or training implementation; source excerpts are partial, so uncertain module wiring is omitted.

Main entry points: [`src/cli/stage.py`](https://github.com/znzhao/etfregulus/blob/main/src/cli/stage.py) (Stage harness), [`src/sim/simulator.py`](https://github.com/znzhao/etfregulus/blob/main/src/sim/simulator.py) (Portfolio simulator), [`src/features/builder.py`](https://github.com/znzhao/etfregulus/blob/main/src/features/builder.py) (Feature builder), [`src/sim/runner.py`](https://github.com/znzhao/etfregulus/blob/main/src/sim/runner.py) (Simulation runner)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_stages["Stage workflow"]
  node_stage["Stage harness<br/>[stage.py]"]
  node_fetch_stage["Fetch stage<br/>[s01_fetch_data.py]"]
  node_curate_stage["Curation stage<br/>[s02_curate_data.py]"]
  node_feature_stage["Feature stage"]
  node_simulate_stage["Simulation stage<br/>[s04_simulate.py]"]
  node_baseline_stage["Baseline stage"]
  node_config["Typed configuration<br/>[loader.py]"]
end

subgraph group_data["Market data"]
  node_fetch["Data fetch<br/>[fetch.py]"]
  node_curate["Data curation<br/>[curate.py]"]
  node_calendar["Trading calendar<br/>[calendar.py]"]
  node_features["Feature builder<br/>[builder.py]"]
  node_etf_features["ETF features<br/>[etf.py]"]
  node_macro_features["Macro features<br/>[macro.py]"]
  node_cross_features["Cross-sectional features<br/>[cross_sectional.py]"]
end

subgraph group_allocation["Allocation simulation"]
  node_baselines["Baseline strategies<br/>[strategies.py]"]
  node_simulator["Portfolio simulator<br/>[simulator.py]"]
  node_runner["Simulation runner<br/>[runner.py]"]
  node_projector["Feasibility projector<br/>[projector.py]"]
  node_risk["Risk envelope<br/>[risk_envelope.py]"]
  node_execution["Trade execution<br/>[execution.py]"]
  node_locks["Holding locks<br/>[lock_manager.py]"]
  node_ledger[("Portfolio ledger<br/>[ledger.py]")]
  node_valuation["Portfolio valuation<br/>[valuation.py]"]
end

subgraph group_assessment["Evaluation"]
  node_metrics["Performance metrics<br/>[metrics.py]"]
end

node_user(("Researcher"))
node_market_sources["Market data providers"]
node_macro_source["FRED"]

node_user -->|"runs stages"| node_stage
node_stage -->|"dispatches"| node_fetch_stage
node_stage -->|"dispatches"| node_curate_stage
node_stage -->|"dispatches"| node_feature_stage
node_stage -->|"dispatches"| node_simulate_stage
node_stage -->|"dispatches"| node_baseline_stage
node_stage -->|"loads config"| node_config
node_fetch_stage -->|"invokes"| node_fetch
node_market_sources -.->|"provides data"| node_fetch
node_macro_source -.->|"provides series"| node_fetch
node_curate_stage -->|"invokes"| node_curate
node_curate -->|"aligns sessions"| node_calendar
node_feature_stage -->|"invokes"| node_features
node_features -->|"builds ETF signals"| node_etf_features
node_features -->|"builds macro signals"| node_macro_features
node_features -->|"builds cross signals"| node_cross_features
node_baseline_stage -->|"selects weights"| node_baselines
node_simulate_stage -->|"invokes"| node_runner
node_runner -->|"runs trajectory"| node_simulator
node_baselines -->|"supplies weights"| node_simulator
node_simulator -->|"projects targets"| node_projector
node_simulator -->|"prepares risk limits"| node_risk
node_simulator -->|"executes targets"| node_execution
node_simulator -->|"checks lock state"| node_locks
node_execution -->|"checks sellability"| node_locks
node_execution -->|"updates holdings"| node_ledger
node_simulator -->|"values portfolio"| node_valuation
node_runner -->|"summarizes results"| node_metrics

click node_stage "https://github.com/znzhao/etfregulus/blob/main/src/cli/stage.py"
click node_fetch_stage "https://github.com/znzhao/etfregulus/blob/main/scripts/s01_fetch_data.py"
click node_curate_stage "https://github.com/znzhao/etfregulus/blob/main/scripts/s02_curate_data.py"
click node_feature_stage "https://github.com/znzhao/etfregulus/blob/main/scripts/s03_build_features.py"
click node_simulate_stage "https://github.com/znzhao/etfregulus/blob/main/scripts/s04_simulate.py"
click node_baseline_stage "https://github.com/znzhao/etfregulus/blob/main/scripts/s05_run_baselines.py"
click node_fetch "https://github.com/znzhao/etfregulus/blob/main/src/data/fetch.py"
click node_curate "https://github.com/znzhao/etfregulus/blob/main/src/data/curate.py"
click node_calendar "https://github.com/znzhao/etfregulus/blob/main/src/data/calendar.py"
click node_features "https://github.com/znzhao/etfregulus/blob/main/src/features/builder.py"
click node_etf_features "https://github.com/znzhao/etfregulus/blob/main/src/features/etf.py"
click node_macro_features "https://github.com/znzhao/etfregulus/blob/main/src/features/macro.py"
click node_cross_features "https://github.com/znzhao/etfregulus/blob/main/src/features/cross_sectional.py"
click node_config "https://github.com/znzhao/etfregulus/blob/main/src/config/loader.py"
click node_baselines "https://github.com/znzhao/etfregulus/blob/main/src/baselines/strategies.py"
click node_simulator "https://github.com/znzhao/etfregulus/blob/main/src/sim/simulator.py"
click node_runner "https://github.com/znzhao/etfregulus/blob/main/src/sim/runner.py"
click node_projector "https://github.com/znzhao/etfregulus/blob/main/src/constraints/projector.py"
click node_risk "https://github.com/znzhao/etfregulus/blob/main/src/constraints/risk_envelope.py"
click node_execution "https://github.com/znzhao/etfregulus/blob/main/src/portfolio/execution.py"
click node_locks "https://github.com/znzhao/etfregulus/blob/main/src/portfolio/lock_manager.py"
click node_ledger "https://github.com/znzhao/etfregulus/blob/main/src/portfolio/ledger.py"
click node_valuation "https://github.com/znzhao/etfregulus/blob/main/src/portfolio/valuation.py"
click node_metrics "https://github.com/znzhao/etfregulus/blob/main/src/evaluation/metrics.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_stage,node_fetch_stage,node_curate_stage,node_feature_stage,node_simulate_stage,node_baseline_stage,node_config toneBlue
class node_fetch,node_curate,node_calendar,node_features,node_etf_features,node_macro_features,node_cross_features toneAmber
class node_baselines,node_simulator,node_runner,node_projector,node_risk,node_execution,node_locks,node_ledger,node_valuation toneMint
class node_metrics toneRose
class node_user,node_market_sources,node_macro_source toneIndigo
```

## Components

### Stage workflow

- [Stage harness](https://github.com/znzhao/etfregulus/blob/main/src/cli/stage.py): `src/cli/stage.py`
- [Fetch stage](https://github.com/znzhao/etfregulus/blob/main/scripts/s01_fetch_data.py): `scripts/s01_fetch_data.py`
- [Curation stage](https://github.com/znzhao/etfregulus/blob/main/scripts/s02_curate_data.py): `scripts/s02_curate_data.py`
- [Feature stage](https://github.com/znzhao/etfregulus/blob/main/scripts/s03_build_features.py): `scripts/s03_build_features.py`
- [Simulation stage](https://github.com/znzhao/etfregulus/blob/main/scripts/s04_simulate.py): `scripts/s04_simulate.py`
- [Baseline stage](https://github.com/znzhao/etfregulus/blob/main/scripts/s05_run_baselines.py): `scripts/s05_run_baselines.py`
- [Typed configuration](https://github.com/znzhao/etfregulus/blob/main/src/config/loader.py): `src/config/loader.py`

### Market data

- [Data fetch](https://github.com/znzhao/etfregulus/blob/main/src/data/fetch.py): `src/data/fetch.py`
- [Data curation](https://github.com/znzhao/etfregulus/blob/main/src/data/curate.py): `src/data/curate.py`
- [Trading calendar](https://github.com/znzhao/etfregulus/blob/main/src/data/calendar.py): `src/data/calendar.py`
- [Feature builder](https://github.com/znzhao/etfregulus/blob/main/src/features/builder.py): `src/features/builder.py`
- [ETF features](https://github.com/znzhao/etfregulus/blob/main/src/features/etf.py): `src/features/etf.py`
- [Macro features](https://github.com/znzhao/etfregulus/blob/main/src/features/macro.py): `src/features/macro.py`
- [Cross-sectional features](https://github.com/znzhao/etfregulus/blob/main/src/features/cross_sectional.py): `src/features/cross_sectional.py`

### Allocation simulation

- [Baseline strategies](https://github.com/znzhao/etfregulus/blob/main/src/baselines/strategies.py): `src/baselines/strategies.py`
- [Portfolio simulator](https://github.com/znzhao/etfregulus/blob/main/src/sim/simulator.py): `src/sim/simulator.py`
- [Simulation runner](https://github.com/znzhao/etfregulus/blob/main/src/sim/runner.py): `src/sim/runner.py`
- [Feasibility projector](https://github.com/znzhao/etfregulus/blob/main/src/constraints/projector.py): `src/constraints/projector.py`
- [Risk envelope](https://github.com/znzhao/etfregulus/blob/main/src/constraints/risk_envelope.py): `src/constraints/risk_envelope.py`
- [Trade execution](https://github.com/znzhao/etfregulus/blob/main/src/portfolio/execution.py): `src/portfolio/execution.py`
- [Holding locks](https://github.com/znzhao/etfregulus/blob/main/src/portfolio/lock_manager.py): `src/portfolio/lock_manager.py`
- [Portfolio ledger](https://github.com/znzhao/etfregulus/blob/main/src/portfolio/ledger.py): `src/portfolio/ledger.py`
- [Portfolio valuation](https://github.com/znzhao/etfregulus/blob/main/src/portfolio/valuation.py): `src/portfolio/valuation.py`

### Evaluation

- [Performance metrics](https://github.com/znzhao/etfregulus/blob/main/src/evaluation/metrics.py): `src/evaluation/metrics.py`

### Other components

- **Researcher**
- **Market data providers**
- **FRED**

## Connections

- Researcher → Stage harness: runs stages
- Stage harness → Fetch stage: dispatches
- Stage harness → Curation stage: dispatches
- Stage harness → Feature stage: dispatches
- Stage harness → Simulation stage: dispatches
- Stage harness → Baseline stage: dispatches
- Stage harness → Typed configuration: loads config
- Fetch stage → Data fetch: invokes
- Market data providers → Data fetch: provides data
- FRED → Data fetch: provides series
- Curation stage → Data curation: invokes
- Data curation → Trading calendar: aligns sessions
- Feature stage → Feature builder: invokes
- Feature builder → ETF features: builds ETF signals
- Feature builder → Macro features: builds macro signals
- Feature builder → Cross-sectional features: builds cross signals
- Baseline stage → Baseline strategies: selects weights
- Simulation stage → Simulation runner: invokes
- Simulation runner → Portfolio simulator: runs trajectory
- Baseline strategies → Portfolio simulator: supplies weights
- Portfolio simulator → Feasibility projector: projects targets
- Portfolio simulator → Risk envelope: prepares risk limits
- Portfolio simulator → Trade execution: executes targets
- Portfolio simulator → Holding locks: checks lock state
- Trade execution → Holding locks: checks sellability
- Trade execution → Portfolio ledger: updates holdings
- Portfolio simulator → Portfolio valuation: values portfolio
- Simulation runner → Performance metrics: summarizes results
