openseries 1.8.1__py3-none-any.whl → 1.8.3__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.
- openseries/_common_model.py +250 -77
- openseries/_risk.py +2 -2
- openseries/datefixer.py +10 -10
- openseries/frame.py +38 -41
- openseries/load_plotly.py +2 -2
- openseries/owntypes.py +11 -2
- openseries/plotly_layouts.json +4 -4
- openseries/portfoliotools.py +14 -13
- openseries/series.py +29 -27
- openseries/simulation.py +10 -10
- {openseries-1.8.1.dist-info → openseries-1.8.3.dist-info}/METADATA +7 -6
- openseries-1.8.3.dist-info/RECORD +16 -0
- {openseries-1.8.1.dist-info → openseries-1.8.3.dist-info}/WHEEL +1 -1
- openseries-1.8.1.dist-info/RECORD +0 -16
- {openseries-1.8.1.dist-info → openseries-1.8.3.dist-info}/LICENSE.md +0 -0
openseries/_risk.py
CHANGED
@@ -32,7 +32,7 @@ def _cvar_down_calc(
|
|
32
32
|
level: float, default: 0.95
|
33
33
|
The sought CVaR level
|
34
34
|
|
35
|
-
Returns
|
35
|
+
Returns:
|
36
36
|
-------
|
37
37
|
float
|
38
38
|
Downside Conditional Value At Risk "CVaR"
|
@@ -66,7 +66,7 @@ def _var_down_calc(
|
|
66
66
|
interpolation: LiteralQuantileInterp, default: "lower"
|
67
67
|
type of interpolation in Pandas.DataFrame.quantile() function.
|
68
68
|
|
69
|
-
Returns
|
69
|
+
Returns:
|
70
70
|
-------
|
71
71
|
float
|
72
72
|
Downside Value At Risk
|
openseries/datefixer.py
CHANGED
@@ -65,7 +65,7 @@ def holiday_calendar(
|
|
65
65
|
Argument where missing holidays can be added as
|
66
66
|
{"2021-02-12": "Jack's birthday"} or ["2021-02-12"]
|
67
67
|
|
68
|
-
Returns
|
68
|
+
Returns:
|
69
69
|
-------
|
70
70
|
numpy.busdaycalendar
|
71
71
|
Generate a business calendar
|
@@ -113,7 +113,7 @@ def date_fix(
|
|
113
113
|
fixerdate: DateType
|
114
114
|
The data item to parse
|
115
115
|
|
116
|
-
Returns
|
116
|
+
Returns:
|
117
117
|
-------
|
118
118
|
datetime.date
|
119
119
|
Parsed date
|
@@ -160,7 +160,7 @@ def date_offset_foll(
|
|
160
160
|
following: bool, default: True
|
161
161
|
Determines if days should be offset forward (following) or backward
|
162
162
|
|
163
|
-
Returns
|
163
|
+
Returns:
|
164
164
|
-------
|
165
165
|
datetime.date
|
166
166
|
Off-set date
|
@@ -185,7 +185,7 @@ def date_offset_foll(
|
|
185
185
|
while not is_busday(dates=new_date, busdaycal=calendar):
|
186
186
|
new_date += day_delta
|
187
187
|
|
188
|
-
return new_date
|
188
|
+
return new_date # type: ignore[no-any-return]
|
189
189
|
|
190
190
|
|
191
191
|
def get_previous_business_day_before_today(
|
@@ -205,7 +205,7 @@ def get_previous_business_day_before_today(
|
|
205
205
|
Argument where missing holidays can be added as
|
206
206
|
{"2021-02-12": "Jack's birthday"} or ["2021-02-12"]
|
207
207
|
|
208
|
-
Returns
|
208
|
+
Returns:
|
209
209
|
-------
|
210
210
|
datetime.date
|
211
211
|
The previous business day
|
@@ -248,7 +248,7 @@ def offset_business_days(
|
|
248
248
|
Argument where missing holidays can be added as
|
249
249
|
{"2021-02-12": "Jack's birthday"} or ["2021-02-12"]
|
250
250
|
|
251
|
-
Returns
|
251
|
+
Returns:
|
252
252
|
-------
|
253
253
|
datetime.date
|
254
254
|
The new offset business day
|
@@ -324,7 +324,7 @@ def generate_calendar_date_range(
|
|
324
324
|
countries: CountriesType, default: "SE"
|
325
325
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
326
326
|
|
327
|
-
Returns
|
327
|
+
Returns:
|
328
328
|
-------
|
329
329
|
list[dt.date]
|
330
330
|
List of business day calendar dates
|
@@ -342,7 +342,7 @@ def generate_calendar_date_range(
|
|
342
342
|
)
|
343
343
|
calendar = holiday_calendar(
|
344
344
|
startyear=start.year,
|
345
|
-
endyear=date_fix(tmp_range[-1]).year,
|
345
|
+
endyear=date_fix(tmp_range.tolist()[-1]).year,
|
346
346
|
countries=countries,
|
347
347
|
)
|
348
348
|
return [
|
@@ -357,7 +357,7 @@ def generate_calendar_date_range(
|
|
357
357
|
if end and not start:
|
358
358
|
tmp_range = date_range(end=end, periods=trading_days * 365 // 252, freq="D")
|
359
359
|
calendar = holiday_calendar(
|
360
|
-
startyear=date_fix(tmp_range[0]).year,
|
360
|
+
startyear=date_fix(tmp_range.tolist()[0]).year,
|
361
361
|
endyear=end.year,
|
362
362
|
countries=countries,
|
363
363
|
)
|
@@ -396,7 +396,7 @@ def _do_resample_to_business_period_ends(
|
|
396
396
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
397
397
|
to create a business day calendar used for date adjustments
|
398
398
|
|
399
|
-
Returns
|
399
|
+
Returns:
|
400
400
|
-------
|
401
401
|
Pandas.DatetimeIndex
|
402
402
|
A date range aligned to business period ends
|
openseries/frame.py
CHANGED
@@ -11,11 +11,11 @@ from typing import TYPE_CHECKING, cast
|
|
11
11
|
if TYPE_CHECKING: # pragma: no cover
|
12
12
|
import datetime as dt
|
13
13
|
|
14
|
-
from statsmodels.regression.linear_model import ( # type: ignore[import-untyped
|
14
|
+
from statsmodels.regression.linear_model import ( # type: ignore[import-untyped]
|
15
15
|
OLSResults,
|
16
16
|
)
|
17
17
|
|
18
|
-
import statsmodels.api as sm # type: ignore[import-untyped
|
18
|
+
import statsmodels.api as sm # type: ignore[import-untyped]
|
19
19
|
from numpy import (
|
20
20
|
array,
|
21
21
|
cov,
|
@@ -31,7 +31,6 @@ from pandas import (
|
|
31
31
|
DataFrame,
|
32
32
|
DatetimeIndex,
|
33
33
|
Index,
|
34
|
-
Int64Dtype,
|
35
34
|
MultiIndex,
|
36
35
|
Series,
|
37
36
|
concat,
|
@@ -82,7 +81,7 @@ class OpenFrame(_CommonModel):
|
|
82
81
|
weights: list[float], optional
|
83
82
|
List of weights in float format.
|
84
83
|
|
85
|
-
Returns
|
84
|
+
Returns:
|
86
85
|
-------
|
87
86
|
OpenFrame
|
88
87
|
Object of the class OpenFrame
|
@@ -94,7 +93,7 @@ class OpenFrame(_CommonModel):
|
|
94
93
|
weights: list[float] | None = None
|
95
94
|
|
96
95
|
# noinspection PyMethodParameters
|
97
|
-
@field_validator("constituents")
|
96
|
+
@field_validator("constituents") # type: ignore[misc]
|
98
97
|
def _check_labels_unique( # type: ignore[misc]
|
99
98
|
cls: OpenFrame, # noqa: N805
|
100
99
|
tseries: list[OpenTimeSeries],
|
@@ -122,7 +121,7 @@ class OpenFrame(_CommonModel):
|
|
122
121
|
weights: list[float], optional
|
123
122
|
List of weights in float format.
|
124
123
|
|
125
|
-
Returns
|
124
|
+
Returns:
|
126
125
|
-------
|
127
126
|
OpenFrame
|
128
127
|
Object of the class OpenFrame
|
@@ -150,7 +149,7 @@ class OpenFrame(_CommonModel):
|
|
150
149
|
def from_deepcopy(self: Self) -> Self:
|
151
150
|
"""Create copy of the OpenFrame object.
|
152
151
|
|
153
|
-
Returns
|
152
|
+
Returns:
|
154
153
|
-------
|
155
154
|
OpenFrame
|
156
155
|
An OpenFrame object
|
@@ -169,7 +168,7 @@ class OpenFrame(_CommonModel):
|
|
169
168
|
how: LiteralHowMerge, default: "outer"
|
170
169
|
The Pandas merge method.
|
171
170
|
|
172
|
-
Returns
|
171
|
+
Returns:
|
173
172
|
-------
|
174
173
|
OpenFrame
|
175
174
|
An OpenFrame object
|
@@ -213,7 +212,7 @@ class OpenFrame(_CommonModel):
|
|
213
212
|
properties: list[LiteralFrameProps], optional
|
214
213
|
The properties to calculate. Defaults to calculating all available.
|
215
214
|
|
216
|
-
Returns
|
215
|
+
Returns:
|
217
216
|
-------
|
218
217
|
pandas.DataFrame
|
219
218
|
Properties of the contituent OpenTimeSeries
|
@@ -232,24 +231,23 @@ class OpenFrame(_CommonModel):
|
|
232
231
|
def lengths_of_items(self: Self) -> Series[int]:
|
233
232
|
"""Number of observations of all constituents.
|
234
233
|
|
235
|
-
Returns
|
234
|
+
Returns:
|
236
235
|
-------
|
237
236
|
Pandas.Series[int]
|
238
237
|
Number of observations of all constituents
|
239
238
|
|
240
239
|
"""
|
241
240
|
return Series(
|
242
|
-
data=[
|
241
|
+
data=[self.tsdf.loc[:, d].count() for d in self.tsdf],
|
243
242
|
index=self.tsdf.columns,
|
244
243
|
name="observations",
|
245
|
-
|
246
|
-
)
|
244
|
+
).astype(int)
|
247
245
|
|
248
246
|
@property
|
249
247
|
def item_count(self: Self) -> int:
|
250
248
|
"""Number of constituents.
|
251
249
|
|
252
|
-
Returns
|
250
|
+
Returns:
|
253
251
|
-------
|
254
252
|
int
|
255
253
|
Number of constituents
|
@@ -261,7 +259,7 @@ class OpenFrame(_CommonModel):
|
|
261
259
|
def columns_lvl_zero(self: Self) -> list[str]:
|
262
260
|
"""Level 0 values of the MultiIndex columns in the .tsdf DataFrame.
|
263
261
|
|
264
|
-
Returns
|
262
|
+
Returns:
|
265
263
|
-------
|
266
264
|
list[str]
|
267
265
|
Level 0 values of the MultiIndex columns in the .tsdf DataFrame
|
@@ -273,7 +271,7 @@ class OpenFrame(_CommonModel):
|
|
273
271
|
def columns_lvl_one(self: Self) -> list[ValueType]:
|
274
272
|
"""Level 1 values of the MultiIndex columns in the .tsdf DataFrame.
|
275
273
|
|
276
|
-
Returns
|
274
|
+
Returns:
|
277
275
|
-------
|
278
276
|
list[ValueType]
|
279
277
|
Level 1 values of the MultiIndex columns in the .tsdf DataFrame
|
@@ -285,7 +283,7 @@ class OpenFrame(_CommonModel):
|
|
285
283
|
def first_indices(self: Self) -> Series[dt.date]:
|
286
284
|
"""The first dates in the timeseries of all constituents.
|
287
285
|
|
288
|
-
Returns
|
286
|
+
Returns:
|
289
287
|
-------
|
290
288
|
Pandas.Series[dt.date]
|
291
289
|
The first dates in the timeseries of all constituents
|
@@ -302,7 +300,7 @@ class OpenFrame(_CommonModel):
|
|
302
300
|
def last_indices(self: Self) -> Series[dt.date]:
|
303
301
|
"""The last dates in the timeseries of all constituents.
|
304
302
|
|
305
|
-
Returns
|
303
|
+
Returns:
|
306
304
|
-------
|
307
305
|
Pandas.Series[dt.date]
|
308
306
|
The last dates in the timeseries of all constituents
|
@@ -319,7 +317,7 @@ class OpenFrame(_CommonModel):
|
|
319
317
|
def span_of_days_all(self: Self) -> Series[int]:
|
320
318
|
"""Number of days from the first date to the last for all items in the frame.
|
321
319
|
|
322
|
-
Returns
|
320
|
+
Returns:
|
323
321
|
-------
|
324
322
|
Pandas.Series[int]
|
325
323
|
Number of days from the first date to the last for all
|
@@ -330,13 +328,12 @@ class OpenFrame(_CommonModel):
|
|
330
328
|
data=[c.span_of_days for c in self.constituents],
|
331
329
|
index=self.tsdf.columns,
|
332
330
|
name="span of days",
|
333
|
-
|
334
|
-
)
|
331
|
+
).astype(int)
|
335
332
|
|
336
333
|
def value_to_ret(self: Self) -> Self:
|
337
334
|
"""Convert series of values into series of returns.
|
338
335
|
|
339
|
-
Returns
|
336
|
+
Returns:
|
340
337
|
-------
|
341
338
|
OpenFrame
|
342
339
|
The returns of the values in the series
|
@@ -359,7 +356,7 @@ class OpenFrame(_CommonModel):
|
|
359
356
|
The number of periods between observations over which difference
|
360
357
|
is calculated
|
361
358
|
|
362
|
-
Returns
|
359
|
+
Returns:
|
363
360
|
-------
|
364
361
|
OpenFrame
|
365
362
|
An OpenFrame object
|
@@ -375,7 +372,7 @@ class OpenFrame(_CommonModel):
|
|
375
372
|
def to_cumret(self: Self) -> Self:
|
376
373
|
"""Convert series of returns into cumulative series of values.
|
377
374
|
|
378
|
-
Returns
|
375
|
+
Returns:
|
379
376
|
-------
|
380
377
|
OpenFrame
|
381
378
|
An OpenFrame object
|
@@ -411,7 +408,7 @@ class OpenFrame(_CommonModel):
|
|
411
408
|
freq: LiteralBizDayFreq | str, default "BME"
|
412
409
|
The date offset string that sets the resampled frequency
|
413
410
|
|
414
|
-
Returns
|
411
|
+
Returns:
|
415
412
|
-------
|
416
413
|
OpenFrame
|
417
414
|
An OpenFrame object
|
@@ -449,7 +446,7 @@ class OpenFrame(_CommonModel):
|
|
449
446
|
method: LiteralPandasReindexMethod, default: nearest
|
450
447
|
Controls the method used to align values across columns
|
451
448
|
|
452
|
-
Returns
|
449
|
+
Returns:
|
453
450
|
-------
|
454
451
|
OpenFrame
|
455
452
|
An OpenFrame object
|
@@ -517,7 +514,7 @@ class OpenFrame(_CommonModel):
|
|
517
514
|
Allows locking the periods-in-a-year to simplify test cases and
|
518
515
|
comparisons
|
519
516
|
|
520
|
-
Returns
|
517
|
+
Returns:
|
521
518
|
-------
|
522
519
|
Pandas.DataFrame
|
523
520
|
Series volatilities and correlation
|
@@ -605,7 +602,7 @@ class OpenFrame(_CommonModel):
|
|
605
602
|
def correl_matrix(self: Self) -> DataFrame:
|
606
603
|
"""Correlation matrix.
|
607
604
|
|
608
|
-
Returns
|
605
|
+
Returns:
|
609
606
|
-------
|
610
607
|
Pandas.DataFrame
|
611
608
|
Correlation matrix
|
@@ -635,7 +632,7 @@ class OpenFrame(_CommonModel):
|
|
635
632
|
new_series: OpenTimeSeries
|
636
633
|
The timeseries to add
|
637
634
|
|
638
|
-
Returns
|
635
|
+
Returns:
|
639
636
|
-------
|
640
637
|
OpenFrame
|
641
638
|
An OpenFrame object
|
@@ -653,7 +650,7 @@ class OpenFrame(_CommonModel):
|
|
653
650
|
lvl_zero_item: str
|
654
651
|
The .tsdf column level 0 value of the timeseries to delete
|
655
652
|
|
656
|
-
Returns
|
653
|
+
Returns:
|
657
654
|
-------
|
658
655
|
OpenFrame
|
659
656
|
An OpenFrame object
|
@@ -692,7 +689,7 @@ class OpenFrame(_CommonModel):
|
|
692
689
|
Determines where dataframe is truncated also when start_cut
|
693
690
|
or end_cut is None.
|
694
691
|
|
695
|
-
Returns
|
692
|
+
Returns:
|
696
693
|
-------
|
697
694
|
OpenFrame
|
698
695
|
An OpenFrame object
|
@@ -793,7 +790,7 @@ class OpenFrame(_CommonModel):
|
|
793
790
|
Allows locking the periods-in-a-year to simplify test cases and
|
794
791
|
comparisons
|
795
792
|
|
796
|
-
Returns
|
793
|
+
Returns:
|
797
794
|
-------
|
798
795
|
Pandas.Series[float]
|
799
796
|
Tracking Errors
|
@@ -885,7 +882,7 @@ class OpenFrame(_CommonModel):
|
|
885
882
|
Allows locking the periods-in-a-year to simplify test cases and
|
886
883
|
comparisons
|
887
884
|
|
888
|
-
Returns
|
885
|
+
Returns:
|
889
886
|
-------
|
890
887
|
Pandas.Series[float]
|
891
888
|
Information Ratios
|
@@ -987,7 +984,7 @@ class OpenFrame(_CommonModel):
|
|
987
984
|
Allows locking the periods-in-a-year to simplify test cases and
|
988
985
|
comparisons
|
989
986
|
|
990
|
-
Returns
|
987
|
+
Returns:
|
991
988
|
-------
|
992
989
|
Pandas.Series[float]
|
993
990
|
Capture Ratios
|
@@ -1169,7 +1166,7 @@ class OpenFrame(_CommonModel):
|
|
1169
1166
|
dlta_degr_freedms: int, default: 1
|
1170
1167
|
Variance bias factor taking the value 0 or 1.
|
1171
1168
|
|
1172
|
-
Returns
|
1169
|
+
Returns:
|
1173
1170
|
-------
|
1174
1171
|
float
|
1175
1172
|
Beta as Co-variance of x & y divided by Variance of x
|
@@ -1253,7 +1250,7 @@ class OpenFrame(_CommonModel):
|
|
1253
1250
|
fitted_series: bool, default: True
|
1254
1251
|
If True the fit is added as a new column in the .tsdf Pandas.DataFrame
|
1255
1252
|
|
1256
|
-
Returns
|
1253
|
+
Returns:
|
1257
1254
|
-------
|
1258
1255
|
OLSResults
|
1259
1256
|
The Statsmodels regression output
|
@@ -1318,7 +1315,7 @@ class OpenFrame(_CommonModel):
|
|
1318
1315
|
dlta_degr_freedms: int, default: 1
|
1319
1316
|
Variance bias factor taking the value 0 or 1.
|
1320
1317
|
|
1321
|
-
Returns
|
1318
|
+
Returns:
|
1322
1319
|
-------
|
1323
1320
|
float
|
1324
1321
|
Jensen's alpha
|
@@ -1438,7 +1435,7 @@ class OpenFrame(_CommonModel):
|
|
1438
1435
|
weight_strat: LiteralPortfolioWeightings, optional
|
1439
1436
|
weight calculation strategies
|
1440
1437
|
|
1441
|
-
Returns
|
1438
|
+
Returns:
|
1442
1439
|
-------
|
1443
1440
|
Pandas.DataFrame
|
1444
1441
|
A basket timeseries
|
@@ -1503,7 +1500,7 @@ class OpenFrame(_CommonModel):
|
|
1503
1500
|
periods_in_a_year_fixed : DaysInYearType, optional
|
1504
1501
|
Allows locking the periods-in-a-year to simplify test cases and comparisons
|
1505
1502
|
|
1506
|
-
Returns
|
1503
|
+
Returns:
|
1507
1504
|
-------
|
1508
1505
|
Pandas.DataFrame
|
1509
1506
|
Rolling Information Ratios
|
@@ -1569,7 +1566,7 @@ class OpenFrame(_CommonModel):
|
|
1569
1566
|
dlta_degr_freedms: int, default: 1
|
1570
1567
|
Variance bias factor taking the value 0 or 1.
|
1571
1568
|
|
1572
|
-
Returns
|
1569
|
+
Returns:
|
1573
1570
|
-------
|
1574
1571
|
Pandas.DataFrame
|
1575
1572
|
Rolling Betas
|
@@ -1629,7 +1626,7 @@ class OpenFrame(_CommonModel):
|
|
1629
1626
|
observations: int, default: 21
|
1630
1627
|
The length of the rolling window to use is set as number of observations
|
1631
1628
|
|
1632
|
-
Returns
|
1629
|
+
Returns:
|
1633
1630
|
-------
|
1634
1631
|
Pandas.DataFrame
|
1635
1632
|
Rolling Correlations
|
openseries/load_plotly.py
CHANGED
@@ -26,7 +26,7 @@ def _check_remote_file_existence(url: str) -> bool:
|
|
26
26
|
url: str
|
27
27
|
Path to remote file
|
28
28
|
|
29
|
-
Returns
|
29
|
+
Returns:
|
30
30
|
-------
|
31
31
|
bool
|
32
32
|
True if url is valid and False otherwise
|
@@ -54,7 +54,7 @@ def load_plotly_dict(
|
|
54
54
|
responsive : bool
|
55
55
|
Flag whether to load as responsive
|
56
56
|
|
57
|
-
Returns
|
57
|
+
Returns:
|
58
58
|
-------
|
59
59
|
tuple[PlotlyLayoutType, CaptorLogoType]
|
60
60
|
A dictionary with the Plotly config and layout template
|
openseries/owntypes.py
CHANGED
@@ -38,7 +38,7 @@ CountryListType = conset(
|
|
38
38
|
CountriesType = Union[CountryListType, CountryStringType] # type: ignore[valid-type] # noqa: UP007
|
39
39
|
|
40
40
|
|
41
|
-
class Countries(BaseModel):
|
41
|
+
class Countries(BaseModel): # type: ignore[misc]
|
42
42
|
"""Declare Countries."""
|
43
43
|
|
44
44
|
countryinput: CountriesType
|
@@ -57,7 +57,7 @@ CurrencyStringType = Annotated[
|
|
57
57
|
]
|
58
58
|
|
59
59
|
|
60
|
-
class Currency(BaseModel):
|
60
|
+
class Currency(BaseModel): # type: ignore[misc]
|
61
61
|
"""Declare Currency."""
|
62
62
|
|
63
63
|
ccy: CurrencyStringType
|
@@ -135,6 +135,15 @@ LiteralCaptureRatio = Literal["up", "down", "both"]
|
|
135
135
|
LiteralBarPlotMode = Literal["stack", "group", "overlay", "relative"]
|
136
136
|
LiteralPlotlyOutput = Literal["file", "div"]
|
137
137
|
LiteralPlotlyJSlib = Literal[True, False, "cdn"]
|
138
|
+
LiteralPlotlyHistogramPlotType = Literal["bars", "lines"]
|
139
|
+
LiteralPlotlyHistogramBarMode = Literal["stack", "group", "overlay", "relative"]
|
140
|
+
LiteralPlotlyHistogramCurveType = Literal["normal", "kde"]
|
141
|
+
LiteralPlotlyHistogramHistNorm = Literal[
|
142
|
+
"percent",
|
143
|
+
"probability",
|
144
|
+
"density",
|
145
|
+
"probability density",
|
146
|
+
]
|
138
147
|
LiteralOlsFitMethod = Literal["pinv", "qr"]
|
139
148
|
LiteralPortfolioWeightings = Literal["eq_weights", "inv_vol"]
|
140
149
|
LiteralOlsFitCovType = Literal[
|
openseries/plotly_layouts.json
CHANGED
@@ -43,19 +43,19 @@
|
|
43
43
|
"size": 14
|
44
44
|
},
|
45
45
|
"legend": {
|
46
|
-
"bgcolor": "rgba(0,
|
46
|
+
"bgcolor": "rgba(0,0,0,0)",
|
47
47
|
"orientation": "h",
|
48
48
|
"x": 0.98,
|
49
49
|
"xanchor": "right",
|
50
50
|
"y": -0.15,
|
51
51
|
"yanchor": "bottom"
|
52
52
|
},
|
53
|
-
"paper_bgcolor": "rgba(
|
54
|
-
"plot_bgcolor": "rgba(
|
53
|
+
"paper_bgcolor": "rgba(255,255,255,1)",
|
54
|
+
"plot_bgcolor": "rgba(255,255,255,1)",
|
55
55
|
"showlegend": true,
|
56
56
|
"title": {
|
57
57
|
"font": {
|
58
|
-
"size":
|
58
|
+
"size": 32
|
59
59
|
},
|
60
60
|
"x": 0.5,
|
61
61
|
"xanchor": "center",
|
openseries/portfoliotools.py
CHANGED
@@ -26,10 +26,10 @@ from pandas import (
|
|
26
26
|
Series,
|
27
27
|
concat,
|
28
28
|
)
|
29
|
-
from plotly.graph_objs import Figure # type: ignore[import-untyped
|
30
|
-
from plotly.io import to_html # type: ignore[import-untyped
|
31
|
-
from plotly.offline import plot # type: ignore[import-untyped
|
32
|
-
from scipy.optimize import minimize # type: ignore[import-untyped
|
29
|
+
from plotly.graph_objs import Figure # type: ignore[import-untyped]
|
30
|
+
from plotly.io import to_html # type: ignore[import-untyped]
|
31
|
+
from plotly.offline import plot # type: ignore[import-untyped]
|
32
|
+
from scipy.optimize import minimize # type: ignore[import-untyped]
|
33
33
|
|
34
34
|
from .load_plotly import load_plotly_dict
|
35
35
|
from .owntypes import (
|
@@ -47,6 +47,7 @@ from .series import OpenTimeSeries
|
|
47
47
|
from .simulation import _random_generator
|
48
48
|
|
49
49
|
if TYPE_CHECKING: # pragma: no cover
|
50
|
+
# noinspection PyUnresolvedReferences
|
50
51
|
from collections.abc import Callable
|
51
52
|
|
52
53
|
from numpy.typing import NDArray
|
@@ -79,7 +80,7 @@ def simulate_portfolios(
|
|
79
80
|
seed: int
|
80
81
|
The seed for the random process
|
81
82
|
|
82
|
-
Returns
|
83
|
+
Returns:
|
83
84
|
-------
|
84
85
|
pandas.DataFrame
|
85
86
|
The resulting data
|
@@ -160,7 +161,7 @@ def efficient_frontier(
|
|
160
161
|
tweak: bool, default: True
|
161
162
|
cutting the frontier to exclude multiple points with almost the same risk
|
162
163
|
|
163
|
-
Returns
|
164
|
+
Returns:
|
164
165
|
-------
|
165
166
|
tuple[DataFrame, DataFrame, NDArray[float]]
|
166
167
|
The efficient frontier data, simulation data and optimal portfolio
|
@@ -192,8 +193,8 @@ def efficient_frontier(
|
|
192
193
|
|
193
194
|
frontier_max = cleaned_arithmetic_means.max()
|
194
195
|
|
195
|
-
def _check_sum(weights: NDArray[float64]) ->
|
196
|
-
return npsum(weights) - 1
|
196
|
+
def _check_sum(weights: NDArray[float64]) -> float:
|
197
|
+
return cast("float", npsum(weights) - 1)
|
197
198
|
|
198
199
|
def _get_ret_vol_sr(
|
199
200
|
lg_ret: DataFrame,
|
@@ -347,7 +348,7 @@ def constrain_optimized_portfolios(
|
|
347
348
|
minimize_method: LiteralMinimizeMethods, default: SLSQP
|
348
349
|
The method passed into the scipy.minimize function
|
349
350
|
|
350
|
-
Returns
|
351
|
+
Returns:
|
351
352
|
-------
|
352
353
|
tuple[OpenFrame, OpenTimeSeries, OpenFrame, OpenTimeSeries]
|
353
354
|
The constrained optimal portfolio data
|
@@ -407,7 +408,7 @@ def prepare_plot_data(
|
|
407
408
|
optimized: DataFrame
|
408
409
|
Data optimized with the efficient_frontier method
|
409
410
|
|
410
|
-
Returns
|
411
|
+
Returns:
|
411
412
|
-------
|
412
413
|
DataFrame
|
413
414
|
The data prepared with mean returns, volatility and weights
|
@@ -492,7 +493,7 @@ def sharpeplot(
|
|
492
493
|
auto_open: bool, default: True
|
493
494
|
Determines whether to open a browser window with the plot
|
494
495
|
|
495
|
-
Returns
|
496
|
+
Returns:
|
496
497
|
-------
|
497
498
|
Figure
|
498
499
|
The scatter plot with simulated and optimized results
|
@@ -559,8 +560,8 @@ def sharpeplot(
|
|
559
560
|
fig["layout"],
|
560
561
|
).get("colorway")[: len(point_frame.columns)]
|
561
562
|
for col, clr in zip(point_frame.columns, colorway, strict=True):
|
562
|
-
returns.extend([point_frame.loc["ret", col]])
|
563
|
-
risk.extend([point_frame.loc["stdev", col]])
|
563
|
+
returns.extend([cast("float", point_frame.loc["ret", col])])
|
564
|
+
risk.extend([cast("float", point_frame.loc["stdev", col])])
|
564
565
|
figure.add_scatter(
|
565
566
|
x=[point_frame.loc["stdev", col]],
|
566
567
|
y=[point_frame.loc["ret", col]],
|