Skip to content

Commit 884c671

Browse files
Implement exponential mode for annualized_return calculation in risk_analysis
Resolves microsoft#964
1 parent 6295939 commit 884c671

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

qlib/contrib/evaluate.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,14 @@
2424
logger = get_module_logger("Evaluate")
2525

2626

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"):
2828
"""Risk Analysis
2929
NOTE:
3030
The calculation of annulaized return is different from the definition of annualized return.
3131
It is implemented by design.
3232
Qlib tries to cumulated returns by summation instead of production to avoid the cumulated curve being skewed exponentially.
3333
All the calculation of annualized returns follows this principle in Qlib.
3434
35-
TODO: add a parameter to enable calculating metrics with production accumulation of return.
36-
3735
Parameters
3836
----------
3937
r : pandas.Series
@@ -42,6 +40,8 @@ def risk_analysis(r, N: int = None, freq: str = "day"):
4240
scaler for annualizing information_ratio (day: 252, week: 50, month: 12), at least one of `N` and `freq` should exist
4341
freq: str
4442
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'
4545
"""
4646

4747
def cal_risk_analysis_scaler(freq):
@@ -61,10 +61,16 @@ def cal_risk_analysis_scaler(freq):
6161
warnings.warn("risk_analysis freq will be ignored")
6262
if N is None:
6363
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")
6467

6568
mean = r.mean()
6669
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)
6874
information_ratio = mean / std * np.sqrt(N)
6975
max_drawdown = (r.cumsum() - r.cumsum().cummax()).min()
7076
data = {

0 commit comments

Comments
 (0)