Skip to main content

Analysis Example: Variable Rate Annuity Contract

This end-to-end example demonstrates how to define, simulate, and analyze a variable-rate Annuity (ANN) contract using the Awesome Actus Library (AAL).

0. Setup and Imports

import numpy as np
import pandas as pd
from awesome_actus_lib import ANN, ReferenceIndex, PublicActusService, LiquidityAnalysis, ValueAnalysis, IncomeAnalysis
np.random.seed(42) # for reproducability

1. Define the Contract

We define an annuity contract that pays interest and principal annually and resets its rate every 6 months based on a reference index.

ann = ANN(
contractID="ann1",
creatorID="me",
counterpartyID="bank",
notionalPrincipal=20000,
nominalInterestRate=0.04,
dayCountConvention="30E360",
contractRole="RPA",
statusDate="2024-12-31",
initialExchangeDate="2025-01-01",
maturityDate="2030-01-01",
contractDealDate="2024-12-31",
currency="USD",
cycleOfInterestPayment="P1YL1",
cycleOfPrincipalRedemption="P1YL1",
cycleAnchorDateOfInterestPayment="2026-01-01",
cycleAnchorDateOfPrincipalRedemption="2026-01-01",
cycleOfRateReset="P6ML1",
marketObjectCodeOfRateReset="UST5Y",
rateSpread=0.01
)

2. Simulate Reference Index (UST5Y)

We generate a synthetic interest rate index (UST5Y) with 20 semiannual points from 2023 to 2030.

index_data = pd.DataFrame({
"date": pd.date_range(start="2023-01-01", end="2030-12-31", periods=20).strftime("%Y-%m-%d"),
"value": np.random.uniform(0.01, 0.08, size=20).round(4)
})
ust5y = ReferenceIndex(marketObjectCode="UST5Y", source=index_data, base=1.0)
ust5y.plot()

UST5Y Plot

3. Generate Cash Flow Events

Using the contract and index, we generate future cash flow events (principal, interest, etc.).

service = PublicActusService()
events = service.generateEvents(portfolio=ann, riskFactors=ust5y)
events.plot()

Cashflows

Event Table

typetimepayoffcurrencynominalValuenominalRatenominalAccruedcontractId
IED2025-01-01T00:00-20000USD200000.040ann1
RR2025-01-01T00:000USD200000.03090ann1
PRF2025-01-01T00:000USD200000.03090ann1
RR2025-07-01T00:000USD200000.0309309ann1
PRF2025-07-01T00:000USD200000.0309309ann1
PRF2025-12-31T00:000USD200000.0309616.283ann1
PR2026-01-01T00:003760.32USD16239.70.0309618ann1
IP2026-01-01T00:00618USD16239.70.03090ann1
RR2026-01-01T00:000USD16239.70.08060ann1
PRF2026-01-01T00:000USD16239.70.08060ann1
RR2026-07-01T00:000USD16239.70.0621654.459ann1
PRF2026-07-01T00:000USD16239.70.0621654.459ann1
PR2027-01-01T00:003591.5USD12648.20.06211158.7ann1
IP2027-01-01T00:001158.7USD12648.20.06210ann1
RR2027-01-01T00:000USD12648.20.06960ann1
PRF2027-01-01T00:000USD12648.20.06960ann1
RR2027-07-01T00:000USD12648.20.0214440.157ann1
PRF2027-07-01T00:000USD12648.20.0214440.157ann1
PR2028-01-01T00:003926.05USD8722.120.0214575.492ann1
IP2028-01-01T00:00575.492USD8722.120.02140ann1
RR2028-01-01T00:000USD8722.120.08790ann1
PRF2028-01-01T00:000USD8722.120.08790ann1
RR2028-07-01T00:000USD8722.120.0349383.337ann1
PRF2028-07-01T00:000USD8722.120.0349383.337ann1
PR2029-01-01T00:004172.68USD4549.440.0349535.538ann1
IP2029-01-01T00:00535.538USD4549.440.03490ann1
RR2029-01-01T00:000USD4549.440.03270ann1
PRF2029-01-01T00:000USD4549.440.03270ann1
RR2029-07-01T00:000USD4549.440.032874.3834ann1
PRF2029-07-01T00:000USD4549.440.032874.3834ann1
IP2030-01-01T00:00148.994USD4549.440.03280ann1
MD2030-01-01T00:004549.44USD00.03280ann1

4. Liquidity Analysis

Yearly net cash flows are analyzed to identify funding needs or surpluses.

liq = LiquidityAnalysis(cf_stream=events, freq="Y")
liq.plot()

Liquidity

      netLiquidity
time
2025 -20000.000000
2026 4378.319824
2027 4750.203489
2028 4501.546054
2029 4708.218944
2030 4698.437641

5. Value Analysis

Discounted value of future cash flows as of 2025-01-01 using a 2% flat rate.

val = ValueAnalysis(cf_stream=events, as_of_date="2025-01-01", flat_rate=0.02)
  as_of_date  nominal_value         npv
0 2025-01-01 3036.725952 296.344084

6. Income Analysis

Annual income flows based on the contract’s interest components.

inc = IncomeAnalysis(cf_stream=events, freq="Y")
inc.plot()

Income

        netIncome
time
2026 618.000000
2027 1158.701181
2028 575.492093
2029 535.538408
2030 148.994270