Generated file. Source:
docs/ROS_logic.mdEdit the source document and runnpm run docs:syncto refresh this published copy.
ROS Logic¶
This file documents the current ROS calculation engine implementation.
Status¶
- Scope: current
ROSengine and the shared annual-accumulation strategy family it uses - Implementation status: active in production code
- Code path:
annual-accumulation.ts: src/app/domain/bond-engine/strategies/annual-accumulation.tsros.ts: src/app/domain/bond-engine/strategies/ros.ts- Test path:
annual-accumulation.strategy.test.ts: tests/annual-accumulation.strategy.test.tsros.strategy.test.ts: tests/ros.strategy.test.ts- Last reviewed against code: 2026-03-23
Product Rules¶
- Bond:
ROS - Duration:
6 years - Year 1 rate:
5.20% - Years 2-6 rate:
inflation + 2.00% - Capitalization: yearly
- Interest payout: only on redemption
- Early redemption cost:
3 złper bond - Bond unit price:
100 zł - Tax rate:
19% - Availability: only for investors receiving
800+
Strategy Family¶
ROS does not use the generic yearly calculator anymore.
It is implemented as a specialization of the shared annual-accumulation family for bonds that:
- capitalize annually
- do not pay cash during the cycle
- allow reinvestment only after redemption
- may end with early redemption of unfinished batches
That same family is currently used by:
TOSEDO
and is intended to be extended further with:
ROD
ROS Specialization¶
ROS configures the shared engine with:
strategyId = annual-accumulation-roscycleLengthYears = 6- rate resolver:
cycleYear === 1->5.20%cycleYear >= 2->inflation + 2.00%
So the ROS module contains only product-specific rate policy, while yearly batch mechanics remain shared.
State Model¶
The engine tracks:
cashpositionspurchaseEventsredemptionEventsyearSnapshotsyearlyResults
Each active position contains:
bondspurchaseYear
Simulation Flow¶
The engine works on yearly steps.
For each year:
- Redeem positions that reached natural maturity (
6 years). - Add redeemed net cash to
cash. - Reinvest available
cashinto full new bonds if the horizon continues. - If this is the final year, early-redeem all still-active positions.
- Build yearly carried-value and liquidation snapshots.
flowchart TD
A[Initial cash] --> B[Buy initial full bonds]
B --> C[Year loop]
C --> D{Any batch reached 6 years?}
D -->|Yes| E[Natural redemption + tax]
D -->|No| F[Keep active batches]
E --> G[Add net cash]
F --> G
G --> H{More years left?}
H -->|Yes| I[Buy new full bonds]
H -->|No| J[Final settlement]
I --> C
J --> K[Early redeem unfinished batches]
K --> L[Build final result]
Natural Redemption¶
For a naturally redeemed batch:
- Start with nominal principal.
- Apply yearly compounding for
6years:
V1 = P * (1 + 0.052)
V2 = V1 * (1 + inflation + 0.02)
...
V6 = V5 * (1 + inflation + 0.02)
- Compute gross profit:
grossProfit = V6 - P
- Compute tax:
tax = grossProfit * 0.19
- Add net redemption value to cash:
netRedemption = V6 - tax
Final Early Redemption¶
If the investment horizon ends before a batch reaches 6 years:
- Compute accumulated value for the current age in full years.
- Compute tax on total accrued gain.
- Subtract early redemption cost:
earlyCost = bondCount * 3 zł
- Add final net liquidation value to
cash.
Reinvestment¶
ROS does not reinvest during a cycle.
Reinvestment may happen only after natural redemption, using:
reinvestedBondCount = floor(cash / 100)
Any remainder stays as cash.
The engine records:
- initial allocation purchase event
- each reinvestment purchase event
- natural redemption events
- final early redemption events
Snapshot Semantics¶
grossValue¶
For each year:
grossValuemeans year-end portfolio value before all taxes and costs realized so far- it includes:
- carried portfolio value
- taxes already realized in previous completed cycles
- early-redemption costs already realized, if any
netValue¶
- intermediate years:
netValue = carried portfolio value- no forced liquidation is applied
- final year:
netValue = liquidationValue- all taxes and early redemption costs are fully settled
Rounding Policy¶
Current implementation follows project policy:
- internal calculations:
0.001 zł - final public values:
0.01 zł
Public Contract¶
The ROS public result includes:
- yearly results
- final totals
simulationDetails.strategy = "annual-accumulation-ros"simulationDetails.purchaseEventssimulationDetails.redemptionEvents
Covered Tests¶
Current automated ROS tests cover:
- first-year fixed
5.20%rate - switch to
inflation + 2.00% - natural 6-year redemption
- early redemption after 1, 2, and 5 years through direct and golden references
- no reinvestment before maturity
- reinvestment after natural redemption
- public result contract and strategy id
- long-horizon large-principal stability
- shared annual-accumulation invariant grid
Traceability¶
- product duration, redemption, tax, reinvestment:
ros.strategy.test.ts: tests/ros.strategy.test.ts- shared carried-value vs liquidation semantics:
annual-accumulation.strategy.test.ts: tests/annual-accumulation.strategy.test.ts- purchase and redemption history retention:
ros.strategy.test.ts: tests/ros.strategy.test.tsannual-accumulation.strategy.test.ts: tests/annual-accumulation.strategy.test.ts
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.tsros.strategy.test.ts: tests/ros.strategy.test.ts- ROS_logic.md
init_prompt.md: ai/init_prompt.md