openseries 1.4.8__py3-none-any.whl → 1.4.10__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 +90 -7
- openseries/_risk.py +4 -0
- openseries/datefixer.py +8 -5
- openseries/frame.py +37 -30
- openseries/load_plotly.py +2 -0
- openseries/series.py +25 -31
- openseries/simulation.py +10 -0
- openseries/types.py +1 -2
- {openseries-1.4.8.dist-info → openseries-1.4.10.dist-info}/METADATA +17 -10
- openseries-1.4.10.dist-info/RECORD +15 -0
- openseries-1.4.8.dist-info/RECORD +0 -15
- {openseries-1.4.8.dist-info → openseries-1.4.10.dist-info}/LICENSE.md +0 -0
- {openseries-1.4.8.dist-info → openseries-1.4.10.dist-info}/WHEEL +0 -0
openseries/frame.py
CHANGED
@@ -50,7 +50,6 @@ from openseries.types import (
|
|
50
50
|
LiteralOlsFitCovType,
|
51
51
|
LiteralOlsFitMethod,
|
52
52
|
LiteralPandasReindexMethod,
|
53
|
-
LiteralPandasResampleConvention,
|
54
53
|
LiteralPortfolioWeightings,
|
55
54
|
LiteralRiskParityMethod,
|
56
55
|
LiteralTrunc,
|
@@ -77,6 +76,7 @@ class OpenFrame(_CommonModel):
|
|
77
76
|
-------
|
78
77
|
OpenFrame
|
79
78
|
Object of the class OpenFrame
|
79
|
+
|
80
80
|
"""
|
81
81
|
|
82
82
|
constituents: list[OpenTimeSeries]
|
@@ -117,6 +117,7 @@ class OpenFrame(_CommonModel):
|
|
117
117
|
-------
|
118
118
|
OpenFrame
|
119
119
|
Object of the class OpenFrame
|
120
|
+
|
120
121
|
"""
|
121
122
|
super().__init__( # type: ignore[call-arg]
|
122
123
|
constituents=constituents,
|
@@ -145,6 +146,7 @@ class OpenFrame(_CommonModel):
|
|
145
146
|
-------
|
146
147
|
OpenFrame
|
147
148
|
An OpenFrame object
|
149
|
+
|
148
150
|
"""
|
149
151
|
return deepcopy(self)
|
150
152
|
|
@@ -164,6 +166,7 @@ class OpenFrame(_CommonModel):
|
|
164
166
|
-------
|
165
167
|
OpenFrame
|
166
168
|
An OpenFrame object
|
169
|
+
|
167
170
|
"""
|
168
171
|
self.tsdf = reduce(
|
169
172
|
lambda left, right: merge(
|
@@ -204,6 +207,7 @@ class OpenFrame(_CommonModel):
|
|
204
207
|
-------
|
205
208
|
pandas.DataFrame
|
206
209
|
Properties of the contituent OpenTimeSeries
|
210
|
+
|
207
211
|
"""
|
208
212
|
if properties:
|
209
213
|
props = OpenFramePropertiesList(*properties)
|
@@ -223,6 +227,7 @@ class OpenFrame(_CommonModel):
|
|
223
227
|
-------
|
224
228
|
Pandas.Series[int]
|
225
229
|
Number of observations of all constituents
|
230
|
+
|
226
231
|
"""
|
227
232
|
return Series(
|
228
233
|
data=[int(self.tsdf.loc[:, d].count()) for d in self.tsdf],
|
@@ -240,6 +245,7 @@ class OpenFrame(_CommonModel):
|
|
240
245
|
-------
|
241
246
|
int
|
242
247
|
Number of constituents
|
248
|
+
|
243
249
|
"""
|
244
250
|
return len(self.constituents)
|
245
251
|
|
@@ -252,6 +258,7 @@ class OpenFrame(_CommonModel):
|
|
252
258
|
-------
|
253
259
|
list[str]
|
254
260
|
Level 0 values of the MultiIndex columns in the .tsdf DataFrame
|
261
|
+
|
255
262
|
"""
|
256
263
|
return list(self.tsdf.columns.get_level_values(0))
|
257
264
|
|
@@ -264,6 +271,7 @@ class OpenFrame(_CommonModel):
|
|
264
271
|
-------
|
265
272
|
list[ValueType]
|
266
273
|
Level 1 values of the MultiIndex columns in the .tsdf DataFrame
|
274
|
+
|
267
275
|
"""
|
268
276
|
return list(self.tsdf.columns.get_level_values(1))
|
269
277
|
|
@@ -276,6 +284,7 @@ class OpenFrame(_CommonModel):
|
|
276
284
|
-------
|
277
285
|
Pandas.Series[dt.date]
|
278
286
|
The first dates in the timeseries of all constituents
|
287
|
+
|
279
288
|
"""
|
280
289
|
return Series(
|
281
290
|
data=[i.first_idx for i in self.constituents],
|
@@ -293,6 +302,7 @@ class OpenFrame(_CommonModel):
|
|
293
302
|
-------
|
294
303
|
Pandas.Series[dt.date]
|
295
304
|
The last dates in the timeseries of all constituents
|
305
|
+
|
296
306
|
"""
|
297
307
|
return Series(
|
298
308
|
data=[i.last_idx for i in self.constituents],
|
@@ -311,6 +321,7 @@ class OpenFrame(_CommonModel):
|
|
311
321
|
Pandas.Series[int]
|
312
322
|
Number of days from the first date to the last for all
|
313
323
|
items in the frame.
|
324
|
+
|
314
325
|
"""
|
315
326
|
return Series(
|
316
327
|
data=[c.span_of_days for c in self.constituents],
|
@@ -319,27 +330,6 @@ class OpenFrame(_CommonModel):
|
|
319
330
|
dtype=Int64Dtype(),
|
320
331
|
)
|
321
332
|
|
322
|
-
@property
|
323
|
-
def worst_month(self: Self) -> Series[float]:
|
324
|
-
"""
|
325
|
-
Most negative month.
|
326
|
-
|
327
|
-
Returns
|
328
|
-
-------
|
329
|
-
Pandas.Series[float]
|
330
|
-
Most negative month
|
331
|
-
"""
|
332
|
-
wdf = self.tsdf.copy()
|
333
|
-
wdf.index = DatetimeIndex(wdf.index)
|
334
|
-
return Series(
|
335
|
-
data=wdf.resample("BM")
|
336
|
-
.last()
|
337
|
-
.pct_change(fill_method=cast(str, None))
|
338
|
-
.min(),
|
339
|
-
name="Worst month",
|
340
|
-
dtype="float64",
|
341
|
-
)
|
342
|
-
|
343
333
|
def value_to_ret(self: Self) -> Self:
|
344
334
|
"""
|
345
335
|
Convert series of values into series of returns.
|
@@ -348,6 +338,7 @@ class OpenFrame(_CommonModel):
|
|
348
338
|
-------
|
349
339
|
OpenFrame
|
350
340
|
The returns of the values in the series
|
341
|
+
|
351
342
|
"""
|
352
343
|
self.tsdf = self.tsdf.pct_change(fill_method=cast(str, None))
|
353
344
|
self.tsdf.iloc[0] = 0
|
@@ -370,6 +361,7 @@ class OpenFrame(_CommonModel):
|
|
370
361
|
-------
|
371
362
|
OpenFrame
|
372
363
|
An OpenFrame object
|
364
|
+
|
373
365
|
"""
|
374
366
|
self.tsdf = self.tsdf.diff(periods=periods)
|
375
367
|
self.tsdf.iloc[0] = 0
|
@@ -386,6 +378,7 @@ class OpenFrame(_CommonModel):
|
|
386
378
|
-------
|
387
379
|
OpenFrame
|
388
380
|
An OpenFrame object
|
381
|
+
|
389
382
|
"""
|
390
383
|
if any(
|
391
384
|
x == ValueType.PRICE
|
@@ -402,20 +395,21 @@ class OpenFrame(_CommonModel):
|
|
402
395
|
|
403
396
|
def resample(
|
404
397
|
self: Self,
|
405
|
-
freq: Union[LiteralBizDayFreq, str] = "
|
398
|
+
freq: Union[LiteralBizDayFreq, str] = "BME",
|
406
399
|
) -> Self:
|
407
400
|
"""
|
408
401
|
Resample the timeseries frequency.
|
409
402
|
|
410
403
|
Parameters
|
411
404
|
----------
|
412
|
-
freq: Union[LiteralBizDayFreq, str], default "
|
405
|
+
freq: Union[LiteralBizDayFreq, str], default "BME"
|
413
406
|
The date offset string that sets the resampled frequency
|
414
407
|
|
415
408
|
Returns
|
416
409
|
-------
|
417
410
|
OpenFrame
|
418
411
|
An OpenFrame object
|
412
|
+
|
419
413
|
"""
|
420
414
|
self.tsdf.index = DatetimeIndex(self.tsdf.index)
|
421
415
|
self.tsdf = self.tsdf.resample(freq).last()
|
@@ -431,9 +425,8 @@ class OpenFrame(_CommonModel):
|
|
431
425
|
|
432
426
|
def resample_to_business_period_ends(
|
433
427
|
self: Self,
|
434
|
-
freq: LiteralBizDayFreq = "
|
428
|
+
freq: LiteralBizDayFreq = "BME",
|
435
429
|
countries: CountriesType = "SE",
|
436
|
-
convention: LiteralPandasResampleConvention = "end",
|
437
430
|
method: LiteralPandasReindexMethod = "nearest",
|
438
431
|
) -> Self:
|
439
432
|
"""
|
@@ -443,13 +436,11 @@ class OpenFrame(_CommonModel):
|
|
443
436
|
|
444
437
|
Parameters
|
445
438
|
----------
|
446
|
-
freq: LiteralBizDayFreq, default "
|
439
|
+
freq: LiteralBizDayFreq, default "BME"
|
447
440
|
The date offset string that sets the resampled frequency
|
448
441
|
countries: CountriesType, default: "SE"
|
449
442
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
450
443
|
to create a business day calendar used for date adjustments
|
451
|
-
convention: LiteralPandasResampleConvention, default; end
|
452
|
-
Controls whether to use the start or end of `rule`.
|
453
444
|
method: LiteralPandasReindexMethod, default: nearest
|
454
445
|
Controls the method used to align values across columns
|
455
446
|
|
@@ -457,6 +448,7 @@ class OpenFrame(_CommonModel):
|
|
457
448
|
-------
|
458
449
|
OpenFrame
|
459
450
|
An OpenFrame object
|
451
|
+
|
460
452
|
"""
|
461
453
|
head = self.tsdf.loc[self.first_indices.max()].copy()
|
462
454
|
tail = self.tsdf.loc[self.last_indices.min()].copy()
|
@@ -466,7 +458,6 @@ class OpenFrame(_CommonModel):
|
|
466
458
|
tail=tail,
|
467
459
|
freq=freq,
|
468
460
|
countries=countries,
|
469
|
-
convention=convention,
|
470
461
|
)
|
471
462
|
self.tsdf = self.tsdf.reindex([deyt.date() for deyt in dates], method=method)
|
472
463
|
for xerie in self.constituents:
|
@@ -521,6 +512,7 @@ class OpenFrame(_CommonModel):
|
|
521
512
|
-------
|
522
513
|
Pandas.DataFrame
|
523
514
|
Series volatilities and correlation
|
515
|
+
|
524
516
|
"""
|
525
517
|
earlier, later = self.calc_range(months_from_last, from_date, to_date)
|
526
518
|
if periods_in_a_year_fixed is None:
|
@@ -611,6 +603,7 @@ class OpenFrame(_CommonModel):
|
|
611
603
|
-------
|
612
604
|
Pandas.DataFrame
|
613
605
|
Correlation matrix
|
606
|
+
|
614
607
|
"""
|
615
608
|
corr_matrix = self.tsdf.pct_change(fill_method=cast(str, None)).corr(
|
616
609
|
method="pearson",
|
@@ -637,6 +630,7 @@ class OpenFrame(_CommonModel):
|
|
637
630
|
-------
|
638
631
|
OpenFrame
|
639
632
|
An OpenFrame object
|
633
|
+
|
640
634
|
"""
|
641
635
|
self.constituents += [new_series]
|
642
636
|
self.tsdf = concat([self.tsdf, new_series.tsdf], axis="columns", sort=True)
|
@@ -655,6 +649,7 @@ class OpenFrame(_CommonModel):
|
|
655
649
|
-------
|
656
650
|
OpenFrame
|
657
651
|
An OpenFrame object
|
652
|
+
|
658
653
|
"""
|
659
654
|
if self.weights:
|
660
655
|
new_c, new_w = [], []
|
@@ -694,6 +689,7 @@ class OpenFrame(_CommonModel):
|
|
694
689
|
-------
|
695
690
|
OpenFrame
|
696
691
|
An OpenFrame object
|
692
|
+
|
697
693
|
"""
|
698
694
|
if not start_cut and where in ["before", "both"]:
|
699
695
|
start_cut = self.first_indices.max()
|
@@ -743,6 +739,7 @@ class OpenFrame(_CommonModel):
|
|
743
739
|
base_zero: bool, default: True
|
744
740
|
If set to False 1.0 is added to allow for a capital base and
|
745
741
|
to allow a volatility calculation
|
742
|
+
|
746
743
|
"""
|
747
744
|
rel_label = (
|
748
745
|
cast(tuple[str, str], self.tsdf.iloc[:, long_column].name)[0]
|
@@ -795,6 +792,7 @@ class OpenFrame(_CommonModel):
|
|
795
792
|
-------
|
796
793
|
Pandas.Series[float]
|
797
794
|
Tracking Errors
|
795
|
+
|
798
796
|
"""
|
799
797
|
earlier, later = self.calc_range(months_from_last, from_date, to_date)
|
800
798
|
fraction = (later - earlier).days / 365.25
|
@@ -888,6 +886,7 @@ class OpenFrame(_CommonModel):
|
|
888
886
|
-------
|
889
887
|
Pandas.Series[float]
|
890
888
|
Information Ratios
|
889
|
+
|
891
890
|
"""
|
892
891
|
earlier, later = self.calc_range(months_from_last, from_date, to_date)
|
893
892
|
fraction = (later - earlier).days / 365.25
|
@@ -992,6 +991,7 @@ class OpenFrame(_CommonModel):
|
|
992
991
|
-------
|
993
992
|
Pandas.Series[float]
|
994
993
|
Capture Ratios
|
994
|
+
|
995
995
|
"""
|
996
996
|
loss_limit: float = 0.0
|
997
997
|
earlier, later = self.calc_range(months_from_last, from_date, to_date)
|
@@ -1172,6 +1172,7 @@ class OpenFrame(_CommonModel):
|
|
1172
1172
|
-------
|
1173
1173
|
float
|
1174
1174
|
Beta as Co-variance of x & y divided by Variance of x
|
1175
|
+
|
1175
1176
|
"""
|
1176
1177
|
if all(
|
1177
1178
|
x_value == ValueType.RTRN
|
@@ -1261,6 +1262,7 @@ class OpenFrame(_CommonModel):
|
|
1261
1262
|
-------
|
1262
1263
|
OLSResults
|
1263
1264
|
The Statsmodels regression output
|
1265
|
+
|
1264
1266
|
"""
|
1265
1267
|
if isinstance(y_column, tuple):
|
1266
1268
|
y_value = self.tsdf.loc[:, y_column]
|
@@ -1327,6 +1329,7 @@ class OpenFrame(_CommonModel):
|
|
1327
1329
|
-------
|
1328
1330
|
float
|
1329
1331
|
Jensen's alpha
|
1332
|
+
|
1330
1333
|
"""
|
1331
1334
|
full_year = 1.0
|
1332
1335
|
if all(
|
@@ -1478,6 +1481,7 @@ class OpenFrame(_CommonModel):
|
|
1478
1481
|
-------
|
1479
1482
|
Pandas.DataFrame
|
1480
1483
|
A basket timeseries
|
1484
|
+
|
1481
1485
|
"""
|
1482
1486
|
if self.weights is None and weight_strat is None:
|
1483
1487
|
msg = (
|
@@ -1562,6 +1566,7 @@ class OpenFrame(_CommonModel):
|
|
1562
1566
|
-------
|
1563
1567
|
Pandas.DataFrame
|
1564
1568
|
Rolling Information Ratios
|
1569
|
+
|
1565
1570
|
"""
|
1566
1571
|
long_label = cast(
|
1567
1572
|
tuple[str, str],
|
@@ -1624,6 +1629,7 @@ class OpenFrame(_CommonModel):
|
|
1624
1629
|
-------
|
1625
1630
|
Pandas.DataFrame
|
1626
1631
|
Rolling Betas
|
1632
|
+
|
1627
1633
|
"""
|
1628
1634
|
market_label = cast(tuple[str, str], self.tsdf.iloc[:, market_column].name)[0]
|
1629
1635
|
asset_label = cast(tuple[str, str], self.tsdf.iloc[:, asset_column].name)[0]
|
@@ -1679,6 +1685,7 @@ class OpenFrame(_CommonModel):
|
|
1679
1685
|
-------
|
1680
1686
|
Pandas.DataFrame
|
1681
1687
|
Rolling Correlations
|
1688
|
+
|
1682
1689
|
"""
|
1683
1690
|
corr_label = (
|
1684
1691
|
cast(tuple[str, str], self.tsdf.iloc[:, first_column].name)[0]
|
openseries/load_plotly.py
CHANGED
@@ -23,6 +23,7 @@ def _check_remote_file_existence(url: str) -> bool:
|
|
23
23
|
-------
|
24
24
|
bool
|
25
25
|
True if url is valid and False otherwise
|
26
|
+
|
26
27
|
"""
|
27
28
|
ok_code = 200
|
28
29
|
|
@@ -51,6 +52,7 @@ def load_plotly_dict(
|
|
51
52
|
-------
|
52
53
|
tuple[PlotlyLayoutType, CaptorLogoType]
|
53
54
|
A dictionary with the Plotly config and layout template
|
55
|
+
|
54
56
|
"""
|
55
57
|
project_root = Path(__file__).resolve().parent.parent
|
56
58
|
layoutfile = project_root.joinpath("openseries").joinpath("plotly_layouts.json")
|
openseries/series.py
CHANGED
@@ -41,7 +41,6 @@ from openseries.types import (
|
|
41
41
|
DaysInYearType,
|
42
42
|
LiteralBizDayFreq,
|
43
43
|
LiteralPandasReindexMethod,
|
44
|
-
LiteralPandasResampleConvention,
|
45
44
|
LiteralSeriesProps,
|
46
45
|
OpenTimeSeriesPropertiesList,
|
47
46
|
ValueListType,
|
@@ -89,6 +88,7 @@ class OpenTimeSeries(_CommonModel):
|
|
89
88
|
ISO 6166 identifier code of the associated instrument
|
90
89
|
label : str, optional
|
91
90
|
Placeholder for a name of the timeseries
|
91
|
+
|
92
92
|
"""
|
93
93
|
|
94
94
|
timeseries_id: DatabaseIdStringType
|
@@ -141,6 +141,7 @@ class OpenTimeSeries(_CommonModel):
|
|
141
141
|
Currency code according to ISO 4217
|
142
142
|
countries: CountriesType, default: "SE"
|
143
143
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
144
|
+
|
144
145
|
"""
|
145
146
|
_ = Currency(ccy=domestic_ccy)
|
146
147
|
_ = Countries(countryinput=countries)
|
@@ -190,6 +191,7 @@ class OpenTimeSeries(_CommonModel):
|
|
190
191
|
-------
|
191
192
|
OpenTimeSeries
|
192
193
|
An OpenTimeSeries object
|
194
|
+
|
193
195
|
"""
|
194
196
|
return cls(
|
195
197
|
name=name,
|
@@ -240,6 +242,7 @@ class OpenTimeSeries(_CommonModel):
|
|
240
242
|
-------
|
241
243
|
OpenTimeSeries
|
242
244
|
An OpenTimeSeries object
|
245
|
+
|
243
246
|
"""
|
244
247
|
if isinstance(dframe, Series):
|
245
248
|
if isinstance(dframe.name, tuple):
|
@@ -334,6 +337,7 @@ class OpenTimeSeries(_CommonModel):
|
|
334
337
|
-------
|
335
338
|
OpenTimeSeries
|
336
339
|
An OpenTimeSeries object
|
340
|
+
|
337
341
|
"""
|
338
342
|
if not isinstance(d_range, DatetimeIndex) and all([days, end_dt]):
|
339
343
|
d_range = DatetimeIndex(
|
@@ -381,6 +385,7 @@ class OpenTimeSeries(_CommonModel):
|
|
381
385
|
-------
|
382
386
|
OpenTimeSeries
|
383
387
|
An OpenTimeSeries object
|
388
|
+
|
384
389
|
"""
|
385
390
|
return deepcopy(self)
|
386
391
|
|
@@ -392,6 +397,7 @@ class OpenTimeSeries(_CommonModel):
|
|
392
397
|
-------
|
393
398
|
OpenTimeSeries
|
394
399
|
An OpenTimeSeries object
|
400
|
+
|
395
401
|
"""
|
396
402
|
dframe = DataFrame(
|
397
403
|
data=self.values,
|
@@ -419,6 +425,7 @@ class OpenTimeSeries(_CommonModel):
|
|
419
425
|
-------
|
420
426
|
pandas.DataFrame
|
421
427
|
Properties of the OpenTimeSeries
|
428
|
+
|
422
429
|
"""
|
423
430
|
if not properties:
|
424
431
|
properties = cast(
|
@@ -431,27 +438,6 @@ class OpenTimeSeries(_CommonModel):
|
|
431
438
|
pdf.columns = self.tsdf.columns
|
432
439
|
return pdf
|
433
440
|
|
434
|
-
@property
|
435
|
-
def worst_month(self: Self) -> float:
|
436
|
-
"""
|
437
|
-
Most negative month.
|
438
|
-
|
439
|
-
Returns
|
440
|
-
-------
|
441
|
-
float
|
442
|
-
Most negative month
|
443
|
-
"""
|
444
|
-
resdf = self.tsdf.copy()
|
445
|
-
resdf.index = DatetimeIndex(resdf.index)
|
446
|
-
return float(
|
447
|
-
(
|
448
|
-
resdf.resample("BM")
|
449
|
-
.last()
|
450
|
-
.pct_change(fill_method=cast(str, None))
|
451
|
-
.min()
|
452
|
-
).iloc[0],
|
453
|
-
)
|
454
|
-
|
455
441
|
def value_to_ret(self: Self) -> Self:
|
456
442
|
"""
|
457
443
|
Convert series of values into series of returns.
|
@@ -460,6 +446,7 @@ class OpenTimeSeries(_CommonModel):
|
|
460
446
|
-------
|
461
447
|
OpenTimeSeries
|
462
448
|
The returns of the values in the series
|
449
|
+
|
463
450
|
"""
|
464
451
|
self.tsdf = self.tsdf.pct_change(fill_method=cast(str, None))
|
465
452
|
self.tsdf.iloc[0] = 0
|
@@ -486,6 +473,7 @@ class OpenTimeSeries(_CommonModel):
|
|
486
473
|
-------
|
487
474
|
OpenTimeSeries
|
488
475
|
An OpenTimeSeries object
|
476
|
+
|
489
477
|
"""
|
490
478
|
self.tsdf = self.tsdf.diff(periods=periods)
|
491
479
|
self.tsdf.iloc[0] = 0
|
@@ -506,6 +494,7 @@ class OpenTimeSeries(_CommonModel):
|
|
506
494
|
-------
|
507
495
|
OpenTimeSeries
|
508
496
|
An OpenTimeSeries object
|
497
|
+
|
509
498
|
"""
|
510
499
|
if not any(
|
511
500
|
x == ValueType.RTRN
|
@@ -543,6 +532,7 @@ class OpenTimeSeries(_CommonModel):
|
|
543
532
|
-------
|
544
533
|
OpenTimeSeries
|
545
534
|
An OpenTimeSeries object
|
535
|
+
|
546
536
|
"""
|
547
537
|
arr = array(self.values) / divider
|
548
538
|
|
@@ -563,21 +553,21 @@ class OpenTimeSeries(_CommonModel):
|
|
563
553
|
|
564
554
|
def resample(
|
565
555
|
self: Self,
|
566
|
-
freq: Union[LiteralBizDayFreq, str] = "
|
556
|
+
freq: Union[LiteralBizDayFreq, str] = "BME",
|
567
557
|
) -> Self:
|
568
558
|
"""
|
569
559
|
Resamples the timeseries frequency.
|
570
560
|
|
571
561
|
Parameters
|
572
562
|
----------
|
573
|
-
freq: Union[LiteralBizDayFreq, str], default "
|
563
|
+
freq: Union[LiteralBizDayFreq, str], default "BME"
|
574
564
|
The date offset string that sets the resampled frequency
|
575
|
-
Examples are "7D", "B", "M", "BM", "Q", "BQ", "A", "BA"
|
576
565
|
|
577
566
|
Returns
|
578
567
|
-------
|
579
568
|
OpenTimeSeries
|
580
569
|
An OpenTimeSeries object
|
570
|
+
|
581
571
|
"""
|
582
572
|
self.tsdf.index = DatetimeIndex(self.tsdf.index)
|
583
573
|
self.tsdf = self.tsdf.resample(freq).last()
|
@@ -586,8 +576,7 @@ class OpenTimeSeries(_CommonModel):
|
|
586
576
|
|
587
577
|
def resample_to_business_period_ends(
|
588
578
|
self: Self,
|
589
|
-
freq: LiteralBizDayFreq = "
|
590
|
-
convention: LiteralPandasResampleConvention = "end",
|
579
|
+
freq: LiteralBizDayFreq = "BME",
|
591
580
|
method: LiteralPandasReindexMethod = "nearest",
|
592
581
|
) -> Self:
|
593
582
|
"""
|
@@ -597,10 +586,8 @@ class OpenTimeSeries(_CommonModel):
|
|
597
586
|
|
598
587
|
Parameters
|
599
588
|
----------
|
600
|
-
freq: LiteralBizDayFreq, default
|
589
|
+
freq: LiteralBizDayFreq, default BME
|
601
590
|
The date offset string that sets the resampled frequency
|
602
|
-
convention: LiteralPandasResampleConvention, default; end
|
603
|
-
Controls whether to use the start or end of `rule`.
|
604
591
|
method: LiteralPandasReindexMethod, default: nearest
|
605
592
|
Controls the method used to align values across columns
|
606
593
|
|
@@ -608,6 +595,7 @@ class OpenTimeSeries(_CommonModel):
|
|
608
595
|
-------
|
609
596
|
OpenTimeSeries
|
610
597
|
An OpenTimeSeries object
|
598
|
+
|
611
599
|
"""
|
612
600
|
head = self.tsdf.iloc[0].copy()
|
613
601
|
tail = self.tsdf.iloc[-1].copy()
|
@@ -617,7 +605,6 @@ class OpenTimeSeries(_CommonModel):
|
|
617
605
|
tail=tail,
|
618
606
|
freq=freq,
|
619
607
|
countries=self.countries,
|
620
|
-
convention=convention,
|
621
608
|
)
|
622
609
|
self.tsdf = self.tsdf.reindex([deyt.date() for deyt in dates], method=method)
|
623
610
|
return self
|
@@ -659,6 +646,7 @@ class OpenTimeSeries(_CommonModel):
|
|
659
646
|
-------
|
660
647
|
Pandas.Series[float]
|
661
648
|
Series EWMA volatility
|
649
|
+
|
662
650
|
"""
|
663
651
|
earlier, later = self.calc_range(months_from_last, from_date, to_date)
|
664
652
|
if periods_in_a_year_fixed:
|
@@ -722,6 +710,7 @@ class OpenTimeSeries(_CommonModel):
|
|
722
710
|
-------
|
723
711
|
OpenTimeSeries
|
724
712
|
An OpenTimeSeries object
|
713
|
+
|
725
714
|
"""
|
726
715
|
values: list[float]
|
727
716
|
if any(
|
@@ -787,6 +776,7 @@ class OpenTimeSeries(_CommonModel):
|
|
787
776
|
-------
|
788
777
|
OpenTimeSeries
|
789
778
|
An OpenTimeSeries object
|
779
|
+
|
790
780
|
"""
|
791
781
|
if lvl_zero is None and lvl_one is None:
|
792
782
|
self.tsdf.columns = MultiIndex.from_arrays(
|
@@ -814,6 +804,8 @@ def timeseries_chain(
|
|
814
804
|
"""
|
815
805
|
Chain two timeseries together.
|
816
806
|
|
807
|
+
The function assumes that the two series have at least one date in common.
|
808
|
+
|
817
809
|
Parameters
|
818
810
|
----------
|
819
811
|
front: TypeOpenTimeSeries
|
@@ -827,6 +819,7 @@ def timeseries_chain(
|
|
827
819
|
-------
|
828
820
|
Union[TypeOpenTimeSeries, OpenTimeSeries]
|
829
821
|
An OpenTimeSeries object or a subclass thereof
|
822
|
+
|
830
823
|
"""
|
831
824
|
old = front.from_deepcopy()
|
832
825
|
old.running_adjustment(old_fee)
|
@@ -907,6 +900,7 @@ def _check_if_none(item: Any) -> bool: # noqa: ANN401
|
|
907
900
|
-------
|
908
901
|
bool
|
909
902
|
Answer to whether the variable is None or equivalent
|
903
|
+
|
910
904
|
"""
|
911
905
|
try:
|
912
906
|
return cast(bool, isnan(item))
|
openseries/simulation.py
CHANGED
@@ -37,6 +37,7 @@ def random_generator(seed: Optional[int]) -> Generator:
|
|
37
37
|
-------
|
38
38
|
numpy.random.Generator
|
39
39
|
Numpy random process generator
|
40
|
+
|
40
41
|
"""
|
41
42
|
ss = SeedSequence(entropy=seed)
|
42
43
|
bg = PCG64(seed=cast(Optional[int], ss))
|
@@ -66,6 +67,7 @@ class ReturnSimulation(BaseModel):
|
|
66
67
|
Seed for random process initiation
|
67
68
|
randomizer: numpy.random.Generator, optional
|
68
69
|
Random process generator
|
70
|
+
|
69
71
|
"""
|
70
72
|
|
71
73
|
number_of_sims: PositiveInt
|
@@ -92,6 +94,7 @@ class ReturnSimulation(BaseModel):
|
|
92
94
|
-------
|
93
95
|
pandas.DataFrame
|
94
96
|
Simulation data
|
97
|
+
|
95
98
|
"""
|
96
99
|
return self.dframe.add(1.0).cumprod(axis="columns").T
|
97
100
|
|
@@ -104,6 +107,7 @@ class ReturnSimulation(BaseModel):
|
|
104
107
|
-------
|
105
108
|
float
|
106
109
|
Annualized arithmetic mean of returns
|
110
|
+
|
107
111
|
"""
|
108
112
|
return cast(
|
109
113
|
float,
|
@@ -122,6 +126,7 @@ class ReturnSimulation(BaseModel):
|
|
122
126
|
-------
|
123
127
|
float
|
124
128
|
Annualized volatility
|
129
|
+
|
125
130
|
"""
|
126
131
|
return cast(
|
127
132
|
float,
|
@@ -164,6 +169,7 @@ class ReturnSimulation(BaseModel):
|
|
164
169
|
-------
|
165
170
|
ReturnSimulation
|
166
171
|
Normal distribution simulation
|
172
|
+
|
167
173
|
"""
|
168
174
|
cls.randomizer = random_generator(seed=seed)
|
169
175
|
|
@@ -217,6 +223,7 @@ class ReturnSimulation(BaseModel):
|
|
217
223
|
-------
|
218
224
|
ReturnSimulation
|
219
225
|
Lognormal distribution simulation
|
226
|
+
|
220
227
|
"""
|
221
228
|
cls.randomizer = random_generator(seed=seed)
|
222
229
|
|
@@ -272,6 +279,7 @@ class ReturnSimulation(BaseModel):
|
|
272
279
|
-------
|
273
280
|
ReturnSimulation
|
274
281
|
Geometric Brownian Motion simulation
|
282
|
+
|
275
283
|
"""
|
276
284
|
cls.randomizer = random_generator(seed=seed)
|
277
285
|
|
@@ -340,6 +348,7 @@ class ReturnSimulation(BaseModel):
|
|
340
348
|
-------
|
341
349
|
ReturnSimulation
|
342
350
|
Merton Jump-Diffusion model simulation
|
351
|
+
|
343
352
|
"""
|
344
353
|
cls.randomizer = random_generator(seed=seed)
|
345
354
|
|
@@ -408,6 +417,7 @@ class ReturnSimulation(BaseModel):
|
|
408
417
|
-------
|
409
418
|
pandas.DataFrame
|
410
419
|
Object based on the simulation(s)
|
420
|
+
|
411
421
|
"""
|
412
422
|
d_range = generate_calendar_date_range(
|
413
423
|
trading_days=self.trading_days,
|
openseries/types.py
CHANGED
@@ -122,8 +122,7 @@ LiteralLinePlotMode = Literal[
|
|
122
122
|
]
|
123
123
|
LiteralHowMerge = Literal["outer", "inner"]
|
124
124
|
LiteralQuantileInterp = Literal["linear", "lower", "higher", "midpoint", "nearest"]
|
125
|
-
LiteralBizDayFreq = Literal["
|
126
|
-
LiteralPandasResampleConvention = Literal["start", "s", "end", "e"]
|
125
|
+
LiteralBizDayFreq = Literal["B", "BME", "BQE", "BYE"]
|
127
126
|
LiteralPandasReindexMethod = Literal[
|
128
127
|
None,
|
129
128
|
"pad",
|