openseries 1.7.8__tar.gz → 1.8.0__tar.gz
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-1.7.8 → openseries-1.8.0}/PKG-INFO +17 -19
- {openseries-1.7.8 → openseries-1.8.0}/README.md +4 -8
- {openseries-1.7.8 → openseries-1.8.0}/openseries/__init__.py +1 -1
- {openseries-1.7.8 → openseries-1.8.0}/openseries/_common_model.py +1 -1
- {openseries-1.7.8 → openseries-1.8.0}/openseries/_risk.py +1 -1
- {openseries-1.7.8 → openseries-1.8.0}/openseries/datefixer.py +2 -2
- {openseries-1.7.8 → openseries-1.8.0}/openseries/frame.py +4 -4
- {openseries-1.7.8 → openseries-1.8.0}/openseries/load_plotly.py +1 -1
- openseries-1.7.8/openseries/types.py → openseries-1.8.0/openseries/owntypes.py +1 -1
- {openseries-1.7.8 → openseries-1.8.0}/openseries/portfoliotools.py +11 -8
- {openseries-1.7.8 → openseries-1.8.0}/openseries/series.py +4 -2
- {openseries-1.7.8 → openseries-1.8.0}/openseries/simulation.py +1 -1
- {openseries-1.7.8 → openseries-1.8.0}/pyproject.toml +32 -20
- {openseries-1.7.8 → openseries-1.8.0}/LICENSE.md +0 -0
- {openseries-1.7.8 → openseries-1.8.0}/openseries/plotly_captor_logo.json +0 -0
- {openseries-1.7.8 → openseries-1.8.0}/openseries/plotly_layouts.json +0 -0
@@ -1,36 +1,38 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: openseries
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.8.0
|
4
4
|
Summary: Tools for analyzing financial timeseries.
|
5
|
-
Home-page: https://github.com/CaptorAB/openseries
|
6
5
|
License: BSD-3-Clause
|
7
6
|
Keywords: python,finance,fintech,data-science,timeseries,timeseries-data,timeseries-analysis,investment,investment-analysis,investing
|
8
7
|
Author: Martin Karrin
|
9
8
|
Author-email: martin.karrin@captor.se
|
9
|
+
Maintainer: Martin Karrin
|
10
|
+
Maintainer-email: martin.karrin@captor.se
|
10
11
|
Requires-Python: >=3.10,<3.14
|
11
|
-
Classifier: Development Status :: 5 - Production/Stable
|
12
|
-
Classifier: Framework :: Pydantic
|
13
|
-
Classifier: Intended Audience :: Financial and Insurance Industry
|
14
|
-
Classifier: License :: OSI Approved :: BSD License
|
15
|
-
Classifier: Natural Language :: English
|
16
|
-
Classifier: Operating System :: OS Independent
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
18
12
|
Classifier: Programming Language :: Python :: 3.10
|
19
13
|
Classifier: Programming Language :: Python :: 3.11
|
20
14
|
Classifier: Programming Language :: Python :: 3.12
|
21
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
17
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
22
18
|
Classifier: Topic :: Office/Business :: Financial :: Investment
|
19
|
+
Classifier: Natural Language :: English
|
20
|
+
Classifier: Development Status :: 5 - Production/Stable
|
21
|
+
Classifier: Operating System :: OS Independent
|
22
|
+
Classifier: Framework :: Pydantic
|
23
23
|
Requires-Dist: holidays (>=0.30,<1.0)
|
24
24
|
Requires-Dist: numpy (>=1.23.2,<3.0.0)
|
25
25
|
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
26
26
|
Requires-Dist: pandas (>=2.1.2,<3.0.0)
|
27
27
|
Requires-Dist: plotly (>=5.18.0,<6.0.0)
|
28
|
-
Requires-Dist: pyarrow (>=14.0.2,<
|
28
|
+
Requires-Dist: pyarrow (>=14.0.2,<20.0.0)
|
29
29
|
Requires-Dist: pydantic (>=2.5.2,<3.0.0)
|
30
30
|
Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
|
31
31
|
Requires-Dist: requests (>=2.20.0,<3.0.0)
|
32
32
|
Requires-Dist: scipy (>=1.11.4,<2.0.0)
|
33
33
|
Requires-Dist: statsmodels (>=0.14.0,!=0.14.2,<1.0.0)
|
34
|
+
Project-URL: Documentation, https://github.com/CaptorAB/openseries
|
35
|
+
Project-URL: Homepage, https://github.com/CaptorAB/openseries
|
34
36
|
Project-URL: Repository, https://github.com/CaptorAB/openseries
|
35
37
|
Description-Content-Type: text/markdown
|
36
38
|
|
@@ -43,6 +45,7 @@ Description-Content-Type: text/markdown
|
|
43
45
|
[](https://pypi.org/project/openseries/)
|
44
46
|
[](https://anaconda.org/conda-forge/openseries)
|
45
47
|
[](https://anaconda.org/conda-forge/openseries)
|
48
|
+
[](https://nbviewer.org/github/karrmagadgeteer2/NoteBook/blob/master/openseriesnotebook.ipynb)
|
46
49
|
[](https://www.python.org/)
|
47
50
|
[](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
|
48
51
|
[](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
|
@@ -80,10 +83,10 @@ Install openseries and yfinance first.
|
|
80
83
|
from openseries import OpenTimeSeries
|
81
84
|
import yfinance as yf
|
82
85
|
|
83
|
-
move=yf.Ticker("^MOVE")
|
86
|
+
move=yf.Ticker(ticker="^MOVE")
|
84
87
|
history=move.history(period="max")
|
85
|
-
series=OpenTimeSeries.from_df(history.loc[:, "Close"])
|
86
|
-
_=series.set_new_label("ICE BofAML MOVE Index")
|
88
|
+
series=OpenTimeSeries.from_df(dframe=history.loc[:, "Close"])
|
89
|
+
_=series.set_new_label(lvl_zero="ICE BofAML MOVE Index")
|
87
90
|
_,_=series.plot_series()
|
88
91
|
|
89
92
|
```
|
@@ -117,11 +120,6 @@ first indices 2006-01-03
|
|
117
120
|
last indices 2023-04-05 2023-04-05
|
118
121
|
```
|
119
122
|
|
120
|
-
### Usage example on Jupyter Nbviewer
|
121
|
-
|
122
|
-
[](https://nbviewer.org/github/karrmagadgeteer2/NoteBook/blob/master/openseriesnotebook.ipynb)
|
123
|
-
|
124
|
-
|
125
123
|
## Development Instructions
|
126
124
|
|
127
125
|
These instructions assume that you have a compatible Python version installed on
|
@@ -7,6 +7,7 @@
|
|
7
7
|
[](https://pypi.org/project/openseries/)
|
8
8
|
[](https://anaconda.org/conda-forge/openseries)
|
9
9
|
[](https://anaconda.org/conda-forge/openseries)
|
10
|
+
[](https://nbviewer.org/github/karrmagadgeteer2/NoteBook/blob/master/openseriesnotebook.ipynb)
|
10
11
|
[](https://www.python.org/)
|
11
12
|
[](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
|
12
13
|
[](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
|
@@ -44,10 +45,10 @@ Install openseries and yfinance first.
|
|
44
45
|
from openseries import OpenTimeSeries
|
45
46
|
import yfinance as yf
|
46
47
|
|
47
|
-
move=yf.Ticker("^MOVE")
|
48
|
+
move=yf.Ticker(ticker="^MOVE")
|
48
49
|
history=move.history(period="max")
|
49
|
-
series=OpenTimeSeries.from_df(history.loc[:, "Close"])
|
50
|
-
_=series.set_new_label("ICE BofAML MOVE Index")
|
50
|
+
series=OpenTimeSeries.from_df(dframe=history.loc[:, "Close"])
|
51
|
+
_=series.set_new_label(lvl_zero="ICE BofAML MOVE Index")
|
51
52
|
_,_=series.plot_series()
|
52
53
|
|
53
54
|
```
|
@@ -81,11 +82,6 @@ first indices 2006-01-03
|
|
81
82
|
last indices 2023-04-05 2023-04-05
|
82
83
|
```
|
83
84
|
|
84
|
-
### Usage example on Jupyter Nbviewer
|
85
|
-
|
86
|
-
[](https://nbviewer.org/github/karrmagadgeteer2/NoteBook/blob/master/openseriesnotebook.ipynb)
|
87
|
-
|
88
|
-
|
89
85
|
## Development Instructions
|
90
86
|
|
91
87
|
These instructions assume that you have a compatible Python version installed on
|
@@ -10,6 +10,7 @@ from .datefixer import (
|
|
10
10
|
)
|
11
11
|
from .frame import OpenFrame
|
12
12
|
from .load_plotly import load_plotly_dict
|
13
|
+
from .owntypes import ValueType
|
13
14
|
from .portfoliotools import (
|
14
15
|
constrain_optimized_portfolios,
|
15
16
|
efficient_frontier,
|
@@ -19,7 +20,6 @@ from .portfoliotools import (
|
|
19
20
|
)
|
20
21
|
from .series import OpenTimeSeries, timeseries_chain
|
21
22
|
from .simulation import ReturnSimulation
|
22
|
-
from .types import ValueType
|
23
23
|
|
24
24
|
__all__ = [
|
25
25
|
"OpenFrame",
|
@@ -22,7 +22,7 @@ from pandas import (
|
|
22
22
|
from pandas.tseries.offsets import CustomBusinessDay
|
23
23
|
|
24
24
|
if TYPE_CHECKING:
|
25
|
-
from .
|
25
|
+
from .owntypes import ( # pragma: no cover
|
26
26
|
CountriesType,
|
27
27
|
DateType,
|
28
28
|
HolidayType,
|
@@ -114,7 +114,7 @@ def date_fix(
|
|
114
114
|
|
115
115
|
"""
|
116
116
|
msg = f"Unknown date format {fixerdate!s} of type {type(fixerdate)!s} encountered"
|
117
|
-
if isinstance(fixerdate,
|
117
|
+
if isinstance(fixerdate, Timestamp | dt.datetime):
|
118
118
|
return fixerdate.date()
|
119
119
|
if isinstance(fixerdate, dt.date):
|
120
120
|
return fixerdate
|
@@ -43,8 +43,7 @@ from typing_extensions import Self
|
|
43
43
|
|
44
44
|
from ._common_model import _CommonModel
|
45
45
|
from .datefixer import _do_resample_to_business_period_ends
|
46
|
-
from .
|
47
|
-
from .types import (
|
46
|
+
from .owntypes import (
|
48
47
|
CountriesType,
|
49
48
|
DaysInYearType,
|
50
49
|
LiteralBizDayFreq,
|
@@ -59,6 +58,7 @@ from .types import (
|
|
59
58
|
OpenFramePropertiesList,
|
60
59
|
ValueType,
|
61
60
|
)
|
61
|
+
from .series import OpenTimeSeries
|
62
62
|
|
63
63
|
__all__ = ["OpenFrame"]
|
64
64
|
|
@@ -181,7 +181,7 @@ class OpenFrame(_CommonModel):
|
|
181
181
|
[x.tsdf for x in self.constituents],
|
182
182
|
)
|
183
183
|
|
184
|
-
mapper = dict(zip(self.columns_lvl_zero, lvl_zero))
|
184
|
+
mapper = dict(zip(self.columns_lvl_zero, lvl_zero, strict=True))
|
185
185
|
self.tsdf = self.tsdf.rename(columns=mapper, level=0)
|
186
186
|
|
187
187
|
if self.tsdf.empty:
|
@@ -653,7 +653,7 @@ class OpenFrame(_CommonModel):
|
|
653
653
|
"""
|
654
654
|
if self.weights:
|
655
655
|
new_c, new_w = [], []
|
656
|
-
for serie, weight in zip(self.constituents, self.weights):
|
656
|
+
for serie, weight in zip(self.constituents, self.weights, strict=True):
|
657
657
|
if serie.label != lvl_zero_item:
|
658
658
|
new_c.append(serie)
|
659
659
|
new_w.append(weight)
|
@@ -11,7 +11,7 @@ import requests
|
|
11
11
|
from requests.exceptions import ConnectionError as RequestsConnectionError
|
12
12
|
|
13
13
|
if TYPE_CHECKING:
|
14
|
-
from .
|
14
|
+
from .owntypes import CaptorLogoType, PlotlyLayoutType # pragma: no cover
|
15
15
|
|
16
16
|
__all__ = ["load_plotly_dict"]
|
17
17
|
|
@@ -30,7 +30,7 @@ CountryListType = conset(
|
|
30
30
|
item_type=CountryStringType,
|
31
31
|
min_length=1,
|
32
32
|
)
|
33
|
-
CountriesType = Union[CountryListType, CountryStringType] # type: ignore[valid-type]
|
33
|
+
CountriesType = Union[CountryListType, CountryStringType] # type: ignore[valid-type] # noqa: UP007
|
34
34
|
|
35
35
|
|
36
36
|
class Countries(BaseModel):
|
@@ -3,9 +3,10 @@
|
|
3
3
|
# mypy: disable-error-code="index,assignment"
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
+
from collections.abc import Callable
|
6
7
|
from inspect import stack
|
7
8
|
from pathlib import Path
|
8
|
-
from typing import TYPE_CHECKING,
|
9
|
+
from typing import TYPE_CHECKING, cast
|
9
10
|
|
10
11
|
from numpy import (
|
11
12
|
append,
|
@@ -33,17 +34,17 @@ from plotly.offline import plot # type: ignore[import-untyped,unused-ignore]
|
|
33
34
|
from scipy.optimize import minimize # type: ignore[import-untyped,unused-ignore]
|
34
35
|
|
35
36
|
from .load_plotly import load_plotly_dict
|
36
|
-
from .
|
37
|
-
|
38
|
-
# noinspection PyProtectedMember
|
39
|
-
from .simulation import _random_generator
|
40
|
-
from .types import (
|
37
|
+
from .owntypes import (
|
41
38
|
LiteralLinePlotMode,
|
42
39
|
LiteralMinimizeMethods,
|
43
40
|
LiteralPlotlyJSlib,
|
44
41
|
LiteralPlotlyOutput,
|
45
42
|
ValueType,
|
46
43
|
)
|
44
|
+
from .series import OpenTimeSeries
|
45
|
+
|
46
|
+
# noinspection PyProtectedMember
|
47
|
+
from .simulation import _random_generator
|
47
48
|
|
48
49
|
if TYPE_CHECKING: # pragma: no cover
|
49
50
|
from pydantic import DirectoryPath
|
@@ -415,12 +416,14 @@ def prepare_plot_data(
|
|
415
416
|
for wgt, nm in zip(
|
416
417
|
cast(list[float], assets.weights),
|
417
418
|
assets.columns_lvl_zero,
|
419
|
+
strict=True,
|
418
420
|
)
|
419
421
|
],
|
420
422
|
)
|
421
423
|
|
422
424
|
opt_text_list = [
|
423
|
-
f"{wgt:.1%} {nm}"
|
425
|
+
f"{wgt:.1%} {nm}"
|
426
|
+
for wgt, nm in zip(optimized[3:], assets.columns_lvl_zero, strict=True)
|
424
427
|
]
|
425
428
|
opt_text = "<br><br>Weights:<br>" + "<br>".join(opt_text_list)
|
426
429
|
vol: Series[float] = assets.vol
|
@@ -552,7 +555,7 @@ def sharpeplot( # noqa: C901
|
|
552
555
|
dict[str, str | int | float | bool | list[str]],
|
553
556
|
fig["layout"],
|
554
557
|
).get("colorway")[: len(point_frame.columns)]
|
555
|
-
for col, clr in zip(point_frame.columns, colorway):
|
558
|
+
for col, clr in zip(point_frame.columns, colorway, strict=True):
|
556
559
|
returns.extend([point_frame.loc["ret", col]])
|
557
560
|
risk.extend([point_frame.loc["stdev", col]])
|
558
561
|
figure.add_scatter(
|
@@ -31,7 +31,7 @@ from typing_extensions import Self
|
|
31
31
|
|
32
32
|
from ._common_model import _CommonModel
|
33
33
|
from .datefixer import _do_resample_to_business_period_ends, date_fix
|
34
|
-
from .
|
34
|
+
from .owntypes import (
|
35
35
|
Countries,
|
36
36
|
CountriesType,
|
37
37
|
Currency,
|
@@ -513,7 +513,9 @@ class OpenTimeSeries(_CommonModel):
|
|
513
513
|
|
514
514
|
deltas = array([i.days for i in self.tsdf.index[1:] - self.tsdf.index[:-1]])
|
515
515
|
# noinspection PyTypeChecker
|
516
|
-
arr = cumprod(
|
516
|
+
arr = cumprod( # type: ignore[assignment,unused-ignore]
|
517
|
+
a=insert(arr=1.0 + deltas * arr[:-1] / days_in_year, obj=0, values=1.0)
|
518
|
+
)
|
517
519
|
|
518
520
|
self.dates = [d.strftime("%Y-%m-%d") for d in self.tsdf.index]
|
519
521
|
self.values = list(arr)
|
@@ -1,11 +1,17 @@
|
|
1
|
-
[
|
1
|
+
[project]
|
2
2
|
name = "openseries"
|
3
|
-
version = "1.
|
3
|
+
version = "1.8.0"
|
4
4
|
description = "Tools for analyzing financial timeseries."
|
5
|
-
authors = [
|
6
|
-
|
5
|
+
authors = [
|
6
|
+
{ name = "Martin Karrin", email = "martin.karrin@captor.se" },
|
7
|
+
]
|
8
|
+
maintainers = [
|
9
|
+
{ name = "Martin Karrin", email = "martin.karrin@captor.se" },
|
10
|
+
]
|
7
11
|
license = "BSD-3-Clause"
|
8
12
|
readme = "README.md"
|
13
|
+
requires-python = ">=3.10,<3.14"
|
14
|
+
|
9
15
|
classifiers = [
|
10
16
|
"Programming Language :: Python :: 3.10",
|
11
17
|
"Programming Language :: Python :: 3.11",
|
@@ -19,6 +25,7 @@ classifiers = [
|
|
19
25
|
"Operating System :: OS Independent",
|
20
26
|
"Framework :: Pydantic",
|
21
27
|
]
|
28
|
+
|
22
29
|
keywords = [
|
23
30
|
"python",
|
24
31
|
"finance",
|
@@ -32,35 +39,40 @@ keywords = [
|
|
32
39
|
"investing"
|
33
40
|
]
|
34
41
|
|
35
|
-
[
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
dependencies = [
|
43
|
+
"holidays (>=0.30,<1.0)",
|
44
|
+
"numpy (>=1.23.2,<3.0.0)",
|
45
|
+
"openpyxl (>=3.1.2,<4.0.0)",
|
46
|
+
"pandas (>=2.1.2,<3.0.0)",
|
47
|
+
"plotly (>=5.18.0,<6.0.0)",
|
48
|
+
"pyarrow (>=14.0.2,<20.0.0)",
|
49
|
+
"pydantic (>=2.5.2,<3.0.0)",
|
50
|
+
"python-dateutil (>=2.8.2,<3.0.0)",
|
51
|
+
"requests (>=2.20.0,<3.0.0)",
|
52
|
+
"scipy (>=1.11.4,<2.0.0)",
|
53
|
+
"statsmodels (>=0.14.0,!=0.14.2,<1.0.0)"
|
54
|
+
]
|
55
|
+
|
56
|
+
[project.urls]
|
57
|
+
homepage = "https://github.com/CaptorAB/openseries"
|
58
|
+
repository = "https://github.com/CaptorAB/openseries"
|
59
|
+
documentation = "https://github.com/CaptorAB/openseries"
|
48
60
|
|
49
61
|
[tool.poetry.group.dev.dependencies]
|
50
62
|
black = ">=24.4.2,<25.0.0"
|
51
63
|
coverage = ">=7.2.7,<9.0.0"
|
52
|
-
genbadge = {version = ">=1.1.1,<2.0.0", extras = ["coverage"]}
|
64
|
+
genbadge = { version = ">=1.1.1,<2.0.0", extras = ["coverage"] }
|
53
65
|
mypy = "1.14.1"
|
54
66
|
pandas-stubs = ">=2.1.2,<3.0.0"
|
55
67
|
pre-commit = ">=3.7.1,<6.0.0"
|
56
68
|
pytest = ">=8.2.2,<9.0.0"
|
57
|
-
ruff = "0.
|
69
|
+
ruff = "0.9.3"
|
58
70
|
types-openpyxl = ">=3.1.2,<4.0.0"
|
59
71
|
types-python-dateutil = ">=2.8.2,<3.0.0"
|
60
72
|
types-requests = ">=2.20.0,<3.0.0"
|
61
73
|
|
62
74
|
[build-system]
|
63
|
-
requires = ["poetry-core>=
|
75
|
+
requires = ["poetry-core>=2.0.1"]
|
64
76
|
build-backend = "poetry.core.masonry.api"
|
65
77
|
|
66
78
|
[tool.coverage.run]
|
File without changes
|
File without changes
|
File without changes
|