# maxzcodes/zeghers-multifactor-thesis architecture

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

- Interactive diagram: https://gitdiagram.com/maxzcodes/zeghers-multifactor-thesis
- Repository: https://github.com/maxzcodes/zeghers-multifactor-thesis

## Overview

This repository is a research pipeline for evaluating characteristic-based stock-selection strategies on a US equity universe. Its main workflow fetches licensed market and fundamentals data, builds and ranks monthly characteristics, forms portfolios, and evaluates gross/net returns, factor exposures, and benchmarks before exporting thesis tables and charts. The graph combines the documented stage sequence with sampled implementation details; unsampled modules are represented only where the README documents their role.

Main entry points: [`src/06_performance_gross.py`](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/06_performance_gross.py) (Gross performance), [`data/results`](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/results) (Strategy results), [`data`](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data) (Strategy labels), [`src/03_rank_select.py`](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/03_rank_select.py) (Rank and select)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingest["Data ingestion"]
  node_universe["RIC universe<br/>[ric_mapping.csv]"]
  node_price_fetch["Fetch prices<br/>[00_fetch_prices.py]"]
  node_fund_fetch["Fetch fundamentals"]
  node_raw_prices["Monthly price panel"]
  node_raw_funds["Annual fundamentals"]
  node_clean_funds["Clean fundamentals"]
end

subgraph group_signals["Signal construction"]
  node_characteristics["Build characteristics"]
  node_char_panel["Characteristics panel"]
  node_ranking["Rank and select<br/>[03_rank_select.py]"]
  node_labels["Strategy labels"]
  node_tw_weights["Freeze TW weights"]
  node_composites["Score composites"]
  node_composite_tsmv["Score TSMV composites"]
end

subgraph group_strategies["Portfolio evaluation"]
  node_portfolios["Form portfolios<br/>[05_portfolio_ls.py]"]
  node_long_only["Long-only portfolios<br/>[05_portfolio_lo.py]"]
  node_gross_perf["Gross performance"]
  node_transaction_costs["Transaction costs"]
end

subgraph group_analysis["Statistical analysis"]
  node_ff_factors["FF factors"]
  node_ff6["FF6 regressions<br/>[08_ff6_full.py]"]
  node_rolling_ff6["Rolling FF6<br/>[08_ff6_rolling.py]"]
  node_subperiod_ff6["Subperiod FF6"]
  node_benchmarks["Benchmark analysis<br/>[09_benchmark.py]"]
  node_spy["SPY returns<br/>[spy_tr_monthly.csv]"]
  node_results[("Strategy results")]
  node_export["Export thesis tables"]
  node_charts["Generate charts"]
  node_published_tables["Research question tables"]
end

subgraph group_shared["Shared analysis layer"]
  node_preprocessing["Signal preprocessing<br/>[preprocessing.py]"]
  node_rank_helpers["Ranking methods<br/>[ranking.py]"]
  node_performance_helpers["Performance metrics<br/>[performance.py]"]
  node_regression_helpers["Regression methods<br/>[regression.py]"]
end

node_analyst(("Researcher"))
node_lseg["LSEG Workspace"]

node_analyst -->|"runs fetch"| node_price_fetch
node_analyst -->|"runs fetch"| node_fund_fetch
node_universe -->|"provides RICs"| node_price_fetch
node_universe -->|"provides RICs"| node_fund_fetch
node_price_fetch -->|"requests prices"| node_lseg
node_fund_fetch -->|"requests fundamentals"| node_lseg
node_price_fetch -->|"writes panel"| node_raw_prices
node_fund_fetch -->|"writes panel"| node_raw_funds
node_raw_funds -->|"reads panel"| node_clean_funds
node_clean_funds -->|"supplies fundamentals"| node_characteristics
node_raw_prices -->|"supplies prices"| node_characteristics
node_characteristics -->|"uses transforms"| node_preprocessing
node_characteristics -->|"writes panel"| node_char_panel
node_char_panel -->|"reads signals"| node_ranking
node_ranking -->|"uses selection"| node_rank_helpers
node_ranking -->|"writes labels"| node_labels
node_labels -->|"feeds first pass"| node_tw_weights
node_tw_weights -->|"supplies frozen weights"| node_composites
node_labels -->|"supplies ranked signals"| node_composites
node_labels -->|"supplies ranked signals"| node_composite_tsmv
node_composites -->|"adds composite scores"| node_ranking
node_composite_tsmv -->|"adds composite scores"| node_ranking
node_labels -->|"forms holdings"| node_portfolios
node_labels -->|"forms holdings"| node_long_only
node_portfolios -->|"provides returns"| node_gross_perf
node_long_only -->|"provides returns"| node_gross_perf
node_gross_perf -->|"uses metrics"| node_performance_helpers
node_gross_perf -->|"provides gross inputs"| node_transaction_costs
node_transaction_costs -->|"uses metrics"| node_performance_helpers
node_gross_perf -->|"writes gross results"| node_results
node_transaction_costs -->|"writes net results"| node_results
node_ff_factors -->|"provides factors"| node_ff6
node_ff_factors -->|"provides factors"| node_rolling_ff6
node_ff_factors -->|"provides factors"| node_subperiod_ff6
node_gross_perf -->|"provides returns"| node_ff6
node_gross_perf -->|"provides returns"| node_rolling_ff6
node_gross_perf -->|"provides returns"| node_subperiod_ff6
node_ff6 -->|"uses regressions"| node_regression_helpers
node_rolling_ff6 -->|"uses regressions"| node_regression_helpers
node_subperiod_ff6 -->|"uses regressions"| node_regression_helpers
node_ff6 -->|"writes factor results"| node_results
node_rolling_ff6 -->|"writes rolling results"| node_results
node_subperiod_ff6 -->|"writes subperiod results"| node_results
node_ff_factors -->|"provides factors"| node_benchmarks
node_spy -->|"provides yardstick"| node_benchmarks
node_gross_perf -->|"provides returns"| node_benchmarks
node_benchmarks -->|"writes comparisons"| node_results
node_results -->|"reads analysis"| node_export

click node_universe "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/ric_mapping.csv"
click node_price_fetch "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/00_fetch_prices.py"
click node_fund_fetch "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/00_fetch_fundamentals.py"
click node_raw_prices "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data"
click node_raw_funds "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data"
click node_clean_funds "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/01_clean_fundamentals.py"
click node_characteristics "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/02_build_characteristics.py"
click node_preprocessing "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/preprocessing.py"
click node_char_panel "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data"
click node_ranking "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/03_rank_select.py"
click node_rank_helpers "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/ranking.py"
click node_labels "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data"
click node_tw_weights "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_freeze_tw_weights.py"
click node_composites "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_score_composite_ewcw.py"
click node_composite_tsmv "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_score_composite_tsmv.py"
click node_portfolios "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/05_portfolio_ls.py"
click node_long_only "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/05_portfolio_lo.py"
click node_gross_perf "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/06_performance_gross.py"
click node_transaction_costs "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/07_transaction_costs.py"
click node_ff_factors "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/ff_factors"
click node_ff6 "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_full.py"
click node_rolling_ff6 "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_rolling.py"
click node_subperiod_ff6 "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_subperiod.py"
click node_benchmarks "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/09_benchmark.py"
click node_spy "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/data/benchmarks/spy_tr_monthly.csv"
click node_performance_helpers "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/performance.py"
click node_regression_helpers "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/regression.py"
click node_results "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/results"
click node_export "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/10_export_tables.py"
click node_charts "https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/10_generate_charts.py"
click node_published_tables "https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/results/research_questions"

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_universe,node_price_fetch,node_fund_fetch,node_raw_prices,node_raw_funds,node_clean_funds toneBlue
class node_characteristics,node_char_panel,node_ranking,node_labels,node_tw_weights,node_composites,node_composite_tsmv toneAmber
class node_portfolios,node_long_only,node_gross_perf,node_transaction_costs toneMint
class node_ff_factors,node_ff6,node_rolling_ff6,node_subperiod_ff6,node_benchmarks,node_spy,node_results,node_export,node_charts,node_published_tables toneRose
class node_preprocessing,node_rank_helpers,node_performance_helpers,node_regression_helpers,node_analyst,node_lseg toneIndigo
```

## Components

### Data ingestion

- [RIC universe](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/ric_mapping.csv): `ric_mapping.csv`
- [Fetch prices](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/00_fetch_prices.py): `src/00_fetch_prices.py`
- [Fetch fundamentals](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/00_fetch_fundamentals.py): `src/00_fetch_fundamentals.py`
- [Monthly price panel](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data): `data`
- [Annual fundamentals](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data): `data`
- [Clean fundamentals](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/01_clean_fundamentals.py): `src/01_clean_fundamentals.py`

### Signal construction

- [Build characteristics](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/02_build_characteristics.py): `src/02_build_characteristics.py`
- [Characteristics panel](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data): `data`
- [Rank and select](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/03_rank_select.py): `src/03_rank_select.py`
- [Strategy labels](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data): `data`
- [Freeze TW weights](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_freeze_tw_weights.py): `src/04_freeze_tw_weights.py`
- [Score composites](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_score_composite_ewcw.py): `src/04_score_composite_ewcw.py`
- [Score TSMV composites](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/04_score_composite_tsmv.py): `src/04_score_composite_tsmv.py`

### Portfolio evaluation

- [Form portfolios](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/05_portfolio_ls.py): `src/05_portfolio_ls.py`
- [Long-only portfolios](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/05_portfolio_lo.py): `src/05_portfolio_lo.py`
- [Gross performance](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/06_performance_gross.py): `src/06_performance_gross.py`
- [Transaction costs](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/07_transaction_costs.py): `src/07_transaction_costs.py`

### Statistical analysis

- [FF factors](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/ff_factors): `data/ff_factors`
- [FF6 regressions](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_full.py): `src/08_ff6_full.py`
- [Rolling FF6](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_rolling.py): `src/08_ff6_rolling.py`
- [Subperiod FF6](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/08_ff6_subperiod.py): `src/08_ff6_subperiod.py`
- [Benchmark analysis](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/09_benchmark.py): `src/09_benchmark.py`
- [SPY returns](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/data/benchmarks/spy_tr_monthly.csv): `data/benchmarks/spy_tr_monthly.csv`
- [Strategy results](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/results): `data/results`
- [Export thesis tables](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/10_export_tables.py): `src/10_export_tables.py`
- [Generate charts](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/10_generate_charts.py): `src/10_generate_charts.py`
- [Research question tables](https://github.com/maxzcodes/zeghers-multifactor-thesis/tree/main/data/results/research_questions): `data/results/research_questions`

### Shared analysis layer

- [Signal preprocessing](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/preprocessing.py): `src/thesis/preprocessing.py`
- [Ranking methods](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/ranking.py): `src/thesis/ranking.py`
- [Performance metrics](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/performance.py): `src/thesis/performance.py`
- [Regression methods](https://github.com/maxzcodes/zeghers-multifactor-thesis/blob/main/src/thesis/regression.py): `src/thesis/regression.py`

### Other components

- **Researcher**
- **LSEG Workspace**

## Connections

- Researcher → Fetch prices: runs fetch
- Researcher → Fetch fundamentals: runs fetch
- RIC universe → Fetch prices: provides RICs
- RIC universe → Fetch fundamentals: provides RICs
- Fetch prices → LSEG Workspace: requests prices
- Fetch fundamentals → LSEG Workspace: requests fundamentals
- Fetch prices → Monthly price panel: writes panel
- Fetch fundamentals → Annual fundamentals: writes panel
- Annual fundamentals → Clean fundamentals: reads panel
- Clean fundamentals → Build characteristics: supplies fundamentals
- Monthly price panel → Build characteristics: supplies prices
- Build characteristics → Signal preprocessing: uses transforms
- Build characteristics → Characteristics panel: writes panel
- Characteristics panel → Rank and select: reads signals
- Rank and select → Ranking methods: uses selection
- Rank and select → Strategy labels: writes labels
- Strategy labels → Freeze TW weights: feeds first pass
- Freeze TW weights → Score composites: supplies frozen weights
- Strategy labels → Score composites: supplies ranked signals
- Strategy labels → Score TSMV composites: supplies ranked signals
- Score composites → Rank and select: adds composite scores
- Score TSMV composites → Rank and select: adds composite scores
- Strategy labels → Form portfolios: forms holdings
- Strategy labels → Long-only portfolios: forms holdings
- Form portfolios → Gross performance: provides returns
- Long-only portfolios → Gross performance: provides returns
- Gross performance → Performance metrics: uses metrics
- Gross performance → Transaction costs: provides gross inputs
- Transaction costs → Performance metrics: uses metrics
- Gross performance → Strategy results: writes gross results
- Transaction costs → Strategy results: writes net results
- FF factors → FF6 regressions: provides factors
- FF factors → Rolling FF6: provides factors
- FF factors → Subperiod FF6: provides factors
- Gross performance → FF6 regressions: provides returns
- Gross performance → Rolling FF6: provides returns
- Gross performance → Subperiod FF6: provides returns
- FF6 regressions → Regression methods: uses regressions
- Rolling FF6 → Regression methods: uses regressions
- Subperiod FF6 → Regression methods: uses regressions
- FF6 regressions → Strategy results: writes factor results
- Rolling FF6 → Strategy results: writes rolling results
- Subperiod FF6 → Strategy results: writes subperiod results
- FF factors → Benchmark analysis: provides factors
- SPY returns → Benchmark analysis: provides yardstick
- Gross performance → Benchmark analysis: provides returns
- Benchmark analysis → Strategy results: writes comparisons
- Strategy results → Export thesis tables: reads analysis
