-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSichereEntnahme.py
133 lines (98 loc) · 4.12 KB
/
SichereEntnahme.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'''
Vorsicht vor der 4%-Regel
Sicher Entnahmerate
https://www.finanzen-erklaert.de/vorsicht-vor-der-4-regel/
'''
import pandas as pd
import time
from SEsimulation.mDate import mDate
from SEsimulation import SEsimulation
import plotly.express as px
import numpy as np
def optimize(s, probability, loBound, hiBound):
""" Optimiere auf die max. mögliche Entnahme bei einer vorgegebenen Fehlerquote
Returns:
widthdrawal: max. mögliche prozentuale Entnahme
"""
n_ret_months = s.simulation['n_ret_years'] * 12
accuracy = 0.01 # Genauigkeit der Optimierung
# Vorbereitung der Optimierung
deltaWidthdrawal = (hiBound - loBound) / 2
percWidthdrawal = loBound + deltaWidthdrawal
cnt = 0
curProb = 0
# Optimization by successiv approximation
while (deltaWidthdrawal > accuracy) or (curProb > probability):
cnt += 1
s.withdrawal['fixed_pct'] = percWidthdrawal
s.init_simulation()
s.simulate()
survival = [trial_dict['exhaustion'] for trial_dict in s.latest_simulation]
curProb = 100 * (len(survival) - survival.count(n_ret_months)) / len(survival)
if s.visualization['textoutput'] == True:
print(cnt, '. Entnahme: ', percWidthdrawal, ' Ausfallwahrscheinlichkeit: ', curProb, '%')
deltaWidthdrawal /= 2
if deltaWidthdrawal <= accuracy / 10:
break
if curProb > probability:
percWidthdrawal -= deltaWidthdrawal
else:
percWidthdrawal += deltaWidthdrawal
return percWidthdrawal
print('Start')
starttime = time.time()
# Lesen monatliche S&P500 Daten
RETURN_FILE = 'real_return_df.pickle'
real_return_df = pd.read_pickle(RETURN_FILE)
# Konfiguration der Entnahme Simulation
config = {
'date': {'start': mDate(1, 2022), # Start Datum
'start_retirement': mDate(1, 2022)}, # Start der Entnahme
'assets': {'depot': 500000, # Depotvolumen zum Startzeitpunkt
'fees': 0.00}, # Jährliche Depotgebühren in %
'simulation': {'returns_df': real_return_df, # S&P500 Daten
'n_ret_years': 30}, # Simulationsdauer in Jahren
'withdrawal': {'fixed_pct': 4.0}, # Proz. Entnahmerate pro Jahr vom Startdepot
'pension': {'point': np.array([0]), # Anzahl erworbener Rentenpunkte
'point_add': np.array([0.0]), # Rentenpunktzuwachs pro Jahr
'start_date': [mDate(1, 3000)], # Beginn der gesetzlichen Rente
'name': {'John Doe'}, # Name des Rentenbeziehers
'point_value': 0.0, # aktueller Rentenpunktwert
'point_value_inc': 0.0}, # Proz. Steigerung des Rentenpunktwertes
'visualization': {'textoutput': True} # Textueller Zwischenausgaben als Debug Info
}
err_rates = [0.0, 0.1, 0.5, 1.0] # Fehlerraten [%]
years = [10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 35, 39, 44, 49, 55, 60] # Dauer der Entnahme in Jahre
df = pd.DataFrame(columns=err_rates, index=years)
# Optimierungsgrenzen der proz. Entnahme:
loBound = 2 # Untere Grenze der Optimierung
hiBound = 8 # Obere Grenze der Optimierung
column_indexer = 0
for err_rate in err_rates:
row_indexer = 0
hiBound = 8
for year in years:
# Update Laufzeit
config['simulation']['n_ret_years'] = year
s = SEsimulation.SEsimulation(config)
widthdraw = optimize(s, err_rate, loBound, hiBound)
print('\n', year, ' Jahre, Entnahme: ', widthdraw, '% @Risk: ', err_rate, '%\n')
df.iloc[row_indexer, column_indexer] = widthdraw
row_indexer += 1
hiBound = widthdraw
column_indexer += 1
fig = px.line(df)
fig.update_layout(
title="Sichere jährliche Entnahmerate nach Laufzeit mit Inflationsanpassung",
xaxis_title="Laufzeit [Jahre]",
yaxis_title="Sichere Entnahme [%]",
legend_title="Fehlerquote [%]",
font=dict(
family="Courier New, monospace",
size=18,
color="RebeccaPurple"
)
)
fig.show()
endTime = time.time()
print('\nSimulationsdauer: %5.2f sec.' % (endTime - starttime))