Skip to content

Generated file. Source: docs/analysis_models_architecture.md Edit the source document and run npm run docs:sync to refresh this published copy.

Analysis Models Architecture

This document defines the architectural layer for interpretation and analysis models built on top of the canonical bond-engine result.

Goal

The product must support more than one defended interpretation of the same simulation result without corrupting the canonical result contract.

This layer exists to make that possible.

It should allow the project to add new analytical interpretations over time, such as:

  • investment progression
  • year-by-year liquidation comparison
  • future scenario analysis
  • future portfolio analysis
  • future prediction-vs-reality comparison

Architectural Position

The analysis-model layer sits between:

  • the canonical result model produced by the engine
  • view adapters and UI components

Simplified flow:

flowchart LR
    A[Selection and normalized inputs] --> B[Bond engine]
    B --> C[Canonical result model]
    C --> D[Analysis model]
    D --> E[View adapters]
    E --> F[Table]
    E --> G[Chart]
    E --> H[Summary]

Layering Rules

1. Canonical result model

Responsibility:

  • remain the stable engine output
  • describe the real progression of the investment under product mechanics
  • stay independent from any one analytical interpretation

Current source of truth:

2. Analysis models

Responsibility:

  • reinterpret the same canonical result in an explicit and defensible way
  • expose contracts owned by the analytical meaning, not by one UI component
  • keep product semantics out of view components

Initial models:

  • investment_progression
  • year_by_year_liquidation

3. View adapters

Responsibility:

  • prepare analysis-model outputs for table, chart, summary, export, or future UI needs
  • stay presentation-oriented
  • not invent financial semantics locally

Why This Layer Is Needed

Without this layer, new interpretations tend to end up in the wrong places:

  • inside table components
  • inside generic result adapters
  • as convenience fields added directly to the canonical result contract

All three would make the product harder to extend and easier to misinterpret.

Initial Semantics

investment_progression

This is the defended meaning of the current yearly interpretation.

It answers:

  • how the investment evolves under the actual product mechanics
  • what taxes, redemption costs, and carried value look like during the investment

Important:

  • intermediate rows describe the in-flight state of the investment
  • the last year remains the authoritative answer for the chosen horizon

year_by_year_liquidation

This is a separate comparative interpretation.

It answers:

  • what outcome should be presented if the investment is treated as ending in year X

Important:

  • it is not the hidden meaning of current yearly rows
  • it must be explicitly labeled as a comparison mode
  • in v1 it is implemented as a dedicated analysis model above the canonical result
  • in v1 each yearly comparison row is produced by recalculating the engine for the same investment setup with the horizon shortened to year X

Contract Direction

The layer should use:

  • a small shared base contract for analysis models
  • model-specific output contracts for real analytical differences

Examples:

  • InvestmentProgressionAnalysis
  • YearByYearLiquidationAnalysis

The project should avoid creating one giant universal output type with many optional fields.

Dependency Rules

  • engine strategies may produce canonical results and optional simulation details
  • canonical result types must not depend on analysis models
  • analysis models may depend on canonical result types and documented simulation details
  • view adapters may depend on analysis-model outputs
  • UI components should depend on view adapters, not on analytical logic

Extensibility Rules

Adding a new analysis model should normally require:

  1. a new model id
  2. a dedicated model module
  3. a registration entry
  4. contract tests
  5. documentation updates

Adding a new analysis model should not normally require:

  • changing the canonical result contract
  • changing engine strategy outputs
  • adding interpretation-specific fields directly to BondCalculationResult

If a model cannot be implemented without new source data, that gap should be documented explicitly as an engine-support need rather than hidden in UI code.

First Implementation Scope

The first product rollout of this layer is now exposed through:

  • one shared global analysis-mode state
  • two small section-level UI switches acting as interfaces to that same state

That shared state controls:

  • chart semantics
  • summary semantics
  • yearly-table semantics

Why:

  • the product decision is no longer local to one component
  • the user is choosing one defended interpretation of the same simulation
  • keeping the state global reduces semantic drift between result sections

Current UI implementation:

  • one switch is placed in Wykres Porównawczy
  • one switch is placed in Szczegółowa Tabela Roczna
  • both operate on the same global analysisMode
  • Podsumowanie Wyników reflects the active mode without introducing a third competing control

UI control map:

UI section Own switch Consumes active mode Responsibility
Wykres Porównawczy Yes Yes lets the user change the shared analysis state while reading aggregated output
Podsumowanie Wyników No Yes reflects the selected interpretation without creating a competing control
Szczegółowa Tabela Roczna Yes Yes lets the user change the shared analysis state while reading detailed yearly output

Shared-control diagram:

This diagram shows the architectural flow from the shared global state into analysis-aware adapters, not just the user-facing placement of controls.

flowchart LR
    A[Chart switch] --> C[Global analysisMode state]
    B[Yearly-table switch] --> C
    C --> D[Chart adapters]
    C --> E[Summary adapters]
    C --> F[Yearly-table adapters]

The yearly table remains the most detailed consumer of the difference between progression and liquidation semantics, but it is no longer the only entry point for that choice.

Documents That Must Stay Aligned