openseries 1.5.7__py3-none-any.whl → 1.7.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.
- openseries/__init__.py +43 -0
- openseries/_common_model.py +237 -295
- openseries/_risk.py +9 -10
- openseries/datefixer.py +41 -36
- openseries/frame.py +120 -721
- openseries/load_plotly.py +10 -8
- openseries/portfoliotools.py +612 -0
- openseries/series.py +46 -64
- openseries/simulation.py +31 -38
- openseries/types.py +37 -24
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/LICENSE.md +1 -1
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/METADATA +4 -5
- openseries-1.7.0.dist-info/RECORD +16 -0
- openseries-1.5.7.dist-info/RECORD +0 -15
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/WHEEL +0 -0
openseries/series.py
CHANGED
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
5
5
|
import datetime as dt
|
6
6
|
from copy import deepcopy
|
7
7
|
from logging import warning
|
8
|
-
from typing import Any,
|
8
|
+
from typing import Any, TypeVar, cast
|
9
9
|
|
10
10
|
from numpy import (
|
11
11
|
append,
|
@@ -28,9 +28,9 @@ from pandas import (
|
|
28
28
|
from pydantic import model_validator
|
29
29
|
from typing_extensions import Self
|
30
30
|
|
31
|
-
from
|
32
|
-
from
|
33
|
-
from
|
31
|
+
from ._common_model import _CommonModel
|
32
|
+
from .datefixer import date_fix, do_resample_to_business_period_ends
|
33
|
+
from .types import (
|
34
34
|
Countries,
|
35
35
|
CountriesType,
|
36
36
|
Currency,
|
@@ -46,14 +46,14 @@ from openseries.types import (
|
|
46
46
|
ValueType,
|
47
47
|
)
|
48
48
|
|
49
|
+
__all__ = ["OpenTimeSeries", "timeseries_chain"]
|
50
|
+
|
49
51
|
TypeOpenTimeSeries = TypeVar("TypeOpenTimeSeries", bound="OpenTimeSeries")
|
50
52
|
|
51
53
|
|
52
54
|
# noinspection PyUnresolvedReferences
|
53
55
|
class OpenTimeSeries(_CommonModel):
|
54
|
-
|
55
|
-
"""
|
56
|
-
OpenTimeSeries objects are at the core of the openseries package.
|
56
|
+
"""OpenTimeSeries objects are at the core of the openseries package.
|
57
57
|
|
58
58
|
The intended use is to allow analyses of financial timeseries.
|
59
59
|
It is only intended for daily or less frequent data samples.
|
@@ -102,8 +102,8 @@ class OpenTimeSeries(_CommonModel):
|
|
102
102
|
currency: CurrencyStringType
|
103
103
|
domestic: CurrencyStringType = "SEK"
|
104
104
|
countries: CountriesType = "SE"
|
105
|
-
isin:
|
106
|
-
label:
|
105
|
+
isin: str | None = None
|
106
|
+
label: str | None = None
|
107
107
|
|
108
108
|
@model_validator(mode="after") # type: ignore[misc,unused-ignore]
|
109
109
|
def dates_and_values_validate(self: Self) -> Self:
|
@@ -132,8 +132,7 @@ class OpenTimeSeries(_CommonModel):
|
|
132
132
|
domestic_ccy: CurrencyStringType = "SEK",
|
133
133
|
countries: CountriesType = "SE",
|
134
134
|
) -> None:
|
135
|
-
"""
|
136
|
-
Set the domestic currency and calendar of the user.
|
135
|
+
"""Set the domestic currency and calendar of the user.
|
137
136
|
|
138
137
|
Parameters
|
139
138
|
----------
|
@@ -158,13 +157,12 @@ class OpenTimeSeries(_CommonModel):
|
|
158
157
|
valuetype: ValueType = ValueType.PRICE,
|
159
158
|
timeseries_id: DatabaseIdStringType = "",
|
160
159
|
instrument_id: DatabaseIdStringType = "",
|
161
|
-
isin:
|
160
|
+
isin: str | None = None,
|
162
161
|
baseccy: CurrencyStringType = "SEK",
|
163
162
|
*,
|
164
163
|
local_ccy: bool = True,
|
165
164
|
) -> OpenTimeSeries:
|
166
|
-
"""
|
167
|
-
Create series from a Pandas DataFrame or Series.
|
165
|
+
"""Create series from a Pandas DataFrame or Series.
|
168
166
|
|
169
167
|
Parameters
|
170
168
|
----------
|
@@ -215,19 +213,18 @@ class OpenTimeSeries(_CommonModel):
|
|
215
213
|
@classmethod
|
216
214
|
def from_df(
|
217
215
|
cls: type[OpenTimeSeries],
|
218
|
-
dframe:
|
216
|
+
dframe: DataFrame | Series[float],
|
219
217
|
column_nmbr: int = 0,
|
220
218
|
valuetype: ValueType = ValueType.PRICE,
|
221
219
|
baseccy: CurrencyStringType = "SEK",
|
222
220
|
*,
|
223
221
|
local_ccy: bool = True,
|
224
222
|
) -> OpenTimeSeries:
|
225
|
-
"""
|
226
|
-
Create series from a Pandas DataFrame or Series.
|
223
|
+
"""Create series from a Pandas DataFrame or Series.
|
227
224
|
|
228
225
|
Parameters
|
229
226
|
----------
|
230
|
-
dframe:
|
227
|
+
dframe: DataFrame | Series[float]
|
231
228
|
Pandas DataFrame or Series
|
232
229
|
column_nmbr : int, default: 0
|
233
230
|
Using iloc[:, column_nmbr] to pick column
|
@@ -297,17 +294,16 @@ class OpenTimeSeries(_CommonModel):
|
|
297
294
|
def from_fixed_rate(
|
298
295
|
cls: type[OpenTimeSeries],
|
299
296
|
rate: float,
|
300
|
-
d_range:
|
301
|
-
days:
|
302
|
-
end_dt:
|
297
|
+
d_range: DatetimeIndex | None = None,
|
298
|
+
days: int | None = None,
|
299
|
+
end_dt: dt.date | None = None,
|
303
300
|
label: str = "Series",
|
304
301
|
valuetype: ValueType = ValueType.PRICE,
|
305
302
|
baseccy: CurrencyStringType = "SEK",
|
306
303
|
*,
|
307
304
|
local_ccy: bool = True,
|
308
305
|
) -> OpenTimeSeries:
|
309
|
-
"""
|
310
|
-
Create series from values accruing with a given fixed rate return.
|
306
|
+
"""Create series from values accruing with a given fixed rate return.
|
311
307
|
|
312
308
|
Providing a date_range of type Pandas DatetimeIndex takes priority over
|
313
309
|
providing a combination of days and an end date.
|
@@ -378,8 +374,7 @@ class OpenTimeSeries(_CommonModel):
|
|
378
374
|
)
|
379
375
|
|
380
376
|
def from_deepcopy(self: Self) -> Self:
|
381
|
-
"""
|
382
|
-
Create copy of OpenTimeSeries object.
|
377
|
+
"""Create copy of OpenTimeSeries object.
|
383
378
|
|
384
379
|
Returns
|
385
380
|
-------
|
@@ -390,8 +385,7 @@ class OpenTimeSeries(_CommonModel):
|
|
390
385
|
return deepcopy(self)
|
391
386
|
|
392
387
|
def pandas_df(self: Self) -> Self:
|
393
|
-
"""
|
394
|
-
Populate .tsdf Pandas DataFrame from the .dates and .values lists.
|
388
|
+
"""Populate .tsdf Pandas DataFrame from the .dates and .values lists.
|
395
389
|
|
396
390
|
Returns
|
397
391
|
-------
|
@@ -411,10 +405,9 @@ class OpenTimeSeries(_CommonModel):
|
|
411
405
|
|
412
406
|
def all_properties(
|
413
407
|
self: Self,
|
414
|
-
properties:
|
408
|
+
properties: list[LiteralSeriesProps] | None = None,
|
415
409
|
) -> DataFrame:
|
416
|
-
"""
|
417
|
-
Calculate chosen properties.
|
410
|
+
"""Calculate chosen properties.
|
418
411
|
|
419
412
|
Parameters
|
420
413
|
----------
|
@@ -439,8 +432,7 @@ class OpenTimeSeries(_CommonModel):
|
|
439
432
|
return pdf
|
440
433
|
|
441
434
|
def value_to_ret(self: Self) -> Self:
|
442
|
-
"""
|
443
|
-
Convert series of values into series of returns.
|
435
|
+
"""Convert series of values into series of returns.
|
444
436
|
|
445
437
|
Returns
|
446
438
|
-------
|
@@ -448,7 +440,7 @@ class OpenTimeSeries(_CommonModel):
|
|
448
440
|
The returns of the values in the series
|
449
441
|
|
450
442
|
"""
|
451
|
-
self.tsdf = self.tsdf.pct_change(fill_method=
|
443
|
+
self.tsdf = self.tsdf.pct_change(fill_method=None) # type: ignore[arg-type]
|
452
444
|
self.tsdf.iloc[0] = 0
|
453
445
|
self.valuetype = ValueType.RTRN
|
454
446
|
self.tsdf.columns = MultiIndex.from_arrays(
|
@@ -460,8 +452,7 @@ class OpenTimeSeries(_CommonModel):
|
|
460
452
|
return self
|
461
453
|
|
462
454
|
def value_to_diff(self: Self, periods: int = 1) -> Self:
|
463
|
-
"""
|
464
|
-
Convert series of values to series of their period differences.
|
455
|
+
"""Convert series of values to series of their period differences.
|
465
456
|
|
466
457
|
Parameters
|
467
458
|
----------
|
@@ -487,8 +478,7 @@ class OpenTimeSeries(_CommonModel):
|
|
487
478
|
return self
|
488
479
|
|
489
480
|
def to_cumret(self: Self) -> Self:
|
490
|
-
"""
|
491
|
-
Convert series of returns into cumulative series of values.
|
481
|
+
"""Convert series of returns into cumulative series of values.
|
492
482
|
|
493
483
|
Returns
|
494
484
|
-------
|
@@ -518,8 +508,7 @@ class OpenTimeSeries(_CommonModel):
|
|
518
508
|
days_in_year: int = 365,
|
519
509
|
divider: float = 1.0,
|
520
510
|
) -> Self:
|
521
|
-
"""
|
522
|
-
Convert series of 1-day rates into series of cumulative values.
|
511
|
+
"""Convert series of 1-day rates into series of cumulative values.
|
523
512
|
|
524
513
|
Parameters
|
525
514
|
----------
|
@@ -553,14 +542,13 @@ class OpenTimeSeries(_CommonModel):
|
|
553
542
|
|
554
543
|
def resample(
|
555
544
|
self: Self,
|
556
|
-
freq:
|
545
|
+
freq: LiteralBizDayFreq | str = "BME",
|
557
546
|
) -> Self:
|
558
|
-
"""
|
559
|
-
Resamples the timeseries frequency.
|
547
|
+
"""Resamples the timeseries frequency.
|
560
548
|
|
561
549
|
Parameters
|
562
550
|
----------
|
563
|
-
freq:
|
551
|
+
freq: LiteralBizDayFreq | str, default "BME"
|
564
552
|
The date offset string that sets the resampled frequency
|
565
553
|
|
566
554
|
Returns
|
@@ -579,8 +567,7 @@ class OpenTimeSeries(_CommonModel):
|
|
579
567
|
freq: LiteralBizDayFreq = "BME",
|
580
568
|
method: LiteralPandasReindexMethod = "nearest",
|
581
569
|
) -> Self:
|
582
|
-
"""
|
583
|
-
Resamples timeseries frequency to the business calendar month end dates.
|
570
|
+
"""Resamples timeseries frequency to the business calendar month end dates.
|
584
571
|
|
585
572
|
Stubs left in place. Stubs will be aligned to the shortest stub.
|
586
573
|
|
@@ -614,13 +601,12 @@ class OpenTimeSeries(_CommonModel):
|
|
614
601
|
lmbda: float = 0.94,
|
615
602
|
day_chunk: int = 11,
|
616
603
|
dlta_degr_freedms: int = 0,
|
617
|
-
months_from_last:
|
618
|
-
from_date:
|
619
|
-
to_date:
|
620
|
-
periods_in_a_year_fixed:
|
604
|
+
months_from_last: int | None = None,
|
605
|
+
from_date: dt.date | None = None,
|
606
|
+
to_date: dt.date | None = None,
|
607
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
621
608
|
) -> Series[float]:
|
622
|
-
"""
|
623
|
-
Exponentially Weighted Moving Average Model for Volatility.
|
609
|
+
"""Exponentially Weighted Moving Average Model for Volatility.
|
624
610
|
|
625
611
|
https://www.investopedia.com/articles/07/ewma.asp.
|
626
612
|
|
@@ -692,8 +678,7 @@ class OpenTimeSeries(_CommonModel):
|
|
692
678
|
adjustment: float,
|
693
679
|
days_in_year: int = 365,
|
694
680
|
) -> Self:
|
695
|
-
"""
|
696
|
-
Add or subtract a fee from the timeseries return.
|
681
|
+
"""Add or subtract a fee from the timeseries return.
|
697
682
|
|
698
683
|
Parameters
|
699
684
|
----------
|
@@ -719,7 +704,7 @@ class OpenTimeSeries(_CommonModel):
|
|
719
704
|
returns_input = True
|
720
705
|
else:
|
721
706
|
values = [cast(float, self.tsdf.iloc[0, 0])]
|
722
|
-
ra_df = self.tsdf.pct_change(fill_method=
|
707
|
+
ra_df = self.tsdf.pct_change(fill_method=None) # type: ignore[arg-type]
|
723
708
|
returns_input = False
|
724
709
|
ra_df = ra_df.dropna()
|
725
710
|
|
@@ -752,13 +737,12 @@ class OpenTimeSeries(_CommonModel):
|
|
752
737
|
|
753
738
|
def set_new_label(
|
754
739
|
self: Self,
|
755
|
-
lvl_zero:
|
756
|
-
lvl_one:
|
740
|
+
lvl_zero: str | None = None,
|
741
|
+
lvl_one: ValueType | None = None,
|
757
742
|
*,
|
758
743
|
delete_lvl_one: bool = False,
|
759
744
|
) -> Self:
|
760
|
-
"""
|
761
|
-
Set the column labels of the .tsdf Pandas Dataframe.
|
745
|
+
"""Set the column labels of the .tsdf Pandas Dataframe.
|
762
746
|
|
763
747
|
Parameters
|
764
748
|
----------
|
@@ -797,9 +781,8 @@ def timeseries_chain(
|
|
797
781
|
front: TypeOpenTimeSeries,
|
798
782
|
back: TypeOpenTimeSeries,
|
799
783
|
old_fee: float = 0.0,
|
800
|
-
) ->
|
801
|
-
"""
|
802
|
-
Chain two timeseries together.
|
784
|
+
) -> TypeOpenTimeSeries | OpenTimeSeries:
|
785
|
+
"""Chain two timeseries together.
|
803
786
|
|
804
787
|
The function assumes that the two series have at least one date in common.
|
805
788
|
|
@@ -814,7 +797,7 @@ def timeseries_chain(
|
|
814
797
|
|
815
798
|
Returns
|
816
799
|
-------
|
817
|
-
|
800
|
+
TypeOpenTimeSeries | OpenTimeSeries
|
818
801
|
An OpenTimeSeries object or a subclass thereof
|
819
802
|
|
820
803
|
"""
|
@@ -885,8 +868,7 @@ def timeseries_chain(
|
|
885
868
|
|
886
869
|
|
887
870
|
def _check_if_none(item: Any) -> bool: # noqa: ANN401
|
888
|
-
"""
|
889
|
-
Check if a variable is None or equivalent.
|
871
|
+
"""Check if a variable is None or equivalent.
|
890
872
|
|
891
873
|
Parameters
|
892
874
|
----------
|
openseries/simulation.py
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
import
|
6
|
-
|
5
|
+
from typing import TYPE_CHECKING, cast
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
import datetime as dt # pragma: no cover
|
7
9
|
|
8
10
|
from numpy import multiply, sqrt
|
9
11
|
from numpy.random import PCG64, Generator, SeedSequence
|
@@ -22,17 +24,18 @@ from pydantic import (
|
|
22
24
|
)
|
23
25
|
from typing_extensions import Self
|
24
26
|
|
25
|
-
from
|
26
|
-
from
|
27
|
+
from .datefixer import generate_calendar_date_range
|
28
|
+
from .types import (
|
27
29
|
CountriesType,
|
28
30
|
DaysInYearType,
|
29
31
|
ValueType,
|
30
32
|
)
|
31
33
|
|
34
|
+
__all__ = ["ReturnSimulation"]
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
Make a Numpy Random Generator object.
|
36
|
+
|
37
|
+
def _random_generator(seed: int | None) -> Generator:
|
38
|
+
"""Make a Numpy Random Generator object.
|
36
39
|
|
37
40
|
Parameters
|
38
41
|
----------
|
@@ -46,14 +49,12 @@ def random_generator(seed: Optional[int]) -> Generator:
|
|
46
49
|
|
47
50
|
"""
|
48
51
|
ss = SeedSequence(entropy=seed)
|
49
|
-
bg = PCG64(seed=cast(
|
52
|
+
bg = PCG64(seed=cast(int | None, ss))
|
50
53
|
return Generator(bit_generator=bg)
|
51
54
|
|
52
55
|
|
53
56
|
class ReturnSimulation(BaseModel):
|
54
|
-
|
55
|
-
"""
|
56
|
-
The class ReturnSimulation allows for simulating financial timeseries.
|
57
|
+
"""The class ReturnSimulation allows for simulating financial timeseries.
|
57
58
|
|
58
59
|
Parameters
|
59
60
|
----------
|
@@ -89,7 +90,7 @@ class ReturnSimulation(BaseModel):
|
|
89
90
|
jumps_lamda: NonNegativeFloat = 0.0
|
90
91
|
jumps_sigma: NonNegativeFloat = 0.0
|
91
92
|
jumps_mu: float = 0.0
|
92
|
-
seed:
|
93
|
+
seed: int | None = None
|
93
94
|
|
94
95
|
model_config = ConfigDict(
|
95
96
|
arbitrary_types_allowed=True,
|
@@ -99,8 +100,7 @@ class ReturnSimulation(BaseModel):
|
|
99
100
|
|
100
101
|
@property
|
101
102
|
def results(self: Self) -> DataFrame:
|
102
|
-
"""
|
103
|
-
Simulation data.
|
103
|
+
"""Simulation data.
|
104
104
|
|
105
105
|
Returns
|
106
106
|
-------
|
@@ -112,8 +112,7 @@ class ReturnSimulation(BaseModel):
|
|
112
112
|
|
113
113
|
@property
|
114
114
|
def realized_mean_return(self: Self) -> float:
|
115
|
-
"""
|
116
|
-
Annualized arithmetic mean of returns.
|
115
|
+
"""Annualized arithmetic mean of returns.
|
117
116
|
|
118
117
|
Returns
|
119
118
|
-------
|
@@ -131,8 +130,7 @@ class ReturnSimulation(BaseModel):
|
|
131
130
|
|
132
131
|
@property
|
133
132
|
def realized_vol(self: Self) -> float:
|
134
|
-
"""
|
135
|
-
Annualized volatility.
|
133
|
+
"""Annualized volatility.
|
136
134
|
|
137
135
|
Returns
|
138
136
|
-------
|
@@ -157,10 +155,9 @@ class ReturnSimulation(BaseModel):
|
|
157
155
|
trading_days: PositiveInt,
|
158
156
|
seed: int,
|
159
157
|
trading_days_in_year: DaysInYearType = 252,
|
160
|
-
randomizer:
|
158
|
+
randomizer: Generator | None = None,
|
161
159
|
) -> ReturnSimulation:
|
162
|
-
"""
|
163
|
-
Create a Normal distribution simulation.
|
160
|
+
"""Create a Normal distribution simulation.
|
164
161
|
|
165
162
|
Parameters
|
166
163
|
----------
|
@@ -187,7 +184,7 @@ class ReturnSimulation(BaseModel):
|
|
187
184
|
|
188
185
|
"""
|
189
186
|
if not randomizer:
|
190
|
-
randomizer =
|
187
|
+
randomizer = _random_generator(seed=seed)
|
191
188
|
|
192
189
|
returns = randomizer.normal(
|
193
190
|
loc=mean_annual_return / trading_days_in_year,
|
@@ -214,10 +211,9 @@ class ReturnSimulation(BaseModel):
|
|
214
211
|
trading_days: PositiveInt,
|
215
212
|
seed: int,
|
216
213
|
trading_days_in_year: DaysInYearType = 252,
|
217
|
-
randomizer:
|
214
|
+
randomizer: Generator | None = None,
|
218
215
|
) -> ReturnSimulation:
|
219
|
-
"""
|
220
|
-
Create a Lognormal distribution simulation.
|
216
|
+
"""Create a Lognormal distribution simulation.
|
221
217
|
|
222
218
|
Parameters
|
223
219
|
----------
|
@@ -244,7 +240,7 @@ class ReturnSimulation(BaseModel):
|
|
244
240
|
|
245
241
|
"""
|
246
242
|
if not randomizer:
|
247
|
-
randomizer =
|
243
|
+
randomizer = _random_generator(seed=seed)
|
248
244
|
|
249
245
|
returns = (
|
250
246
|
randomizer.lognormal(
|
@@ -274,10 +270,9 @@ class ReturnSimulation(BaseModel):
|
|
274
270
|
trading_days: PositiveInt,
|
275
271
|
seed: int,
|
276
272
|
trading_days_in_year: DaysInYearType = 252,
|
277
|
-
randomizer:
|
273
|
+
randomizer: Generator | None = None,
|
278
274
|
) -> ReturnSimulation:
|
279
|
-
"""
|
280
|
-
Create a Geometric Brownian Motion simulation.
|
275
|
+
"""Create a Geometric Brownian Motion simulation.
|
281
276
|
|
282
277
|
Parameters
|
283
278
|
----------
|
@@ -303,7 +298,7 @@ class ReturnSimulation(BaseModel):
|
|
303
298
|
|
304
299
|
"""
|
305
300
|
if not randomizer:
|
306
|
-
randomizer =
|
301
|
+
randomizer = _random_generator(seed=seed)
|
307
302
|
|
308
303
|
drift = (mean_annual_return - 0.5 * mean_annual_vol**2.0) * (
|
309
304
|
1.0 / trading_days_in_year
|
@@ -340,10 +335,9 @@ class ReturnSimulation(BaseModel):
|
|
340
335
|
jumps_sigma: NonNegativeFloat = 0.0,
|
341
336
|
jumps_mu: float = 0.0,
|
342
337
|
trading_days_in_year: DaysInYearType = 252,
|
343
|
-
randomizer:
|
338
|
+
randomizer: Generator | None = None,
|
344
339
|
) -> ReturnSimulation:
|
345
|
-
"""
|
346
|
-
Create a Merton Jump-Diffusion model simulation.
|
340
|
+
"""Create a Merton Jump-Diffusion model simulation.
|
347
341
|
|
348
342
|
Parameters
|
349
343
|
----------
|
@@ -375,7 +369,7 @@ class ReturnSimulation(BaseModel):
|
|
375
369
|
|
376
370
|
"""
|
377
371
|
if not randomizer:
|
378
|
-
randomizer =
|
372
|
+
randomizer = _random_generator(seed=seed)
|
379
373
|
|
380
374
|
normal_mean = 0.0
|
381
375
|
wiener = randomizer.normal(
|
@@ -422,12 +416,11 @@ class ReturnSimulation(BaseModel):
|
|
422
416
|
def to_dataframe(
|
423
417
|
self: Self,
|
424
418
|
name: str,
|
425
|
-
start:
|
426
|
-
end:
|
419
|
+
start: dt.date | None = None,
|
420
|
+
end: dt.date | None = None,
|
427
421
|
countries: CountriesType = "SE",
|
428
422
|
) -> DataFrame:
|
429
|
-
"""
|
430
|
-
Create a pandas.DataFrame from simulation(s).
|
423
|
+
"""Create a pandas.DataFrame from simulation(s).
|
431
424
|
|
432
425
|
Parameters
|
433
426
|
----------
|
openseries/types.py
CHANGED
@@ -11,6 +11,9 @@ from pandas import Timestamp
|
|
11
11
|
from pydantic import BaseModel, Field, StringConstraints, conlist, conset
|
12
12
|
from typing_extensions import Self
|
13
13
|
|
14
|
+
__all__ = ["ValueType"]
|
15
|
+
|
16
|
+
|
14
17
|
CountryStringType = Annotated[
|
15
18
|
str,
|
16
19
|
StringConstraints(
|
@@ -30,7 +33,6 @@ CountriesType = Union[CountryListType, CountryStringType] # type: ignore[valid-
|
|
30
33
|
|
31
34
|
|
32
35
|
class Countries(BaseModel):
|
33
|
-
|
34
36
|
"""Declare Countries."""
|
35
37
|
|
36
38
|
countryinput: CountriesType
|
@@ -50,7 +52,6 @@ CurrencyStringType = Annotated[
|
|
50
52
|
|
51
53
|
|
52
54
|
class Currency(BaseModel):
|
53
|
-
|
54
55
|
"""Declare Currency."""
|
55
56
|
|
56
57
|
ccy: CurrencyStringType
|
@@ -87,31 +88,29 @@ DatabaseIdStringType = Annotated[
|
|
87
88
|
|
88
89
|
DaysInYearType = Annotated[int, Field(strict=True, ge=1, le=366)]
|
89
90
|
|
90
|
-
DateType =
|
91
|
+
DateType = str | dt.date | dt.datetime | datetime64 | Timestamp
|
91
92
|
|
92
|
-
HolidayType =
|
93
|
-
dict[
|
94
|
-
list[
|
95
|
-
dt.date
|
96
|
-
dt.datetime
|
97
|
-
str
|
98
|
-
float
|
99
|
-
int
|
100
|
-
|
93
|
+
HolidayType = (
|
94
|
+
dict[dt.date | dt.datetime | str | float | int, str]
|
95
|
+
| list[dt.date | dt.datetime | str | float | int]
|
96
|
+
| dt.date
|
97
|
+
| dt.datetime
|
98
|
+
| str
|
99
|
+
| float
|
100
|
+
| int
|
101
|
+
)
|
101
102
|
|
102
103
|
PlotlyLayoutType = dict[
|
103
104
|
str,
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
dict[str, Union[str, int, float, bool, list[str]]],
|
111
|
-
],
|
105
|
+
str
|
106
|
+
| int
|
107
|
+
| float
|
108
|
+
| bool
|
109
|
+
| list[str]
|
110
|
+
| dict[str, str | int | float | bool | list[str]],
|
112
111
|
]
|
113
112
|
|
114
|
-
CaptorLogoType = dict[str,
|
113
|
+
CaptorLogoType = dict[str, str | float]
|
115
114
|
|
116
115
|
LiteralJsonOutput = Literal["values", "tsdf"]
|
117
116
|
LiteralTrunc = Literal["before", "after", "both"]
|
@@ -155,6 +154,23 @@ LiteralOlsFitCovType = Literal[
|
|
155
154
|
"cluster",
|
156
155
|
]
|
157
156
|
|
157
|
+
LiteralMinimizeMethods = Literal[
|
158
|
+
"SLSQP",
|
159
|
+
"Nelder-Mead",
|
160
|
+
"Powell",
|
161
|
+
"CG",
|
162
|
+
"BFGS",
|
163
|
+
"Newton-CG",
|
164
|
+
"L-BFGS-B",
|
165
|
+
"TNC",
|
166
|
+
"COBYLA",
|
167
|
+
"trust-constr",
|
168
|
+
"dogleg",
|
169
|
+
"trust-ncg",
|
170
|
+
"trust-exact",
|
171
|
+
"trust-krylov",
|
172
|
+
]
|
173
|
+
|
158
174
|
LiteralSeriesProps = Literal[
|
159
175
|
"value_ret",
|
160
176
|
"geo_ret",
|
@@ -210,7 +226,6 @@ LiteralFrameProps = Literal[
|
|
210
226
|
|
211
227
|
|
212
228
|
class OpenTimeSeriesPropertiesList(list[str]):
|
213
|
-
|
214
229
|
"""Allowed property arguments for the OpenTimeSeries class."""
|
215
230
|
|
216
231
|
allowed_strings: ClassVar[set[str]] = {
|
@@ -267,7 +282,6 @@ class OpenTimeSeriesPropertiesList(list[str]):
|
|
267
282
|
|
268
283
|
|
269
284
|
class OpenFramePropertiesList(list[str]):
|
270
|
-
|
271
285
|
"""Allowed property arguments for the OpenFrame class."""
|
272
286
|
|
273
287
|
allowed_strings: ClassVar[set[str]] = {
|
@@ -319,7 +333,6 @@ class OpenFramePropertiesList(list[str]):
|
|
319
333
|
|
320
334
|
|
321
335
|
class ValueType(str, Enum):
|
322
|
-
|
323
336
|
"""Enum types of OpenTimeSeries to identify the output."""
|
324
337
|
|
325
338
|
EWMA = "EWMA"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# BSD 3-Clause License
|
2
2
|
|
3
|
-
## Copyright (c)
|
3
|
+
## Copyright (c) Captor Fund Management AB
|
4
4
|
|
5
5
|
Redistribution and use in source and binary forms, with or without modification, are
|
6
6
|
permitted provided that the following conditions are met:
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openseries
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7.0
|
4
4
|
Summary: Tools for analyzing financial timeseries.
|
5
5
|
Home-page: https://github.com/CaptorAB/openseries
|
6
6
|
License: BSD-3-Clause
|
7
7
|
Keywords: python,finance,fintech,data-science,timeseries,timeseries-data,timeseries-analysis,investment,investment-analysis,investing
|
8
8
|
Author: Martin Karrin
|
9
9
|
Author-email: martin.karrin@captor.se
|
10
|
-
Requires-Python: >=3.
|
10
|
+
Requires-Python: >=3.10,<3.13
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
12
12
|
Classifier: Framework :: Pydantic
|
13
13
|
Classifier: Intended Audience :: Financial and Insurance Industry
|
@@ -15,7 +15,6 @@ Classifier: License :: OSI Approved :: BSD License
|
|
15
15
|
Classifier: Natural Language :: English
|
16
16
|
Classifier: Operating System :: OS Independent
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
@@ -25,7 +24,7 @@ Requires-Dist: numpy (>=1.23.2,<=3.0.0)
|
|
25
24
|
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
26
25
|
Requires-Dist: pandas (>=2.1.2,<3.0.0)
|
27
26
|
Requires-Dist: plotly (>=5.18.0,<6.0.0)
|
28
|
-
Requires-Dist: pyarrow (>=14.0.2,<
|
27
|
+
Requires-Dist: pyarrow (>=14.0.2,<18.0.0)
|
29
28
|
Requires-Dist: pydantic (>=2.5.2,<3.0.0)
|
30
29
|
Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
|
31
30
|
Requires-Dist: requests (>=2.20.0,<3.0.0)
|
@@ -80,7 +79,7 @@ The code snippet can be pasted into a Python console to run it.
|
|
80
79
|
Install openseries and yfinance first.
|
81
80
|
|
82
81
|
```python
|
83
|
-
from openseries
|
82
|
+
from openseries import OpenTimeSeries
|
84
83
|
import yfinance as yf
|
85
84
|
|
86
85
|
msft=yf.Ticker("MSFT")
|
@@ -0,0 +1,16 @@
|
|
1
|
+
openseries/__init__.py,sha256=k2r-yXfmxqBT7_voQ-4HL5dBxfkQIItsm-o77ot3aDQ,1116
|
2
|
+
openseries/_common_model.py,sha256=smkqaErhDGbcihsqzFeF7tbwstlmlkgcPF2C1KaaGbU,74369
|
3
|
+
openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
|
4
|
+
openseries/datefixer.py,sha256=CFsZfooXIl2q7w8x8O2xRwfmQP67offwbWEaNYpEJGU,12778
|
5
|
+
openseries/frame.py,sha256=6u5UGLSVyaBC3YdB84mF3iBSw70Gwnrk4iBQiNeJppg,55580
|
6
|
+
openseries/load_plotly.py,sha256=Uuk_-iIY4_C6Z5U3rAneOh8ZlGYWbkuis9s4Amxzko4,1921
|
7
|
+
openseries/plotly_captor_logo.json,sha256=F5nhMzEyxKywtjvQqMTKgKRCJQYMDIiBgDSxdte8Clo,178
|
8
|
+
openseries/plotly_layouts.json,sha256=ahx8-dL4_RPzvHtBOX0SiL0AH7xQJzNRSDhGrSmU-Og,1429
|
9
|
+
openseries/portfoliotools.py,sha256=asD8n8m8roEN0SuJK_LoLc5OnTcPmFVl64598dG2sUQ,18749
|
10
|
+
openseries/series.py,sha256=WqDSGOEBFuVQkfdrysXS4PBi2B7HFT-v9f41vt9JaSA,27984
|
11
|
+
openseries/simulation.py,sha256=QpeEC2nsG3DAqd51spAccrYWhUbsFWfCyyCkrjCMd7Y,13860
|
12
|
+
openseries/types.py,sha256=KoqDGI-DOJGP3zPzhx0an7IGIttWG0zYw-VJqolc1xA,7908
|
13
|
+
openseries-1.7.0.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
|
14
|
+
openseries-1.7.0.dist-info/METADATA,sha256=G82OxH9BK1fRJVI45Lr-PNu_hbHKmdo1uKnZZa8JIx0,44166
|
15
|
+
openseries-1.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
16
|
+
openseries-1.7.0.dist-info/RECORD,,
|