openseries 1.6.0__py3-none-any.whl → 1.7.1__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 +0 -2
- openseries/_common_model.py +261 -324
- openseries/_risk.py +9 -10
- openseries/datefixer.py +42 -63
- openseries/frame.py +125 -161
- openseries/load_plotly.py +8 -8
- openseries/portfoliotools.py +39 -35
- openseries/series.py +65 -93
- openseries/simulation.py +39 -50
- openseries/types.py +17 -24
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/LICENSE.md +1 -1
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/METADATA +4 -5
- openseries-1.7.1.dist-info/RECORD +16 -0
- openseries-1.6.0.dist-info/RECORD +0 -16
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/WHEEL +0 -0
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,8 +24,8 @@ 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,
|
@@ -32,9 +34,8 @@ from openseries.types import (
|
|
32
34
|
__all__ = ["ReturnSimulation"]
|
33
35
|
|
34
36
|
|
35
|
-
def _random_generator(seed:
|
36
|
-
"""
|
37
|
-
Make a Numpy Random Generator object.
|
37
|
+
def _random_generator(seed: int | None) -> Generator:
|
38
|
+
"""Make a Numpy Random Generator object.
|
38
39
|
|
39
40
|
Parameters
|
40
41
|
----------
|
@@ -48,14 +49,12 @@ def _random_generator(seed: Optional[int]) -> Generator:
|
|
48
49
|
|
49
50
|
"""
|
50
51
|
ss = SeedSequence(entropy=seed)
|
51
|
-
bg = PCG64(seed=cast(
|
52
|
+
bg = PCG64(seed=cast(int | None, ss))
|
52
53
|
return Generator(bit_generator=bg)
|
53
54
|
|
54
55
|
|
55
56
|
class ReturnSimulation(BaseModel):
|
56
|
-
|
57
|
-
"""
|
58
|
-
The class ReturnSimulation allows for simulating financial timeseries.
|
57
|
+
"""The class ReturnSimulation allows for simulating financial timeseries.
|
59
58
|
|
60
59
|
Parameters
|
61
60
|
----------
|
@@ -91,7 +90,7 @@ class ReturnSimulation(BaseModel):
|
|
91
90
|
jumps_lamda: NonNegativeFloat = 0.0
|
92
91
|
jumps_sigma: NonNegativeFloat = 0.0
|
93
92
|
jumps_mu: float = 0.0
|
94
|
-
seed:
|
93
|
+
seed: int | None = None
|
95
94
|
|
96
95
|
model_config = ConfigDict(
|
97
96
|
arbitrary_types_allowed=True,
|
@@ -101,8 +100,7 @@ class ReturnSimulation(BaseModel):
|
|
101
100
|
|
102
101
|
@property
|
103
102
|
def results(self: Self) -> DataFrame:
|
104
|
-
"""
|
105
|
-
Simulation data.
|
103
|
+
"""Simulation data.
|
106
104
|
|
107
105
|
Returns
|
108
106
|
-------
|
@@ -114,8 +112,7 @@ class ReturnSimulation(BaseModel):
|
|
114
112
|
|
115
113
|
@property
|
116
114
|
def realized_mean_return(self: Self) -> float:
|
117
|
-
"""
|
118
|
-
Annualized arithmetic mean of returns.
|
115
|
+
"""Annualized arithmetic mean of returns.
|
119
116
|
|
120
117
|
Returns
|
121
118
|
-------
|
@@ -133,8 +130,7 @@ class ReturnSimulation(BaseModel):
|
|
133
130
|
|
134
131
|
@property
|
135
132
|
def realized_vol(self: Self) -> float:
|
136
|
-
"""
|
137
|
-
Annualized volatility.
|
133
|
+
"""Annualized volatility.
|
138
134
|
|
139
135
|
Returns
|
140
136
|
-------
|
@@ -157,12 +153,11 @@ class ReturnSimulation(BaseModel):
|
|
157
153
|
mean_annual_return: float,
|
158
154
|
mean_annual_vol: PositiveFloat,
|
159
155
|
trading_days: PositiveInt,
|
160
|
-
seed: int,
|
161
156
|
trading_days_in_year: DaysInYearType = 252,
|
162
|
-
|
157
|
+
seed: int | None = None,
|
158
|
+
randomizer: Generator | None = None,
|
163
159
|
) -> ReturnSimulation:
|
164
|
-
"""
|
165
|
-
Create a Normal distribution simulation.
|
160
|
+
"""Create a Normal distribution simulation.
|
166
161
|
|
167
162
|
Parameters
|
168
163
|
----------
|
@@ -174,11 +169,10 @@ class ReturnSimulation(BaseModel):
|
|
174
169
|
Mean return
|
175
170
|
mean_annual_vol: PositiveFloat
|
176
171
|
Mean standard deviation
|
177
|
-
|
178
|
-
Seed for random process initiation
|
179
|
-
trading_days_in_year: DaysInYearType,
|
180
|
-
default: 252
|
172
|
+
trading_days_in_year: DaysInYearType, default: 252
|
181
173
|
Number of trading days used to annualize
|
174
|
+
seed: int, optional
|
175
|
+
Seed for random process initiation
|
182
176
|
randomizer: numpy.random.Generator, optional
|
183
177
|
Random process generator
|
184
178
|
|
@@ -214,12 +208,11 @@ class ReturnSimulation(BaseModel):
|
|
214
208
|
mean_annual_return: float,
|
215
209
|
mean_annual_vol: PositiveFloat,
|
216
210
|
trading_days: PositiveInt,
|
217
|
-
seed: int,
|
218
211
|
trading_days_in_year: DaysInYearType = 252,
|
219
|
-
|
212
|
+
seed: int | None = None,
|
213
|
+
randomizer: Generator | None = None,
|
220
214
|
) -> ReturnSimulation:
|
221
|
-
"""
|
222
|
-
Create a Lognormal distribution simulation.
|
215
|
+
"""Create a Lognormal distribution simulation.
|
223
216
|
|
224
217
|
Parameters
|
225
218
|
----------
|
@@ -231,11 +224,10 @@ class ReturnSimulation(BaseModel):
|
|
231
224
|
Mean return
|
232
225
|
mean_annual_vol: PositiveFloat
|
233
226
|
Mean standard deviation
|
234
|
-
|
235
|
-
Seed for random process initiation
|
236
|
-
trading_days_in_year: DaysInYearType,
|
237
|
-
default: 252
|
227
|
+
trading_days_in_year: DaysInYearType, default: 252
|
238
228
|
Number of trading days used to annualize
|
229
|
+
seed: int, optional
|
230
|
+
Seed for random process initiation
|
239
231
|
randomizer: numpy.random.Generator, optional
|
240
232
|
Random process generator
|
241
233
|
|
@@ -274,12 +266,11 @@ class ReturnSimulation(BaseModel):
|
|
274
266
|
mean_annual_return: float,
|
275
267
|
mean_annual_vol: PositiveFloat,
|
276
268
|
trading_days: PositiveInt,
|
277
|
-
seed: int,
|
278
269
|
trading_days_in_year: DaysInYearType = 252,
|
279
|
-
|
270
|
+
seed: int | None = None,
|
271
|
+
randomizer: Generator | None = None,
|
280
272
|
) -> ReturnSimulation:
|
281
|
-
"""
|
282
|
-
Create a Geometric Brownian Motion simulation.
|
273
|
+
"""Create a Geometric Brownian Motion simulation.
|
283
274
|
|
284
275
|
Parameters
|
285
276
|
----------
|
@@ -291,10 +282,10 @@ class ReturnSimulation(BaseModel):
|
|
291
282
|
Mean return
|
292
283
|
mean_annual_vol: PositiveFloat
|
293
284
|
Mean standard deviation
|
294
|
-
seed: int
|
295
|
-
Seed for random process initiation
|
296
285
|
trading_days_in_year: DaysInYearType, default: 252
|
297
286
|
Number of trading days used to annualize
|
287
|
+
seed: int, optional
|
288
|
+
Seed for random process initiation
|
298
289
|
randomizer: numpy.random.Generator, optional
|
299
290
|
Random process generator
|
300
291
|
|
@@ -337,15 +328,14 @@ class ReturnSimulation(BaseModel):
|
|
337
328
|
trading_days: PositiveInt,
|
338
329
|
mean_annual_return: float,
|
339
330
|
mean_annual_vol: PositiveFloat,
|
340
|
-
seed: int,
|
341
331
|
jumps_lamda: NonNegativeFloat,
|
342
332
|
jumps_sigma: NonNegativeFloat = 0.0,
|
343
333
|
jumps_mu: float = 0.0,
|
344
334
|
trading_days_in_year: DaysInYearType = 252,
|
345
|
-
|
335
|
+
seed: int | None = None,
|
336
|
+
randomizer: Generator | None = None,
|
346
337
|
) -> ReturnSimulation:
|
347
|
-
"""
|
348
|
-
Create a Merton Jump-Diffusion model simulation.
|
338
|
+
"""Create a Merton Jump-Diffusion model simulation.
|
349
339
|
|
350
340
|
Parameters
|
351
341
|
----------
|
@@ -357,8 +347,6 @@ class ReturnSimulation(BaseModel):
|
|
357
347
|
Mean return
|
358
348
|
mean_annual_vol: PositiveFloat
|
359
349
|
Mean standard deviation
|
360
|
-
seed: int
|
361
|
-
Seed for random process initiation
|
362
350
|
jumps_lamda: NonNegativeFloat
|
363
351
|
This is the probability of a jump happening at each point in time
|
364
352
|
jumps_sigma: NonNegativeFloat, default: 0.0
|
@@ -367,6 +355,8 @@ class ReturnSimulation(BaseModel):
|
|
367
355
|
This is the average jump size
|
368
356
|
trading_days_in_year: DaysInYearType, default: 252
|
369
357
|
Number of trading days used to annualize
|
358
|
+
seed: int, optional
|
359
|
+
Seed for random process initiation
|
370
360
|
randomizer: numpy.random.Generator, optional
|
371
361
|
Random process generator
|
372
362
|
|
@@ -424,12 +414,11 @@ class ReturnSimulation(BaseModel):
|
|
424
414
|
def to_dataframe(
|
425
415
|
self: Self,
|
426
416
|
name: str,
|
427
|
-
start:
|
428
|
-
end:
|
417
|
+
start: dt.date | None = None,
|
418
|
+
end: dt.date | None = None,
|
429
419
|
countries: CountriesType = "SE",
|
430
420
|
) -> DataFrame:
|
431
|
-
"""
|
432
|
-
Create a pandas.DataFrame from simulation(s).
|
421
|
+
"""Create a pandas.DataFrame from simulation(s).
|
433
422
|
|
434
423
|
Parameters
|
435
424
|
----------
|
openseries/types.py
CHANGED
@@ -33,7 +33,6 @@ CountriesType = Union[CountryListType, CountryStringType] # type: ignore[valid-
|
|
33
33
|
|
34
34
|
|
35
35
|
class Countries(BaseModel):
|
36
|
-
|
37
36
|
"""Declare Countries."""
|
38
37
|
|
39
38
|
countryinput: CountriesType
|
@@ -53,7 +52,6 @@ CurrencyStringType = Annotated[
|
|
53
52
|
|
54
53
|
|
55
54
|
class Currency(BaseModel):
|
56
|
-
|
57
55
|
"""Declare Currency."""
|
58
56
|
|
59
57
|
ccy: CurrencyStringType
|
@@ -90,31 +88,29 @@ DatabaseIdStringType = Annotated[
|
|
90
88
|
|
91
89
|
DaysInYearType = Annotated[int, Field(strict=True, ge=1, le=366)]
|
92
90
|
|
93
|
-
DateType =
|
91
|
+
DateType = str | dt.date | dt.datetime | datetime64 | Timestamp
|
94
92
|
|
95
|
-
HolidayType =
|
96
|
-
dict[
|
97
|
-
list[
|
98
|
-
dt.date
|
99
|
-
dt.datetime
|
100
|
-
str
|
101
|
-
float
|
102
|
-
int
|
103
|
-
|
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
|
+
)
|
104
102
|
|
105
103
|
PlotlyLayoutType = dict[
|
106
104
|
str,
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
dict[str, Union[str, int, float, bool, list[str]]],
|
114
|
-
],
|
105
|
+
str
|
106
|
+
| int
|
107
|
+
| float
|
108
|
+
| bool
|
109
|
+
| list[str]
|
110
|
+
| dict[str, str | int | float | bool | list[str]],
|
115
111
|
]
|
116
112
|
|
117
|
-
CaptorLogoType = dict[str,
|
113
|
+
CaptorLogoType = dict[str, str | float]
|
118
114
|
|
119
115
|
LiteralJsonOutput = Literal["values", "tsdf"]
|
120
116
|
LiteralTrunc = Literal["before", "after", "both"]
|
@@ -230,7 +226,6 @@ LiteralFrameProps = Literal[
|
|
230
226
|
|
231
227
|
|
232
228
|
class OpenTimeSeriesPropertiesList(list[str]):
|
233
|
-
|
234
229
|
"""Allowed property arguments for the OpenTimeSeries class."""
|
235
230
|
|
236
231
|
allowed_strings: ClassVar[set[str]] = {
|
@@ -287,7 +282,6 @@ class OpenTimeSeriesPropertiesList(list[str]):
|
|
287
282
|
|
288
283
|
|
289
284
|
class OpenFramePropertiesList(list[str]):
|
290
|
-
|
291
285
|
"""Allowed property arguments for the OpenFrame class."""
|
292
286
|
|
293
287
|
allowed_strings: ClassVar[set[str]] = {
|
@@ -339,7 +333,6 @@ class OpenFramePropertiesList(list[str]):
|
|
339
333
|
|
340
334
|
|
341
335
|
class ValueType(str, Enum):
|
342
|
-
|
343
336
|
"""Enum types of OpenTimeSeries to identify the output."""
|
344
337
|
|
345
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.1
|
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=gD2dMKRTJ9HMXLca_5sR67xGiU5sWExwaNUi-9N_RGQ,1032
|
2
|
+
openseries/_common_model.py,sha256=qa0MejnuLcLszaeF9IGbrRycv94O3Xf1rBnAjASI-M4,73805
|
3
|
+
openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
|
4
|
+
openseries/datefixer.py,sha256=Gj9r8xXGm0jcWiDlC0IR0mN64vceaZAnXrei-sXcuqE,12345
|
5
|
+
openseries/frame.py,sha256=rl0MNUWrQMffS1beNQWzyLHwuLO9AL_9DI_chUoQweA,55466
|
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=0H3IKq3kA2nol-NJcbytIflC3cVMde7xWWzh4ebQkyM,18961
|
10
|
+
openseries/series.py,sha256=Jn_2NEYGUGrdWhP-Nm3LBA041FzFClqTvmWg6eHhG7E,27882
|
11
|
+
openseries/simulation.py,sha256=P5nkX7o3O_3pOL22MAZTqL_i4TB2IUmPGCodegsAM04,13932
|
12
|
+
openseries/types.py,sha256=KoqDGI-DOJGP3zPzhx0an7IGIttWG0zYw-VJqolc1xA,7908
|
13
|
+
openseries-1.7.1.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
|
14
|
+
openseries-1.7.1.dist-info/METADATA,sha256=sDuycWQUg_jmcAv9LY4uTuZp97rnSIjgfg0gz9Epnis,44166
|
15
|
+
openseries-1.7.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
16
|
+
openseries-1.7.1.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
openseries/__init__.py,sha256=k2r-yXfmxqBT7_voQ-4HL5dBxfkQIItsm-o77ot3aDQ,1116
|
2
|
-
openseries/_common_model.py,sha256=qDrEjLLz7FmXbfMl07eocz7i892JdighGpigWCFBpmo,75623
|
3
|
-
openseries/_risk.py,sha256=etureOLszoEgD48NEOZkx24gaK8I-PfjRXV4Ymjkh7w,2072
|
4
|
-
openseries/datefixer.py,sha256=rNHH5yT8gV9iHgd_TCiVuwTMNB5TcxeqSsvIAq36dXU,12717
|
5
|
-
openseries/frame.py,sha256=w6eZgfPx9gRnmUj_i0--KdurBoy5p18B7k0kpGwSoTM,56440
|
6
|
-
openseries/load_plotly.py,sha256=GLsYrbRYEC3HcKHb7vwZIrlRl3ZjnRhSXoMGJsO8weA,1888
|
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=r6Y1ZRuTV4nsRL4s7WEJfv1u6__6kkc3d5Rb-MhQn2k,18807
|
10
|
-
openseries/series.py,sha256=gZCASMtN6Drw7CcmRTNtKBT66YCsnP7Ei7Jhdytp-oE,28236
|
11
|
-
openseries/simulation.py,sha256=LlssueX0tXHvnEZqiubkfsluOkdd9oQE57RbHZDD7_k,13942
|
12
|
-
openseries/types.py,sha256=hIEPm-5BFs_ZIXoMw2DWnbJWe2xFmWDYkSQsEYlLEEA,7968
|
13
|
-
openseries-1.6.0.dist-info/LICENSE.md,sha256=cPUabMxJ6-ziqzqS6aLGkR-ilIOKe_s3Qtyp0ioTmo0,1521
|
14
|
-
openseries-1.6.0.dist-info/METADATA,sha256=wD4JNrn68QfVpJtZRm7y8BgN7c6jykxMWUmOhHJVH1M,44222
|
15
|
-
openseries-1.6.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
16
|
-
openseries-1.6.0.dist-info/RECORD,,
|
File without changes
|