24
24
logger = get_module_logger ("Evaluate" )
25
25
26
26
27
- def risk_analysis (r , N : int = None , freq : str = "day" ):
27
+ def risk_analysis (r , N : int = None , freq : str = "day" , accumulation_mode = "summation" ):
28
28
"""Risk Analysis
29
29
NOTE:
30
30
The calculation of annulaized return is different from the definition of annualized return.
31
31
It is implemented by design.
32
32
Qlib tries to cumulated returns by summation instead of production to avoid the cumulated curve being skewed exponentially.
33
33
All the calculation of annualized returns follows this principle in Qlib.
34
34
35
- TODO: add a parameter to enable calculating metrics with production accumulation of return.
36
-
37
35
Parameters
38
36
----------
39
37
r : pandas.Series
@@ -42,6 +40,8 @@ def risk_analysis(r, N: int = None, freq: str = "day"):
42
40
scaler for annualizing information_ratio (day: 252, week: 50, month: 12), at least one of `N` and `freq` should exist
43
41
freq: str
44
42
analysis frequency used for calculating the scaler, at least one of `N` and `freq` should exist
43
+ accumulation_mode: str
44
+ the mode of calculating the cumulative return, options are 'exponential' and 'summation'
45
45
"""
46
46
47
47
def cal_risk_analysis_scaler (freq ):
@@ -61,10 +61,16 @@ def cal_risk_analysis_scaler(freq):
61
61
warnings .warn ("risk_analysis freq will be ignored" )
62
62
if N is None :
63
63
N = cal_risk_analysis_scaler (freq )
64
+
65
+ if accumulation_mode not in ["summation" , "exponential" ]:
66
+ raise ValueError ("Invalid value for `accumulation_mode`. Only 'summation' and 'exponential' are supported" )
64
67
65
68
mean = r .mean ()
66
69
std = r .std (ddof = 1 )
67
- annualized_return = mean * N
70
+ if accumulation_mode == "summation" :
71
+ annualized_return = mean * N
72
+ else :
73
+ annualized_return = (np .prod (1 + r ) - 1 )
68
74
information_ratio = mean / std * np .sqrt (N )
69
75
max_drawdown = (r .cumsum () - r .cumsum ().cummax ()).min ()
70
76
data = {
0 commit comments