squarequant 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- squarequant/__init__.py +41 -0
- squarequant/api.py +548 -0
- squarequant/constants.py +35 -0
- squarequant/core/__init__.py +6 -0
- squarequant/core/base.py +166 -0
- squarequant/core/data.py +106 -0
- squarequant/core/metrics.py +1633 -0
- squarequant/plot/__init__.py +7 -0
- squarequant/plot/plot.py +972 -0
- squarequant/utils/__init__.py +6 -0
- squarequant/utils/helpers.py +85 -0
- squarequant-0.1.0.dist-info/LICENSE +21 -0
- squarequant-0.1.0.dist-info/METADATA +217 -0
- squarequant-0.1.0.dist-info/RECORD +16 -0
- squarequant-0.1.0.dist-info/WHEEL +5 -0
- squarequant-0.1.0.dist-info/top_level.txt +1 -0
squarequant/__init__.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# squarequant/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
SquareQuant: A Python package for financial risk metrics and stock data analysis
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = '0.1.0'
|
|
7
|
+
|
|
8
|
+
# Import main functions for easy access
|
|
9
|
+
from squarequant.core.data import download_tickers, DownloadConfig
|
|
10
|
+
from squarequant.core.metrics import (
|
|
11
|
+
SharpeRatio,
|
|
12
|
+
SortinoRatio,
|
|
13
|
+
Volatility,
|
|
14
|
+
MaximumDrawdown,
|
|
15
|
+
ValueAtRisk,
|
|
16
|
+
CalmarRatio,
|
|
17
|
+
ConditionalValueAtRisk,
|
|
18
|
+
SemiDeviation,
|
|
19
|
+
AverageDrawdown,
|
|
20
|
+
UlcerIndex,
|
|
21
|
+
MeanAbsoluteDeviation,
|
|
22
|
+
EntropicRiskMeasure,
|
|
23
|
+
EntropicValueAtRisk,
|
|
24
|
+
ConditionalDrawdownAtRisk,
|
|
25
|
+
EntropicDrawdownAtRisk
|
|
26
|
+
)
|
|
27
|
+
from squarequant.api import sharpe, sortino, vol, mdd, var, calmar, cvar, semidev, avgdd, ulcer, mad, erm, evar, cdar, edar
|
|
28
|
+
|
|
29
|
+
# Import plotting functions
|
|
30
|
+
from squarequant.plot.plot import (
|
|
31
|
+
plot_rolling_metrics,
|
|
32
|
+
plot_correlation_matrix,
|
|
33
|
+
plot_drawdown,
|
|
34
|
+
plot_risk_comparison,
|
|
35
|
+
plot_performance_metrics,
|
|
36
|
+
plot_risk_contribution,
|
|
37
|
+
plot_returns_distribution,
|
|
38
|
+
plot_multiple_drawdowns,
|
|
39
|
+
plot_volatility_comparison,
|
|
40
|
+
plot_weight_allocation
|
|
41
|
+
)
|
squarequant/api.py
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Function-based API for the SquareQuant package
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from squarequant.constants import (
|
|
9
|
+
TRADING_DAYS_PER_YEAR,
|
|
10
|
+
DEFAULT_SHARPE_WINDOW,
|
|
11
|
+
DEFAULT_SORTINO_WINDOW,
|
|
12
|
+
DEFAULT_VOLATILITY_WINDOW,
|
|
13
|
+
DEFAULT_DRAWDOWN_WINDOW,
|
|
14
|
+
DEFAULT_VAR_WINDOW,
|
|
15
|
+
DEFAULT_CALMAR_WINDOW,
|
|
16
|
+
DEFAULT_CVAR_WINDOW,
|
|
17
|
+
DEFAULT_CONFIDENCE,
|
|
18
|
+
DEFAULT_SEMIDEVIATION_WINDOW,
|
|
19
|
+
DEFAULT_AVGDRAWDOWN_WINDOW,
|
|
20
|
+
DEFAULT_ULCER_WINDOW,
|
|
21
|
+
DEFAULT_MAD_WINDOW,
|
|
22
|
+
DEFAULT_ERM_WINDOW,
|
|
23
|
+
DEFAULT_EVAR_WINDOW,
|
|
24
|
+
DEFAULT_CDAR_WINDOW,
|
|
25
|
+
DEFAULT_EDAR_WINDOW,
|
|
26
|
+
DEFAULT_VAR_HOLDING_PERIOD,
|
|
27
|
+
DEFAULT_VAR_CONFIDENCE
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from squarequant.core.metrics import (
|
|
31
|
+
SharpeRatio,
|
|
32
|
+
SortinoRatio,
|
|
33
|
+
Volatility,
|
|
34
|
+
MaximumDrawdown,
|
|
35
|
+
ValueAtRisk,
|
|
36
|
+
CalmarRatio,
|
|
37
|
+
ConditionalValueAtRisk,
|
|
38
|
+
SemiDeviation,
|
|
39
|
+
AverageDrawdown,
|
|
40
|
+
UlcerIndex,
|
|
41
|
+
MeanAbsoluteDeviation,
|
|
42
|
+
EntropicRiskMeasure,
|
|
43
|
+
EntropicValueAtRisk,
|
|
44
|
+
ConditionalDrawdownAtRisk,
|
|
45
|
+
EntropicDrawdownAtRisk
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def sharpe(data: pd.DataFrame,
|
|
50
|
+
assets: List[str],
|
|
51
|
+
freerate: Optional[str] = None,
|
|
52
|
+
freerate_value: Optional[float] = None,
|
|
53
|
+
window: int = DEFAULT_SHARPE_WINDOW,
|
|
54
|
+
start: Optional[str] = None,
|
|
55
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
56
|
+
"""
|
|
57
|
+
Calculate rolling Sharpe ratios for specified assets
|
|
58
|
+
|
|
59
|
+
Parameters:
|
|
60
|
+
data (DataFrame): DataFrame with asset price data
|
|
61
|
+
assets (List[str]): List of asset columns to calculate for
|
|
62
|
+
freerate (str, optional): Column name for risk-free rate in data DataFrame
|
|
63
|
+
freerate_value (float, optional): Constant risk-free rate to use if no column provided
|
|
64
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
65
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
66
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
DataFrame: Rolling Sharpe ratios for specified assets
|
|
70
|
+
"""
|
|
71
|
+
calculator = SharpeRatio(
|
|
72
|
+
data=data,
|
|
73
|
+
assets=assets,
|
|
74
|
+
freerate=freerate,
|
|
75
|
+
freerate_value=freerate_value,
|
|
76
|
+
window=window,
|
|
77
|
+
start=start,
|
|
78
|
+
end=end
|
|
79
|
+
)
|
|
80
|
+
return calculator.calculate()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def sortino(data: pd.DataFrame,
|
|
84
|
+
assets: List[str],
|
|
85
|
+
freerate: Optional[str] = None,
|
|
86
|
+
freerate_value: Optional[float] = None,
|
|
87
|
+
window: int = DEFAULT_SORTINO_WINDOW,
|
|
88
|
+
start: Optional[str] = None,
|
|
89
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
90
|
+
"""
|
|
91
|
+
Calculate rolling Sortino ratios for specified assets
|
|
92
|
+
|
|
93
|
+
Parameters:
|
|
94
|
+
data (DataFrame): DataFrame with asset price data
|
|
95
|
+
assets (List[str]): List of asset columns to calculate for
|
|
96
|
+
freerate (str, optional): Column name for risk-free rate in data DataFrame
|
|
97
|
+
freerate_value (float, optional): Constant risk-free rate to use if no column provided
|
|
98
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
99
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
100
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
DataFrame: Rolling Sortino ratios for specified assets
|
|
104
|
+
"""
|
|
105
|
+
calculator = SortinoRatio(
|
|
106
|
+
data=data,
|
|
107
|
+
assets=assets,
|
|
108
|
+
freerate=freerate,
|
|
109
|
+
freerate_value=freerate_value,
|
|
110
|
+
window=window,
|
|
111
|
+
start=start,
|
|
112
|
+
end=end
|
|
113
|
+
)
|
|
114
|
+
return calculator.calculate()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def vol(data: pd.DataFrame,
|
|
118
|
+
assets: List[str],
|
|
119
|
+
window: int = DEFAULT_VOLATILITY_WINDOW,
|
|
120
|
+
start: Optional[str] = None,
|
|
121
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
122
|
+
"""
|
|
123
|
+
Calculate annualized rolling volatility for specified assets
|
|
124
|
+
|
|
125
|
+
Parameters:
|
|
126
|
+
data (DataFrame): DataFrame with asset price data
|
|
127
|
+
assets (List[str]): List of asset columns to calculate for
|
|
128
|
+
window (int): Rolling window size in trading days, default is 10 days
|
|
129
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
130
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
DataFrame: Rolling annualized volatility for specified assets
|
|
134
|
+
"""
|
|
135
|
+
calculator = Volatility(
|
|
136
|
+
data=data,
|
|
137
|
+
assets=assets,
|
|
138
|
+
window=window,
|
|
139
|
+
start=start,
|
|
140
|
+
end=end
|
|
141
|
+
)
|
|
142
|
+
return calculator.calculate()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def mdd(data: pd.DataFrame,
|
|
146
|
+
assets: List[str],
|
|
147
|
+
window: int = DEFAULT_DRAWDOWN_WINDOW,
|
|
148
|
+
start: Optional[str] = None,
|
|
149
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
150
|
+
"""
|
|
151
|
+
Calculate the maximum drawdown for selected assets over a given time period
|
|
152
|
+
|
|
153
|
+
Parameters:
|
|
154
|
+
data (DataFrame): DataFrame with asset price data
|
|
155
|
+
assets (List[str]): List of asset columns to calculate drawdown for
|
|
156
|
+
window (int): Rolling window size in days, default is 181 days
|
|
157
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
158
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
DataFrame: Rolling maximum drawdown for specified assets
|
|
162
|
+
"""
|
|
163
|
+
calculator = MaximumDrawdown(
|
|
164
|
+
data=data,
|
|
165
|
+
assets=assets,
|
|
166
|
+
window=window,
|
|
167
|
+
start=start,
|
|
168
|
+
end=end
|
|
169
|
+
)
|
|
170
|
+
return calculator.calculate()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def var(data: pd.DataFrame,
|
|
174
|
+
assets: List[str],
|
|
175
|
+
confidence: float = DEFAULT_VAR_CONFIDENCE,
|
|
176
|
+
window: int = DEFAULT_VAR_WINDOW,
|
|
177
|
+
holding_period: int = DEFAULT_VAR_HOLDING_PERIOD,
|
|
178
|
+
start: Optional[str] = None,
|
|
179
|
+
end: Optional[str] = None,
|
|
180
|
+
method: str = 'historical',
|
|
181
|
+
scaling_method: str = 'sqrt_time') -> pd.DataFrame:
|
|
182
|
+
"""
|
|
183
|
+
Calculate rolling Value at Risk (VaR) for specified assets
|
|
184
|
+
|
|
185
|
+
Parameters:
|
|
186
|
+
data (DataFrame): DataFrame with asset price data
|
|
187
|
+
assets (List[str]): List of asset columns to calculate VaR for
|
|
188
|
+
confidence (float): Confidence level (0-1), default is 0.99 (99%)
|
|
189
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
190
|
+
holding_period (int): Holding period in days, default is 10 days
|
|
191
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
192
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
193
|
+
method (str): Method to calculate VaR - 'historical', 'parametric', default is 'historical'
|
|
194
|
+
scaling_method (str): Method to scale 1-day VaR to holding_period-day VaR, default is 'sqrt_time'
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
DataFrame: Rolling VaR for specified assets
|
|
198
|
+
"""
|
|
199
|
+
calculator = ValueAtRisk(
|
|
200
|
+
data=data,
|
|
201
|
+
assets=assets,
|
|
202
|
+
confidence=confidence,
|
|
203
|
+
window=window,
|
|
204
|
+
holding_period=holding_period, # Pass the new parameter
|
|
205
|
+
start=start,
|
|
206
|
+
end=end,
|
|
207
|
+
method=method,
|
|
208
|
+
scaling_method=scaling_method # Pass the new parameter
|
|
209
|
+
)
|
|
210
|
+
return calculator.calculate()
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def calmar(data: pd.DataFrame,
|
|
214
|
+
assets: List[str],
|
|
215
|
+
window: int = DEFAULT_CALMAR_WINDOW,
|
|
216
|
+
start: Optional[str] = None,
|
|
217
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
218
|
+
"""
|
|
219
|
+
Calculate rolling Calmar ratios for specified assets
|
|
220
|
+
|
|
221
|
+
Parameters:
|
|
222
|
+
data (DataFrame): DataFrame with asset price data
|
|
223
|
+
assets (List[str]): List of asset columns to calculate for
|
|
224
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
225
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
226
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
DataFrame: Rolling Calmar ratios for specified assets
|
|
230
|
+
"""
|
|
231
|
+
calculator = CalmarRatio(
|
|
232
|
+
data=data,
|
|
233
|
+
assets=assets,
|
|
234
|
+
window=window,
|
|
235
|
+
start=start,
|
|
236
|
+
end=end
|
|
237
|
+
)
|
|
238
|
+
return calculator.calculate()
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def cvar(data: pd.DataFrame,
|
|
242
|
+
assets: List[str],
|
|
243
|
+
confidence: float = DEFAULT_CONFIDENCE,
|
|
244
|
+
window: int = DEFAULT_CVAR_WINDOW,
|
|
245
|
+
start: Optional[str] = None,
|
|
246
|
+
end: Optional[str] = None,
|
|
247
|
+
method: str = 'historical') -> pd.DataFrame:
|
|
248
|
+
"""
|
|
249
|
+
Calculate rolling Conditional Value at Risk (CVaR) for specified assets
|
|
250
|
+
|
|
251
|
+
Parameters:
|
|
252
|
+
data (DataFrame): DataFrame with asset price data
|
|
253
|
+
assets (List[str]): List of asset columns to calculate CVaR for
|
|
254
|
+
confidence (float): Confidence level (0-1), default is 0.95 (95%)
|
|
255
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
256
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
257
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
258
|
+
method (str): Method to calculate CVaR - 'historical', 'parametric', default is 'historical'
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
DataFrame: Rolling CVaR for specified assets
|
|
262
|
+
"""
|
|
263
|
+
calculator = ConditionalValueAtRisk(
|
|
264
|
+
data=data,
|
|
265
|
+
assets=assets,
|
|
266
|
+
confidence=confidence,
|
|
267
|
+
window=window,
|
|
268
|
+
start=start,
|
|
269
|
+
end=end,
|
|
270
|
+
method=method
|
|
271
|
+
)
|
|
272
|
+
return calculator.calculate()
|
|
273
|
+
|
|
274
|
+
def semidev(data: pd.DataFrame,
|
|
275
|
+
assets: List[str],
|
|
276
|
+
target_return: Optional[float] = None,
|
|
277
|
+
window: int = DEFAULT_SEMIDEVIATION_WINDOW,
|
|
278
|
+
start: Optional[str] = None,
|
|
279
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
280
|
+
"""
|
|
281
|
+
Calculate the semi-deviation (downside volatility) for specified assets.
|
|
282
|
+
|
|
283
|
+
Parameters:
|
|
284
|
+
data (DataFrame): DataFrame with asset price data
|
|
285
|
+
assets (List[str]): List of asset columns to calculate for
|
|
286
|
+
target_return (float, optional): Target return threshold. If None, the mean return is used
|
|
287
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
288
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
289
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
DataFrame: Semi-deviation for specified assets
|
|
293
|
+
"""
|
|
294
|
+
calculator = SemiDeviation(
|
|
295
|
+
data=data,
|
|
296
|
+
assets=assets,
|
|
297
|
+
target_return=target_return,
|
|
298
|
+
window=window,
|
|
299
|
+
start=start,
|
|
300
|
+
end=end
|
|
301
|
+
)
|
|
302
|
+
return calculator.calculate()
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def avgdd(data: pd.DataFrame,
|
|
306
|
+
assets: List[str],
|
|
307
|
+
window: int = DEFAULT_AVGDRAWDOWN_WINDOW,
|
|
308
|
+
start: Optional[str] = None,
|
|
309
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
310
|
+
"""
|
|
311
|
+
Calculate the average drawdown for specified assets.
|
|
312
|
+
|
|
313
|
+
Parameters:
|
|
314
|
+
data (DataFrame): DataFrame with asset price data
|
|
315
|
+
assets (List[str]): List of asset columns to calculate average drawdown for
|
|
316
|
+
window (int): Rolling window size in days, default is 181 days
|
|
317
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
318
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
DataFrame: Average drawdown for specified assets
|
|
322
|
+
"""
|
|
323
|
+
calculator = AverageDrawdown(
|
|
324
|
+
data=data,
|
|
325
|
+
assets=assets,
|
|
326
|
+
window=window,
|
|
327
|
+
start=start,
|
|
328
|
+
end=end
|
|
329
|
+
)
|
|
330
|
+
return calculator.calculate()
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def ulcer(data: pd.DataFrame,
|
|
334
|
+
assets: List[str],
|
|
335
|
+
window: int = DEFAULT_ULCER_WINDOW,
|
|
336
|
+
start: Optional[str] = None,
|
|
337
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
338
|
+
"""
|
|
339
|
+
Calculate the Ulcer Index for specified assets.
|
|
340
|
+
The Ulcer Index is the square root of the mean of the squared drawdowns.
|
|
341
|
+
|
|
342
|
+
Parameters:
|
|
343
|
+
data (DataFrame): DataFrame with asset price data
|
|
344
|
+
assets (List[str]): List of asset columns to calculate Ulcer Index for
|
|
345
|
+
window (int): Rolling window size in days, default is 181 days
|
|
346
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
347
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
DataFrame: Ulcer Index for specified assets
|
|
351
|
+
"""
|
|
352
|
+
calculator = UlcerIndex(
|
|
353
|
+
data=data,
|
|
354
|
+
assets=assets,
|
|
355
|
+
window=window,
|
|
356
|
+
start=start,
|
|
357
|
+
end=end
|
|
358
|
+
)
|
|
359
|
+
return calculator.calculate()
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def mad(data: pd.DataFrame,
|
|
363
|
+
assets: List[str],
|
|
364
|
+
window: int = DEFAULT_MAD_WINDOW,
|
|
365
|
+
start: Optional[str] = None,
|
|
366
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
367
|
+
"""
|
|
368
|
+
Calculate the Mean Absolute Deviation (MAD) for specified assets.
|
|
369
|
+
|
|
370
|
+
Parameters:
|
|
371
|
+
data (DataFrame): DataFrame with asset price data
|
|
372
|
+
assets (List[str]): List of asset columns to calculate MAD for
|
|
373
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
374
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
375
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
DataFrame: Mean Absolute Deviation for specified assets
|
|
379
|
+
"""
|
|
380
|
+
calculator = MeanAbsoluteDeviation(
|
|
381
|
+
data=data,
|
|
382
|
+
assets=assets,
|
|
383
|
+
window=window,
|
|
384
|
+
start=start,
|
|
385
|
+
end=end
|
|
386
|
+
)
|
|
387
|
+
return calculator.calculate()
|
|
388
|
+
|
|
389
|
+
def erm(data: pd.DataFrame,
|
|
390
|
+
assets: List[str],
|
|
391
|
+
z: float = 1.0,
|
|
392
|
+
alpha: float = DEFAULT_CONFIDENCE,
|
|
393
|
+
window: int = DEFAULT_ERM_WINDOW,
|
|
394
|
+
start: Optional[str] = None,
|
|
395
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
396
|
+
"""
|
|
397
|
+
Calculate the Entropic Risk Measure (ERM) for specified assets.
|
|
398
|
+
|
|
399
|
+
Parameters:
|
|
400
|
+
data (DataFrame): DataFrame with asset price data
|
|
401
|
+
assets (List[str]): List of asset columns to calculate for
|
|
402
|
+
z (float): Risk aversion parameter, must be greater than zero
|
|
403
|
+
alpha (float): Significance level (0-1), default is 0.95 (95%)
|
|
404
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
405
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
406
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
DataFrame: Entropic Risk Measure for specified assets
|
|
410
|
+
"""
|
|
411
|
+
calculator = EntropicRiskMeasure(
|
|
412
|
+
data=data,
|
|
413
|
+
assets=assets,
|
|
414
|
+
z=z,
|
|
415
|
+
alpha=alpha,
|
|
416
|
+
window=window,
|
|
417
|
+
start=start,
|
|
418
|
+
end=end
|
|
419
|
+
)
|
|
420
|
+
return calculator.calculate()
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def evar(data: pd.DataFrame,
|
|
424
|
+
assets: List[str],
|
|
425
|
+
alpha: float = DEFAULT_CONFIDENCE,
|
|
426
|
+
window: int = DEFAULT_EVAR_WINDOW,
|
|
427
|
+
start: Optional[str] = None,
|
|
428
|
+
end: Optional[str] = None,
|
|
429
|
+
solver: Optional[str] = None,
|
|
430
|
+
batch_size: int = 1,
|
|
431
|
+
fallback_z_min: float = 0.01,
|
|
432
|
+
fallback_z_max: float = 100.0,
|
|
433
|
+
fallback_steps: int = 20) -> pd.DataFrame:
|
|
434
|
+
"""
|
|
435
|
+
Calculate the Entropic Value at Risk (EVaR) for specified assets.
|
|
436
|
+
This implementation uses convex optimization via CVXPY when available,
|
|
437
|
+
with fallback to grid search if needed.
|
|
438
|
+
|
|
439
|
+
Parameters:
|
|
440
|
+
data (DataFrame): DataFrame with asset price data
|
|
441
|
+
assets (List[str]): List of asset columns to calculate for
|
|
442
|
+
alpha (float): Significance level (0-1), default is 0.95 (95%)
|
|
443
|
+
window (int): Rolling window size in trading days, default is 252 (1 year)
|
|
444
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
445
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
446
|
+
solver (str, optional): CVXPY solver to use (e.g., 'MOSEK', 'ECOS', 'SCS')
|
|
447
|
+
If None, CVXPY will choose automatically.
|
|
448
|
+
batch_size (int): Number of assets to process in one batch for memory efficiency
|
|
449
|
+
fallback_z_min (float): Minimum value of z for fallback grid search
|
|
450
|
+
fallback_z_max (float): Maximum value of z for fallback grid search
|
|
451
|
+
fallback_steps (int): Number of steps for fallback grid search
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
DataFrame: Entropic Value at Risk for specified assets
|
|
455
|
+
"""
|
|
456
|
+
calculator = EntropicValueAtRisk(
|
|
457
|
+
data=data,
|
|
458
|
+
assets=assets,
|
|
459
|
+
alpha=alpha,
|
|
460
|
+
window=window,
|
|
461
|
+
start=start,
|
|
462
|
+
end=end,
|
|
463
|
+
solver=solver,
|
|
464
|
+
batch_size=batch_size,
|
|
465
|
+
fallback_z_min=fallback_z_min,
|
|
466
|
+
fallback_z_max=fallback_z_max,
|
|
467
|
+
fallback_steps=fallback_steps
|
|
468
|
+
)
|
|
469
|
+
return calculator.calculate()
|
|
470
|
+
|
|
471
|
+
def cdar(data: pd.DataFrame,
|
|
472
|
+
assets: List[str],
|
|
473
|
+
confidence: float = DEFAULT_CONFIDENCE,
|
|
474
|
+
window: int = DEFAULT_CDAR_WINDOW,
|
|
475
|
+
start: Optional[str] = None,
|
|
476
|
+
end: Optional[str] = None) -> pd.DataFrame:
|
|
477
|
+
"""
|
|
478
|
+
Calculate the Conditional Drawdown at Risk (CDaR) for specified assets
|
|
479
|
+
|
|
480
|
+
Parameters:
|
|
481
|
+
data (DataFrame): DataFrame with asset price data
|
|
482
|
+
assets (List[str]): List of asset columns to calculate CDaR for
|
|
483
|
+
confidence (float): Confidence level (0-1), default is 0.95 (95%)
|
|
484
|
+
window (int): Rolling window size in days, default is 181 days
|
|
485
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
486
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
DataFrame: CDaR for specified assets
|
|
490
|
+
"""
|
|
491
|
+
calculator = ConditionalDrawdownAtRisk(
|
|
492
|
+
data=data,
|
|
493
|
+
assets=assets,
|
|
494
|
+
confidence=confidence,
|
|
495
|
+
window=window,
|
|
496
|
+
start=start,
|
|
497
|
+
end=end
|
|
498
|
+
)
|
|
499
|
+
return calculator.calculate()
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def edar(data: pd.DataFrame,
|
|
503
|
+
assets: List[str],
|
|
504
|
+
confidence: float = DEFAULT_CONFIDENCE,
|
|
505
|
+
window: int = DEFAULT_EDAR_WINDOW,
|
|
506
|
+
start: Optional[str] = None,
|
|
507
|
+
end: Optional[str] = None,
|
|
508
|
+
solver: Optional[str] = None,
|
|
509
|
+
batch_size: int = 1,
|
|
510
|
+
fallback_z_min: float = 0.01,
|
|
511
|
+
fallback_z_max: float = 100.0,
|
|
512
|
+
fallback_steps: int = 20) -> pd.DataFrame:
|
|
513
|
+
"""
|
|
514
|
+
Calculate the Entropic Drawdown at Risk (EDaR) for specified assets.
|
|
515
|
+
This implementation uses convex optimization via CVXPY when available,
|
|
516
|
+
with fallback to grid search if needed.
|
|
517
|
+
|
|
518
|
+
Parameters:
|
|
519
|
+
data (DataFrame): DataFrame with asset price data
|
|
520
|
+
assets (List[str]): List of asset columns to calculate for
|
|
521
|
+
confidence (float): Confidence level (0-1), default is 0.95 (95%)
|
|
522
|
+
window (int): Rolling window size in days, default is 181 days
|
|
523
|
+
start (str, optional): Start date in format 'YYYY-MM-DD'
|
|
524
|
+
end (str, optional): End date in format 'YYYY-MM-DD'
|
|
525
|
+
solver (str, optional): CVXPY solver to use (e.g., 'MOSEK', 'ECOS', 'SCS')
|
|
526
|
+
If None, CVXPY will choose automatically.
|
|
527
|
+
batch_size (int): Number of assets to process in one batch for memory efficiency
|
|
528
|
+
fallback_z_min (float): Minimum value of z for fallback grid search
|
|
529
|
+
fallback_z_max (float): Maximum value of z for fallback grid search
|
|
530
|
+
fallback_steps (int): Number of steps for fallback grid search
|
|
531
|
+
|
|
532
|
+
Returns:
|
|
533
|
+
DataFrame: Entropic Drawdown at Risk for specified assets
|
|
534
|
+
"""
|
|
535
|
+
calculator = EntropicDrawdownAtRisk(
|
|
536
|
+
data=data,
|
|
537
|
+
assets=assets,
|
|
538
|
+
confidence=confidence,
|
|
539
|
+
window=window,
|
|
540
|
+
start=start,
|
|
541
|
+
end=end,
|
|
542
|
+
solver=solver,
|
|
543
|
+
batch_size=batch_size,
|
|
544
|
+
fallback_z_min=fallback_z_min,
|
|
545
|
+
fallback_z_max=fallback_z_max,
|
|
546
|
+
fallback_steps=fallback_steps
|
|
547
|
+
)
|
|
548
|
+
return calculator.calculate()
|
squarequant/constants.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Package-wide constants
|
|
2
|
+
|
|
3
|
+
# Trading constants
|
|
4
|
+
TRADING_DAYS_PER_YEAR = 252
|
|
5
|
+
|
|
6
|
+
# Default window sizes
|
|
7
|
+
DEFAULT_SHARPE_WINDOW = TRADING_DAYS_PER_YEAR
|
|
8
|
+
DEFAULT_SORTINO_WINDOW = TRADING_DAYS_PER_YEAR
|
|
9
|
+
DEFAULT_VOLATILITY_WINDOW = 10
|
|
10
|
+
DEFAULT_DRAWDOWN_WINDOW = 181
|
|
11
|
+
DEFAULT_CALMAR_WINDOW = TRADING_DAYS_PER_YEAR
|
|
12
|
+
DEFAULT_CVAR_WINDOW = TRADING_DAYS_PER_YEAR
|
|
13
|
+
DEFAULT_VAR_WINDOW = TRADING_DAYS_PER_YEAR
|
|
14
|
+
DEFAULT_SEMIDEVIATION_WINDOW = TRADING_DAYS_PER_YEAR
|
|
15
|
+
DEFAULT_AVGDRAWDOWN_WINDOW = 181
|
|
16
|
+
DEFAULT_ULCER_WINDOW = 181
|
|
17
|
+
DEFAULT_MAD_WINDOW = TRADING_DAYS_PER_YEAR
|
|
18
|
+
DEFAULT_ERM_WINDOW = TRADING_DAYS_PER_YEAR
|
|
19
|
+
DEFAULT_EVAR_WINDOW = TRADING_DAYS_PER_YEAR
|
|
20
|
+
DEFAULT_CDAR_WINDOW = 181
|
|
21
|
+
DEFAULT_EDAR_WINDOW = 181
|
|
22
|
+
|
|
23
|
+
# VaR specific default-values
|
|
24
|
+
DEFAULT_VAR_HOLDING_PERIOD = 10
|
|
25
|
+
DEFAULT_VAR_CONFIDENCE = 0.99
|
|
26
|
+
VALID_VAR_SCALING_METHODS = {'sqrt_time', 'overlapping'}
|
|
27
|
+
|
|
28
|
+
# Default values
|
|
29
|
+
DEFAULT_CONFIDENCE = 0.95
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Valid options
|
|
33
|
+
VALID_INTERVALS = {'1m', '15m', '60m', '1h', '1d', '1wk', '1mo'}
|
|
34
|
+
VALID_COLUMNS = {'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'}
|
|
35
|
+
VALID_VAR_METHODS = {'historical', 'parametric'}
|