Skip to content

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

ROS Logic

This file documents the current ROS calculation engine implementation.

Status

  • Scope: current ROS engine and the shared annual-accumulation family
  • Implementation status: active in production code
  • Code path:
  • annual-accumulation.ts: src/app/domain/bond-engine/strategies/annual-accumulation.ts
  • ros.ts: src/app/domain/bond-engine/strategies/ros.ts
  • Test path:
  • ros.strategy.test.ts: tests/ros.strategy.test.ts
  • annual-accumulation.strategy.test.ts: tests/annual-accumulation.strategy.test.ts
  • excel-accumulation-alignment.test.ts: tests/excel-accumulation-alignment.test.ts
  • Visual diagrams:
  • ROS_interest_flow_diagram.md - Flow diagrams and algorithm visualization

Product Rules

  • Bond: ROS
  • Duration: 6 years
  • Year 1 rate: 5.00%
  • Years 2-6 rate: inflation + 2.00%
  • Capitalization: yearly
  • Interest payout: only on redemption
  • Early redemption cost: 2 zł per bond
  • Exchange price used on rollover: catalog-driven; the production catalog currently stores 99.90, while the workbook-aligned regression scenario uses an explicit override of 100
  • Bond unit price: 100 zł
  • Tax rate: 19%
  • Availability: only for investors receiving 800+

Strategy Family

ROS is a specialization of the shared annual-accumulation family.

It configures:

  • strategyId = annual-accumulation-ros
  • cycleLengthYears = 6
  • rate resolver:
  • cycleYear === 1 -> 5.00%
  • cycleYear >= 2 -> inflation + 2.00%

Runtime Model

The engine models:

  • yearly capitalization inside the active ROS batch
  • tax only on redemption
  • rollover after natural maturity
  • residual cash parked on a non-interest-bearing cash account (unlike non-capitalizing bonds)

For ROS, workbook alignment depends on carrying the residue on that separate account. Since ROS is capitalizing, this account does not earn monthly interest to prevent incorrect OKO balance reporting.

Natural Redemption And Rollover

At natural maturity:

tax = (grossValue - principal) * 0.19
netRedemption = grossValue - tax
nextBondCount = floor(netRedemption / exchangePrice)
residue = netRedemption - nextBondCount * exchangePrice

residue goes to the residual cash account and continues to grow monthly.

Final Early Redemption

If the simulation ends before year 6:

earlyCost = bondCount * 2 zł
taxableProfit = max(0, grossValue - principal - earlyCost)
tax = taxableProfit * 0.19
netLiquidation = grossValue - earlyCost - tax

Public Result Semantics

The ROS public result includes:

  • bondValue
  • cashAccountBalance
  • yearly tax and early-redemption postings
  • purchase and redemption histories

Covered Tests

Current automated ROS tests cover:

  • first-year fixed 5.00%
  • switch to inflation + 2.00%
  • natural 6-year maturity
  • early redemption after 1, 2, and 5 years
  • rollover after natural maturity
  • residual cash-account balance after rollover
  • public result contract
  • Excel alignment across 12 yearly checkpoints

Change Rules

If ROS logic changes, update together:

  • annual-accumulation.ts: src/app/domain/bond-engine/strategies/annual-accumulation.ts
  • annual_accumulation_logic.md
  • ros.ts: src/app/domain/bond-engine/strategies/ros.ts
  • ros.strategy.test.ts: tests/ros.strategy.test.ts
  • excel-accumulation-alignment.test.ts: tests/excel-accumulation-alignment.test.ts
  • ROS_logic.md