# chienwosu/finsignal architecture

> Architecture diagram of the GitHub repository chienwosu/finsignal, 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/chienwosu/finsignal
- Repository: https://github.com/chienwosu/finsignal

## Overview

FinSignal is a synthetic-portfolio monitoring app that checks policy, simulates rebalance or contribution recommendations, and presents a decision brief only when attention is needed. The Streamlit UI also displays portfolio and policy status directly. The deterministic analysis runs before optional language polishing; no trades are executed. Edges follow the sampled UI, orchestration, and tool code plus the README architecture. The README documents the Strands agent’s tool orchestration; the sampled source does not show its internal dispatch behavior in detail.

Main entry points: [`src/agent.py`](https://github.com/chienwosu/finsignal/blob/main/src/agent.py) (Agent runner), [`src/tools/portfolio.py`](https://github.com/chienwosu/finsignal/blob/main/src/tools/portfolio.py) (Portfolio loader), [`app.py`](https://github.com/chienwosu/finsignal/blob/main/app.py) (Streamlit UI), [`src/models/schemas.py`](https://github.com/chienwosu/finsignal/blob/main/src/models/schemas.py) (Domain schemas)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["Investor interface"]
  node_ui["Streamlit UI<br/>[app.py]"]
end

subgraph group_orchestration["Agent orchestration"]
  node_agent["Agent runner<br/>[agent.py]"]
  node_prompts["Prompt builder<br/>[prompts.py]"]
end

subgraph group_analysis["Deterministic analysis"]
  node_portfolio["Portfolio loader<br/>[portfolio.py]"]
  node_constraints["Policy checks<br/>[constraints.py]"]
  node_allocation["Trade simulation<br/>[allocation.py]"]
  node_decisions["Decision evaluator<br/>[decisions.py]"]
  node_schemas["Domain schemas<br/>[schemas.py]"]
end

subgraph group_inputs["Synthetic inputs"]
  node_portfolio_data["Holdings data<br/>[portfolio.json]"]
  node_policy_data["Policy data<br/>[policy.json]"]
  node_scenario_data["Scenario data<br/>[scenarios.json]"]
  node_persona_data["Investor persona<br/>[persona.json]"]
end

node_investor(("Investor"))
node_model(("Language model"))

node_investor -->|"selects scenario"| node_ui
node_ui -->|"loads display data"| node_portfolio
node_ui -->|"checks policy"| node_constraints
node_ui -->|"requests analysis"| node_agent
node_agent -->|"loads portfolio"| node_portfolio
node_agent -->|"loads policy"| node_portfolio
node_agent -->|"checks rules"| node_constraints
node_agent -->|"simulates rebalance"| node_allocation
node_agent -->|"allocates contribution"| node_allocation
node_agent -->|"evaluates results"| node_decisions
node_agent -.->|"builds prompt"| node_prompts
node_prompts -->|"reads persona"| node_persona_data
node_agent -.->|"polishes brief"| node_model
node_portfolio -->|"reads holdings"| node_portfolio_data
node_portfolio -->|"reads scenarios"| node_scenario_data
node_portfolio -->|"reads policy"| node_policy_data
node_ui -->|"shows brief"| node_investor
node_portfolio -->|"creates models"| node_schemas
node_constraints -->|"returns results"| node_schemas
node_allocation -->|"returns trades"| node_schemas
node_decisions -->|"returns brief"| node_schemas

click node_ui "https://github.com/chienwosu/finsignal/blob/main/app.py"
click node_agent "https://github.com/chienwosu/finsignal/blob/main/src/agent.py"
click node_prompts "https://github.com/chienwosu/finsignal/blob/main/src/prompts.py"
click node_portfolio "https://github.com/chienwosu/finsignal/blob/main/src/tools/portfolio.py"
click node_constraints "https://github.com/chienwosu/finsignal/blob/main/src/tools/constraints.py"
click node_allocation "https://github.com/chienwosu/finsignal/blob/main/src/tools/allocation.py"
click node_decisions "https://github.com/chienwosu/finsignal/blob/main/src/tools/decisions.py"
click node_schemas "https://github.com/chienwosu/finsignal/blob/main/src/models/schemas.py"
click node_portfolio_data "https://github.com/chienwosu/finsignal/blob/main/data/portfolio.json"
click node_policy_data "https://github.com/chienwosu/finsignal/blob/main/data/policy.json"
click node_scenario_data "https://github.com/chienwosu/finsignal/blob/main/data/scenarios.json"
click node_persona_data "https://github.com/chienwosu/finsignal/blob/main/data/persona.json"

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_ui toneBlue
class node_agent,node_prompts toneAmber
class node_portfolio,node_constraints,node_allocation,node_decisions,node_schemas toneMint
class node_portfolio_data,node_policy_data,node_scenario_data,node_persona_data toneRose
class node_investor,node_model toneIndigo
```

## Components

### Investor interface

- [Streamlit UI](https://github.com/chienwosu/finsignal/blob/main/app.py): `app.py`

### Agent orchestration

- [Agent runner](https://github.com/chienwosu/finsignal/blob/main/src/agent.py): `src/agent.py`
- [Prompt builder](https://github.com/chienwosu/finsignal/blob/main/src/prompts.py): `src/prompts.py`

### Deterministic analysis

- [Portfolio loader](https://github.com/chienwosu/finsignal/blob/main/src/tools/portfolio.py): `src/tools/portfolio.py`
- [Policy checks](https://github.com/chienwosu/finsignal/blob/main/src/tools/constraints.py): `src/tools/constraints.py`
- [Trade simulation](https://github.com/chienwosu/finsignal/blob/main/src/tools/allocation.py): `src/tools/allocation.py`
- [Decision evaluator](https://github.com/chienwosu/finsignal/blob/main/src/tools/decisions.py): `src/tools/decisions.py`
- [Domain schemas](https://github.com/chienwosu/finsignal/blob/main/src/models/schemas.py): `src/models/schemas.py`

### Synthetic inputs

- [Holdings data](https://github.com/chienwosu/finsignal/blob/main/data/portfolio.json): `data/portfolio.json`
- [Policy data](https://github.com/chienwosu/finsignal/blob/main/data/policy.json): `data/policy.json`
- [Scenario data](https://github.com/chienwosu/finsignal/blob/main/data/scenarios.json): `data/scenarios.json`
- [Investor persona](https://github.com/chienwosu/finsignal/blob/main/data/persona.json): `data/persona.json`

### Other components

- **Investor**
- **Language model**

## Connections

- Investor → Streamlit UI: selects scenario
- Streamlit UI → Portfolio loader: loads display data
- Streamlit UI → Policy checks: checks policy
- Streamlit UI → Agent runner: requests analysis
- Agent runner → Portfolio loader: loads portfolio
- Agent runner → Portfolio loader: loads policy
- Agent runner → Policy checks: checks rules
- Agent runner → Trade simulation: simulates rebalance
- Agent runner → Trade simulation: allocates contribution
- Agent runner → Decision evaluator: evaluates results
- Agent runner → Prompt builder: builds prompt
- Prompt builder → Investor persona: reads persona
- Agent runner → Language model: polishes brief
- Portfolio loader → Holdings data: reads holdings
- Portfolio loader → Scenario data: reads scenarios
- Portfolio loader → Policy data: reads policy
- Streamlit UI → Investor: shows brief
- Portfolio loader → Domain schemas: creates models
- Policy checks → Domain schemas: returns results
- Trade simulation → Domain schemas: returns trades
- Decision evaluator → Domain schemas: returns brief
