Skip to content

Commit 92adceb

Browse files
committed
FEAT: Work on BF IBNR Exhibit.
1 parent 08d93fc commit 92adceb

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

faslr/methods/bornhuetter.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import numpy as np
4+
35
from faslr.base_table import FTableView
46

57
from faslr.model import (
@@ -9,11 +11,24 @@
911
FModelWidget
1012
)
1113

14+
from faslr.style.triangle import (
15+
PERCENT_STYLE,
16+
RATIO_STYLE,
17+
VALUE_STYLE
18+
)
19+
1220
from faslr.methods.expected_loss import (
1321
ExpectedLossAprioriWidget,
1422
ExpectedLossRatioWidget
1523
)
1624

25+
from faslr.utilities import (
26+
fetch_cdf,
27+
fetch_latest_diagonal,
28+
fetch_origin,
29+
fetch_ultimate
30+
)
31+
1732
from PyQt6.QtCore import (
1833
Qt
1934
)
@@ -24,7 +39,7 @@
2439
QTabWidget
2540
)
2641

27-
from typing import TYPE_CHECKING
42+
from typing import TYPE_CHECKING, Any
2843

2944
if TYPE_CHECKING:
3045
from chainladder import Chainladder
@@ -103,14 +118,60 @@ def __init__(
103118
):
104119
super().__init__(parent=parent)
105120
self._data['On-Level Earned Premium'] = self.parent.parent.apriori_tab.model._data['On-Level Earned Premium']
106-
self._data['Paid Losses'] = self.parent.parent.apriori_tab.model._data['Paid Losses']
107-
self._data['Reported Losses'] = self.parent.parent.apriori_tab.model._data['Reported Losses']
108121
self._data = self._data.rename(columns={'Selected Averages': 'Selected Loss Ratio'})
122+
self._data['Expected Claims'] = self._data['Selected Loss Ratio'] * self._data['On-Level Earned Premium']
123+
self._data['Reported CDF'] = np.maximum(1, self.parent.parent.apriori_tab.model._data['Reported CDF'])
124+
self._data['Paid CDF'] = np.maximum(1, self.parent.parent.apriori_tab.model._data['Paid CDF'])
125+
self._data['% Unreported'] = 1 - self._data['Reported CDF'] ** (-1)
126+
self._data['% Unpaid'] = 1 - self._data['Paid CDF'] ** (-1)
127+
self._data['Expected Unreported'] = self._data['% Unreported'] * self._data['Expected Claims']
128+
self._data['Expected Unpaid'] = self._data['% Unpaid'] * self._data['Expected Claims']
129+
self._data['Reported Losses'] = self.parent.parent.apriori_tab.model._data['Reported Losses']
130+
self._data['Paid Losses'] = self.parent.parent.apriori_tab.model._data['Paid Losses']
131+
self._data['Ultimate BF Reported'] = self._data['Expected Unreported'] + self._data['Reported Losses']
132+
self._data['Ultimate BF Paid'] = self._data['Expected Unpaid'] + self._data['Paid Losses']
133+
self._data['Case Outstanding'] = self._data['Reported Losses'] - self._data['Paid Losses']
134+
self._data['BF Reported IBNR'] = self._data['Ultimate BF Reported'] - self._data['Reported Losses']
135+
self._data['BF Paid IBNR'] = self._data['Ultimate BF Paid'] - self._data['Reported Losses']
136+
self._data['BF Reported Unpaid Claims'] = self._data['Ultimate BF Reported'] - self._data['Paid Losses']
137+
self._data['BF Paid Unpaid Claims'] = self._data['Ultimate BF Paid'] - self._data['Paid Losses']
138+
139+
140+
def data(self, index, role = ...) -> Any:
141+
if role == Qt.ItemDataRole.DisplayRole:
142+
143+
value = self._data.iloc[index.row(), index.column()]
144+
col = self._data.columns[index.column()]
145+
146+
if np.isnan(value):
147+
return ""
148+
elif col in [
149+
'Selected Loss Ratio',
150+
'% Unreported',
151+
'% Unpaid'
152+
]:
153+
return PERCENT_STYLE.format(value)
154+
elif col in [
155+
'Reported CDF',
156+
'Paid CDF'
157+
]:
158+
return RATIO_STYLE.format(value)
159+
else:
160+
return VALUE_STYLE.format(value)
109161

110162
def setData(self, index, value, role = ...) -> bool:
111163

112164
if role == Qt.ItemDataRole.EditRole:
113165
self._data['Selected Loss Ratio'] = self.parent_model.selected_ratios_row.T['Selected Averages']
166+
self._data['Expected Claims'] = self._data['Selected Loss Ratio'] * self._data['On-Level Earned Premium']
167+
self._data['Expected Unreported'] = self._data['% Unreported'] * self._data['Expected Claims']
168+
self._data['Expected Unpaid'] = self._data['% Unpaid'] * self._data['Expected Claims']
169+
self._data['Ultimate BF Reported'] = self._data['Expected Unreported'] + self._data['Reported Losses']
170+
self._data['Ultimate BF Paid'] = self._data['Expected Unpaid'] + self._data['Paid Losses']
171+
self._data['BF Reported IBNR'] = self._data['Ultimate BF Reported'] - self._data['Reported Losses']
172+
self._data['BF Paid IBNR'] = self._data['Ultimate BF Paid'] - self._data['Reported Losses']
173+
self._data['BF Reported Unpaid Claims'] = self._data['Ultimate BF Reported'] - self._data['Paid Losses']
174+
self._data['BF Paid Unpaid Claims'] = self._data['Ultimate BF Paid'] - self._data['Paid Losses']
114175

115176
self.dataChanged.emit(index, index)
116177
self.layoutChanged.emit()

0 commit comments

Comments
 (0)