Coverage for src/ifunnel/models/lifecycle/glidePathCreator.py: 0%

19 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-12 09:14 +0000

1import numpy as np 

2import pandas as pd 

3import plotly.express as px 

4 

5 

6def generate_risk_profiles(n_periods: int, initial_risk: float, minimum_risk: float) -> (pd.DataFrame, px.line): 

7 """Generate risk profiles for glide paths.""" 

8 

9 df = pd.DataFrame(index=range(n_periods)) 

10 x_values = np.linspace(0, 1, n_periods) 

11 

12 df["Linear GP"] = np.linspace(initial_risk, minimum_risk, n_periods) 

13 df["Concave GP"] = initial_risk - (initial_risk - minimum_risk) * (x_values**2) 

14 df["Convex GP"] = initial_risk - (initial_risk - minimum_risk) * np.sqrt(x_values) 

15 

16 fig = px.line( 

17 df, 

18 labels={"value": "Risk", "index": "Period"}, 

19 title="Risk Budget Glide Paths", 

20 ).update_traces(mode="lines") 

21 fig.update_layout( 

22 yaxis_title="Annual Standard Deviation", 

23 xaxis_title="Period", 

24 legend_title="Risk Budget Glide Paths", 

25 height=900, 

26 width=1500, 

27 template="plotly_white", 

28 ) 

29 

30 # Update y-axis properties 

31 fig.update_yaxes( 

32 showgrid=True, 

33 showline=True, 

34 gridcolor="rgba(211, 211, 211, 0.5)", 

35 tickformat=".0%", 

36 title_font=dict(size=15), 

37 range=[0, initial_risk * 1.1], 

38 ) 

39 # Update x-axis properties, setting it to reverse 

40 fig.update_xaxes( 

41 showgrid=False, 

42 showline=True, 

43 title_font=dict(size=15), 

44 gridcolor="rgba(211, 211, 211, 0.5)", 

45 ) 

46 

47 # Colors and line width 

48 colors = [ 

49 "#99A4AE", # gray50 

50 "#3b4956", # dark 

51 "#b7ada5", # secondary 

52 "#4099da", # blue 

53 "#8ecdc8", # aqua 

54 "#e85757", # coral 

55 "#fdd779", # sun 

56 "#644c76", # eggplant 

57 "#D8D1CA", # warmGray50 

58 # Additional colors if needed 

59 ] 

60 

61 for i, trace in enumerate(fig.data): 

62 trace.line.color = colors[i % len(colors)] 

63 trace.line.width = 2.5 

64 

65 fig.layout.yaxis.tickformat = ",.1%" 

66 

67 # fig.show() 

68 return df, fig