-
Notifications
You must be signed in to change notification settings - Fork 83
/
stats.py
69 lines (63 loc) · 2.03 KB
/
stats.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
# from https://github.com/esvhd/pypbo/blob/master/pypbo/pbo.py
import scipy.stats as ss
import numpy as np
def psr(sharpe, T, skew, kurtosis, target_sharpe=0):
"""
Probabilistic Sharpe Ratio.
Parameters:
sharpe:
observed sharpe ratio, in same frequency as T.
T:
no. of observations, should match return / sharpe sampling period.
skew:
sharpe ratio skew
kurtosis:
sharpe ratio kurtosis
target_sharpe:
target sharpe ratio
Returns:
Cumulative probabilities for observed sharpe ratios under standard
Normal distribution.
"""
value = (
(sharpe - target_sharpe)
* np.sqrt(T - 1)
/ np.sqrt(1.0 - skew * sharpe + sharpe ** 2 * (kurtosis - 1) / 4.0)
)
psr = ss.norm.cdf(value, 0, 1)
return psr
def expected_max(N):
"""
Expected maximum of IID random variance X_n ~ Z, n = 1,...,N,
where Z is the CDF of the standard Normal distribution,
E[MAX_n] = E[max{x_n}]. Computed for a large N.
"""
if N < 5:
raise AssertionError("Condition N >> 1 not satisfied.")
return (1 - np.euler_gamma) * ss.norm.ppf(
1 - 1.0 / N
) + np.euler_gamma * ss.norm.ppf(1 - np.exp(-1) / N)
def dsr(test_sharpe, sharpe_std, N, T, skew, kurtosis):
"""
Deflated Sharpe Ratio statistic. DSR = PSR(SR_0).
See paper for definition of SR_0. http://ssrn.com/abstract=2460551
Parameters:
test_sharpe :
reported sharpe, to be tested.
sharpe_std :
standard deviation of sharpe ratios from N trials / configurations
N :
number of backtest configurations
T :
number of observations
skew :
skew of returns
kurtosis :
kurtosis of returns
Returns:
DSR statistic
"""
# sharpe_std = np.std(sharpe_n, ddof=1)
target_sharpe = sharpe_std * expected_max(N)
dsr_stat = psr(test_sharpe, T, skew, kurtosis, target_sharpe)
return dsr_stat