Fixed Income Effects¶
1. Calculation Name¶
Fixed Income Factor Effects (Income, Roll, Curve, Spread, FX, Selection)
2. Description and Mathematical Formula¶
The effects plugin breaks absolute performance into additive components derived from portfolio-level key-rate exposures:
\[ \mathrm{Total\ Return} = \mathrm{Income} + \mathrm{Roll} + \mathrm{Curve} + \mathrm{Spread} + \mathrm{FX} + \mathrm{Selection} \]
Each component is computed from mappings such as DV01 (curve), SDV01 (spread), and FX notional. For example:
- Roll \( = \sum_{k} \mathrm{RollDV01}_{k} \times \Delta \text{roll}_{k} \)
- Curve \( = \sum_{k} \mathrm{KRD}_{k} \times \Delta y_{k} \)
- Spread \( = \sum_{k} \mathrm{SDV01}_{k} \times \Delta s_{k} \)
3. Input Sample Data¶
| Date | Income (bps) | Roll (bps) | Curve (bps) | Spread (bps) | FX (bps) | Selection (bps) | Total Return (bps) | DV01 Total | SDV01 Total |
|---|---|---|---|---|---|---|---|---|---|
| 2024-01-05 | 12.5 | 4.3 | -1.2 | 3.8 | 0.5 | 2.1 | 22.0 | 145 | 90 |
| 2024-01-12 | 12.7 | 4.1 | -0.8 | 4.2 | 0.4 | 1.9 | 22.5 | 146 | 91 |
| 2024-01-19 | 12.6 | 3.9 | -0.5 | 3.6 | -0.2 | 2.0 | 21.4 | 144 | 88 |
| 2024-01-26 | 12.8 | 3.5 | -1.0 | 4.5 | -0.1 | 2.2 | 21.9 | 143 | 87 |
| 2024-02-02 | 13.0 | 3.2 | -0.7 | 4.0 | 0.3 | 2.4 | 22.2 | 142 | 89 |
4. Mathematical Solution¶
- Row check (2024-01-05):
\( 12.5 + 4.3 - 1.2 + 3.8 + 0.5 + 2.1 = 22.0 \) bps - DV01/SDV01 columns track interest-rate and spread sensitivity totals used to derive roll/curve/spread components.
- Horizon totals:
- Income sum = 63.6 bps
- Roll sum = 19.0 bps
- Curve sum = -4.2 bps
- Spread sum = 20.1 bps
- FX sum = 0.9 bps
- Selection sum = 10.6 bps
- Total return sum = 109.0 bps
- The equality holds for each row and in aggregate, providing a consistent decomposition.
5. Sample Python and R Code¶
import pandas as pd
data = pd.DataFrame(
{
"date": pd.to_datetime(["2024-01-05", "2024-01-12", "2024-01-19", "2024-01-26", "2024-02-02"]),
"income": [12.5, 12.7, 12.6, 12.8, 13.0],
"roll": [4.3, 4.1, 3.9, 3.5, 3.2],
"curve": [-1.2, -0.8, -0.5, -1.0, -0.7],
"spread": [3.8, 4.2, 3.6, 4.5, 4.0],
"fx": [0.5, 0.4, -0.2, -0.1, 0.3],
"selection": [2.1, 1.9, 2.0, 2.2, 2.4],
}
)
components = ["income", "roll", "curve", "spread", "fx", "selection"]
data["total"] = data[components].sum(axis=1)
totals = data[components + ["total"]].sum()
print(data)
print(totals)
library(dplyr)
data <- tibble::tibble(
date = as.Date(c("2024-01-05", "2024-01-12", "2024-01-19", "2024-01-26", "2024-02-02")),
income = c(12.5, 12.7, 12.6, 12.8, 13.0),
roll = c(4.3, 4.1, 3.9, 3.5, 3.2),
curve = c(-1.2, -0.8, -0.5, -1.0, -0.7),
spread = c(3.8, 4.2, 3.6, 4.5, 4.0),
fx = c(0.5, 0.4, -0.2, -0.1, 0.3),
selection = c(2.1, 1.9, 2.0, 2.2, 2.4)
)
components <- c("income", "roll", "curve", "spread", "fx", "selection")
data <- data %>%
mutate(total = rowSums(across(all_of(components))))
totals <- summarise(data, across(all_of(c(components, "total")), sum))
data
totals
6. Output Table¶
| Component | Sum (bps) |
|---|---|
| Income | 63.6 |
| Roll | 19.0 |
| Curve | -4.2 |
| Spread | 20.1 |
| FX | 0.9 |
| Selection | 10.6 |
| Total Return | 109.0 |
7. Conclusion¶
The fixed-income effects view translates complex exposure data into an intuitive factor breakdown. This template mirrors the plugin’s table layout, making it a solid reference for report authors and QA engineers validating curve or spread mappings.