# hajinhyukson/faustcalc architecture

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

- Interactive diagram: https://gitdiagram.com/hajinhyukson/faustcalc
- Repository: https://github.com/hajinhyukson/faustcalc

## Overview

FaustCalc is an investment portfolio recommendation and reporting product. Investors enter holdings, preferences, and constraints in the browser; the Spring web API extracts profile/filter inputs, invokes the Python recommendation engine, and returns results for report generation and display. Separate branches support universe exploration, run history, dashboards, and methodology. The README documents the cross-service workflow; source-index references and excerpts support selected internal calls. Some unsampled service and pipeline wiring is therefore omitted rather than inferred.

Main entry points: [`java-web/webapp/src/lib/api.ts`](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/lib/api.ts) (Web API client), [`java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java) (Portfolio API), [`java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java`](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java) (Engine bridge), [`src/cli.py`](https://github.com/hajinhyukson/faustcalc/blob/main/src/cli.py) (Python CLI)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Browser experience"]
  node_run_ui["Portfolio interview<br/>[main.ts]"]
  node_api_client["Web API client<br/>[api.ts]"]
  node_explore_ui["Universe explorer<br/>[main.ts]"]
  node_history_ui["Run history<br/>[main.ts]"]
  node_report_ui["Report renderer<br/>[render.ts]"]
end

subgraph group_web["Web application"]
  node_portfolio_api["Portfolio API"]
  node_universe_api["Universe API"]
  node_dashboard_api["Dashboard API"]
  node_run_store[("Run history store")]
  node_preference["Preference extraction"]
  node_filter["Preference filtering<br/>[FilterService.java]"]
  node_investor_profile["Investor profiling"]
  node_engine_bridge["Engine bridge"]
end

subgraph group_engine["Recommendation engine"]
  node_python_cli["Python CLI<br/>[cli.py]"]
  node_recommender["Fit and allocation<br/>[recommender.py]"]
  node_risk["Portfolio risk<br/>[risk.py]"]
end

subgraph group_data["Market data and features"]
  node_market_client["FMP market client<br/>[fmp_client.py]"]
  node_fmp{{"FMP market data"}}
  node_feature_store[("Feature database<br/>[db.py]")]
  node_refresh_jobs["Data refresh"]
end

subgraph group_reporting["Reporting and analysis"]
  node_report_service["Narrative reports"]
  node_analysis["Market analyses<br/>[theme_analysis.py]"]
  node_gemini{{"Gemini"}}
end

node_investor(("Investor"))

node_investor -->|"enters holdings"| node_run_ui
node_run_ui -->|"submits run"| node_api_client
node_api_client -->|"HTTP requests"| node_portfolio_api
node_portfolio_api -->|"extracts preferences"| node_preference
node_portfolio_api -->|"filters candidates"| node_filter
node_portfolio_api -->|"extracts profile"| node_investor_profile
node_portfolio_api -->|"runs engine"| node_engine_bridge
node_engine_bridge -->|"launches CLI"| node_python_cli
node_python_cli -->|"dispatches recommendation"| node_recommender
node_recommender -->|"uses risk metrics"| node_risk
node_recommender -.->|"fetches market data"| node_market_client
node_market_client -->|"requests prices"| node_fmp
node_engine_bridge -->|"generates narrative"| node_report_service
node_report_service -->|"requests report"| node_gemini
node_engine_bridge -->|"returns artifacts"| node_report_ui
node_api_client -.->|"provides report data"| node_report_ui
node_explore_ui -->|"queries universe"| node_api_client
node_api_client -->|"HTTP requests"| node_universe_api
node_dashboard_api -->|"reads runs"| node_run_store
node_history_ui -->|"loads history"| node_api_client
node_api_client -.->|"HTTP requests"| node_dashboard_api
node_universe_api -.->|"reads features"| node_feature_store
node_refresh_jobs -->|"fetches fundamentals"| node_market_client
node_refresh_jobs -->|"stores refreshed data"| node_feature_store
node_python_cli -.->|"runs analyses"| node_analysis

click node_run_ui "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/run/main.ts"
click node_api_client "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/lib/api.ts"
click node_explore_ui "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/explore/main.ts"
click node_history_ui "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/history/main.ts"
click node_report_ui "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/report/render.ts"
click node_portfolio_api "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java"
click node_universe_api "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/UniverseApiController.java"
click node_dashboard_api "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/DashboardApiController.java"
click node_run_store "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/entity/PortfolioRunEntity.java"
click node_preference "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/PreferenceExtractionService.java"
click node_filter "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/FilterService.java"
click node_investor_profile "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/InvestorProfileService.java"
click node_engine_bridge "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java"
click node_report_service "https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/GeminiReportService.java"
click node_python_cli "https://github.com/hajinhyukson/faustcalc/blob/main/src/cli.py"
click node_recommender "https://github.com/hajinhyukson/faustcalc/blob/main/src/ml/recommender.py"
click node_risk "https://github.com/hajinhyukson/faustcalc/blob/main/src/risk.py"
click node_market_client "https://github.com/hajinhyukson/faustcalc/blob/main/src/fmp_client.py"
click node_feature_store "https://github.com/hajinhyukson/faustcalc/blob/main/src/pipeline/db.py"
click node_refresh_jobs "https://github.com/hajinhyukson/faustcalc/blob/main/src/pipeline/refresh_fundamentals.py"
click node_analysis "https://github.com/hajinhyukson/faustcalc/blob/main/src/analysis/theme_analysis.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_run_ui,node_api_client,node_explore_ui,node_history_ui,node_report_ui toneBlue
class node_portfolio_api,node_universe_api,node_dashboard_api,node_run_store,node_preference,node_filter,node_investor_profile,node_engine_bridge toneAmber
class node_python_cli,node_recommender,node_risk toneMint
class node_market_client,node_fmp,node_feature_store,node_refresh_jobs toneRose
class node_report_service,node_analysis,node_gemini,node_investor toneIndigo
```

## Components

### Browser experience

- [Portfolio interview](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/run/main.ts): `java-web/webapp/src/pages/run/main.ts`
- [Web API client](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/lib/api.ts): `java-web/webapp/src/lib/api.ts`
- [Universe explorer](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/explore/main.ts): `java-web/webapp/src/pages/explore/main.ts`
- [Run history](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/history/main.ts): `java-web/webapp/src/pages/history/main.ts`
- [Report renderer](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/webapp/src/pages/report/render.ts): `java-web/webapp/src/pages/report/render.ts`

### Web application

- [Portfolio API](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java): `java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`
- [Universe API](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/UniverseApiController.java): `java-web/src/main/java/com/faustcalc/web/api/UniverseApiController.java`
- [Dashboard API](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/api/DashboardApiController.java): `java-web/src/main/java/com/faustcalc/web/api/DashboardApiController.java`
- [Run history store](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/entity/PortfolioRunEntity.java): `java-web/src/main/java/com/faustcalc/web/entity/PortfolioRunEntity.java`
- [Preference extraction](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/PreferenceExtractionService.java): `java-web/src/main/java/com/faustcalc/web/service/PreferenceExtractionService.java`
- [Preference filtering](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/FilterService.java): `java-web/src/main/java/com/faustcalc/web/service/FilterService.java`
- [Investor profiling](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/InvestorProfileService.java): `java-web/src/main/java/com/faustcalc/web/service/InvestorProfileService.java`
- [Engine bridge](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java): `java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java`

### Recommendation engine

- [Python CLI](https://github.com/hajinhyukson/faustcalc/blob/main/src/cli.py): `src/cli.py`
- [Fit and allocation](https://github.com/hajinhyukson/faustcalc/blob/main/src/ml/recommender.py): `src/ml/recommender.py`
- [Portfolio risk](https://github.com/hajinhyukson/faustcalc/blob/main/src/risk.py): `src/risk.py`

### Market data and features

- [FMP market client](https://github.com/hajinhyukson/faustcalc/blob/main/src/fmp_client.py): `src/fmp_client.py`
- **FMP market data**
- [Feature database](https://github.com/hajinhyukson/faustcalc/blob/main/src/pipeline/db.py): `src/pipeline/db.py`
- [Data refresh](https://github.com/hajinhyukson/faustcalc/blob/main/src/pipeline/refresh_fundamentals.py): `src/pipeline/refresh_fundamentals.py`

### Reporting and analysis

- [Narrative reports](https://github.com/hajinhyukson/faustcalc/blob/main/java-web/src/main/java/com/faustcalc/web/service/GeminiReportService.java): `java-web/src/main/java/com/faustcalc/web/service/GeminiReportService.java`
- [Market analyses](https://github.com/hajinhyukson/faustcalc/blob/main/src/analysis/theme_analysis.py): `src/analysis/theme_analysis.py`
- **Gemini**

### Other components

- **Investor**

## Connections

- Investor → Portfolio interview: enters holdings
- Portfolio interview → Web API client: submits run (evidence: `java-web/webapp/src/pages/run/main.ts`)
- Web API client → Portfolio API: HTTP requests
- Portfolio API → Preference extraction: extracts preferences (evidence: `java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`)
- Portfolio API → Preference filtering: filters candidates (evidence: `java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`)
- Portfolio API → Investor profiling: extracts profile (evidence: `java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`)
- Portfolio API → Engine bridge: runs engine (evidence: `java-web/src/main/java/com/faustcalc/web/api/PortfolioController.java`)
- Engine bridge → Python CLI: launches CLI
- Python CLI → Fit and allocation: dispatches recommendation (evidence: `src/cli.py`)
- Fit and allocation → Portfolio risk: uses risk metrics (evidence: `src/ml/recommender.py`)
- Fit and allocation → FMP market client: fetches market data
- FMP market client → FMP market data: requests prices
- Engine bridge → Narrative reports: generates narrative
- Narrative reports → Gemini: requests report
- Engine bridge → Report renderer: returns artifacts (evidence: `java-web/src/main/java/com/faustcalc/web/service/PortfolioEngineService.java`)
- Web API client → Report renderer: provides report data
- Universe explorer → Web API client: queries universe (evidence: `java-web/webapp/src/pages/explore/main.ts`)
- Web API client → Universe API: HTTP requests
- Dashboard API → Run history store: reads runs (evidence: `java-web/src/main/java/com/faustcalc/web/api/DashboardApiController.java`)
- Run history → Web API client: loads history (evidence: `java-web/webapp/src/pages/history/main.ts`)
- Web API client → Dashboard API: HTTP requests
- Universe API → Feature database: reads features
- Data refresh → FMP market client: fetches fundamentals (evidence: `src/pipeline/refresh_fundamentals.py`)
- Data refresh → Feature database: stores refreshed data (evidence: `src/pipeline/refresh_fundamentals.py`)
- Python CLI → Market analyses: runs analyses (evidence: `src/cli.py`)
