Skip to content

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

COI Logic

This file documents the current COI calculation engine implementation.

Important: COI now has two distinct production paths:

  • reinvest
  • uses the shared annual-payout.ts: src/app/domain/bond-engine/strategies/annual-payout.ts family
  • oko
  • uses the shared Excel-aligned helper excel-like-oko.ts: src/app/domain/bond-engine/strategies/shared/excel-like-oko.ts
  • reproduces the workbook-style yearly liquidation checkpoints, exchange at 99.90, protection window for the early-redemption fee, and separate OKO balance growth

Status

  • Scope: current COI engine and the shared annual-payout strategy family it uses
  • Implementation status: active in production code
  • Code path:
  • annual-payout.ts: src/app/domain/bond-engine/strategies/annual-payout.ts
  • excel-like-oko.ts: src/app/domain/bond-engine/strategies/shared/excel-like-oko.ts
  • coi.ts: src/app/domain/bond-engine/strategies/coi.ts
  • Test path:
  • annual-payout.strategy.test.ts: tests/annual-payout.strategy.test.ts
  • coi.strategy.test.ts: tests/coi.strategy.test.ts
  • Last reviewed against code: 2026-04-04
  • Visual diagrams:
  • COI_interest_flow_diagram.md - Flow diagrams and algorithm visualization

Product Rules

  • Bond: COI
  • Duration: 4 years
  • Year 1 rate: 4.75%
  • Years 2-4 rate: inflation + 1.50%
  • Capitalization: none
  • Interest payout: yearly
  • Early redemption cost: 2 zł per bond
  • Bond unit price: 100 zł
  • Tax rate: 19%
  • Exchange price used by the Excel-aligned OKO path: 99.90 zł
  • Protection window used by the Excel-aligned OKO path: 12 miesięcy

Strategy Family

COI does not use the generic yearly calculator anymore.

For reinvest, COI is implemented as a specialization of the shared annual-payout family for bonds that:

  • pay annual interest out of the bond
  • do not capitalize interest inside the batch
  • may reinvest paid net interest
  • redeem principal at cycle end
  • may finish with final early redemption of unfinished batches

For oko, COI switches to the Excel-aligned helper that:

  • works on monthly steps even though the coupon is annual
  • tracks a separate OKO balance
  • keeps current-cycle accrued interest inside the liquidation checkpoint
  • at natural maturity exchanges the bond value at 99.90
  • additionally buys full 100 zł bonds from whole hundreds already accumulated on OKO

COI Specialization

COI configures the shared engine with:

  • strategyId = annual-payout-coi
  • cycleLengthYears = 4
  • rate resolver:
  • cycleYear === 1 -> 4.75%
  • cycleYear >= 2 -> inflation + 1.50%

State Model

The engine tracks:

  • cash
  • cashAccountBalance
  • positions
  • purchaseEvents
  • payoutEvents
  • cashAccountEvents
  • redemptionEvents
  • yearSnapshots
  • yearlyResults

Each active position contains:

  • bonds
  • purchaseYear

Simulation Flow

The engine works on yearly steps.

For each year:

  1. Pay annual interest for all active positions.
  2. Tax the paid interest immediately.
  3. Depending on interestPayoutMode, either add net interest to reinvestment cash or transfer it to OKO.
  4. Redeem positions that reached natural maturity (4 years) and return principal.
  5. Reinvest available cash into full new bonds if the horizon continues.
  6. If this is the final year, early-redeem all still-active positions.
  7. Build yearly carried-value and liquidation snapshots.

Interest Formula

For one batch in one year:

grossInterest = bonds * 100 * annualRate
taxPaid = grossInterest * 0.19
netInterest = grossInterest - taxPaid
cash += netInterest

annualRate depends on the year inside the 4-year cycle.

Redemption Rules

Natural redemption:

  • happens when ageInYears === 4
  • returns only principal, because interest for the final year was already paid in that same yearly step

Final early redemption:

  • happens only in the terminal year
  • returns principal
  • subtracts 2 zł per active bond
  • in oko mode, the terminal-year coupon is settled inside the final liquidation of the batch instead of being transferred to OKO first
  • does not create an extra end-of-horizon interest tax beyond the settlement already produced by the current coupon and the early-redemption fee

Reinvestment And OKO

COI supports two payout modes:

  • reinvest
  • annual net interest is added to reinvestment cash
  • oko
  • annual net interest from completed years is transferred to a separate OKO balance
  • OKO accrues monthly interest using the configured annual rate
  • OKO interest is taxed on an ongoing basis
  • at natural maturity the redeemed value is exchanged at 99.90
  • whole hundreds already sitting on OKO are also converted into new bonds at the next cycle start
  • remaining OKO money stays outside normal reinvestment

Reinvestment uses:

reinvestedBondCount = floor(cash / 100)

Reinvestment may happen only from reinvestment cash:

  • from accumulated annual net payouts
  • from natural redemptions
  • from both together

The engine records:

  • initial allocation purchase event
  • each reinvestment purchase event
  • annual payout events
  • natural redemption events
  • final early redemption events

Snapshot Semantics

grossValue

For each year:

  • grossValue means year-end portfolio value before all taxes and costs realized so far
  • it includes:
  • carried portfolio value
  • taxes already paid in earlier payout years
  • early-redemption costs already realized, if any

netValue

  • in reinvest mode:
  • intermediate years show carried portfolio value
  • final year shows liquidation value
  • in oko mode:
  • yearly rows are explicit workbook-style liquidation checkpoints
  • each checkpoint combines the current bond liquidation value with the OKO balance after that month’s account accrual but before the current maturity/payout transfer is reused in the next cycle

This differs from annual-capitalization products because there is no unrealized compounded value inside the active principal itself.

Rounding Policy

Current implementation follows project policy:

  • internal calculations: 0.001 zł
  • final public values: 0.01 zł

Public Contract

The COI public result includes:

  • yearly results
  • final totals
  • simulationDetails.strategy = "annual-payout-coi"
  • simulationDetails.purchaseEvents
  • simulationDetails.payoutEvents
  • simulationDetails.cashAccountEvents
  • simulationDetails.redemptionEvents

Covered Tests

Current automated COI tests cover:

  • first-year fixed 4.75% rate
  • switch to inflation + 1.50%
  • annual payout taxation
  • OKO mode with a separate cash-account ledger
  • Excel-aligned OKO checkpoints across a 12-year reference horizon
  • lack of capitalization inside the same batch
  • natural 4-year redemption
  • early redemption after 1, 2, and 3 years through direct and golden references
  • reinvestment from accumulated annual cash
  • public result contract and strategy id
  • long-horizon stability
  • shared annual-payout invariant grid

Traceability

  • product duration, payout, tax, reinvestment:
  • coi.strategy.test.ts: tests/coi.strategy.test.ts
  • first-year fixed payout rate:
    • COI first year uses the dedicated 4.75% rate and pays taxed interest into cash
  • later-year inflation + margin payout:
    • COI switches from year-one fixed rate to inflation + 1.50% in later years
  • no capitalization rule:
    • COI pays out annual interest instead of capitalizing it into the same batch
  • natural maturity:
    • COI natural 4-year redemption returns principal after annual payouts without early cost
  • reinvestment from cash pool:
    • COI reinvests accumulated annual net payouts and redeemed principal into new batches
  • shared carried-value vs liquidation semantics:
  • annual-payout.strategy.test.ts: tests/annual-payout.strategy.test.ts
  • purchase, payout, and redemption history retention:
  • coi.strategy.test.ts: tests/coi.strategy.test.ts
  • annual-payout.strategy.test.ts: tests/annual-payout.strategy.test.ts

Contract Boundary

COI uses payoutEvents, which are part of the shared simulation contract in:

  • bonds.ts: src/app/types/bonds.ts

This is intentional:

  • COI and future annual-payout products need explicit payout history
  • annual-accumulation products do not
  • monthly-income products use different event families instead

Keep this as an optional event branch in the shared simulation contract rather than forcing all strategies to expose identical event shapes.

Change Rules

If COI logic changes, update together:

  • annual-payout.ts: src/app/domain/bond-engine/strategies/annual-payout.ts
  • annual_payout_logic.md
  • coi.ts: src/app/domain/bond-engine/strategies/coi.ts
  • coi.strategy.test.ts: tests/coi.strategy.test.ts
  • COI_logic.md
  • init_prompt.md: ai/init_prompt.md