openseries 1.0.0__py3-none-any.whl → 1.1.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/frame.py +5 -8
- openseries/series.py +48 -51
- openseries/sim_price.py +2 -7
- openseries/types.py +20 -5
- {openseries-1.0.0.dist-info → openseries-1.1.0.dist-info}/METADATA +25 -20
- {openseries-1.0.0.dist-info → openseries-1.1.0.dist-info}/RECORD +8 -8
- {openseries-1.0.0.dist-info → openseries-1.1.0.dist-info}/LICENSE.md +0 -0
- {openseries-1.0.0.dist-info → openseries-1.1.0.dist-info}/WHEEL +0 -0
openseries/frame.py
CHANGED
@@ -29,7 +29,8 @@ from pandas import (
|
|
29
29
|
from pandas.tseries.offsets import CustomBusinessDay
|
30
30
|
from plotly.graph_objs import Figure
|
31
31
|
from plotly.offline import plot
|
32
|
-
from pydantic import
|
32
|
+
from pydantic import field_validator, ConfigDict, BaseModel
|
33
|
+
|
33
34
|
from scipy.stats import kurtosis, norm, skew
|
34
35
|
import statsmodels.api as sm
|
35
36
|
|
@@ -85,15 +86,11 @@ class OpenFrame(BaseModel):
|
|
85
86
|
|
86
87
|
constituents: List[OpenTimeSeries]
|
87
88
|
tsdf: DataFrame = DataFrame()
|
88
|
-
weights: None | List[float]
|
89
|
-
|
90
|
-
class Config:
|
91
|
-
"""Configurations for the OpenFrame class"""
|
89
|
+
weights: None | List[float] = None
|
92
90
|
|
93
|
-
|
94
|
-
validate_assignment = True
|
91
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)
|
95
92
|
|
96
|
-
@
|
93
|
+
@field_validator("constituents")
|
97
94
|
def check_labels_unique(
|
98
95
|
cls, tseries: List[OpenTimeSeries]
|
99
96
|
) -> List[OpenTimeSeries]:
|
openseries/series.py
CHANGED
@@ -9,7 +9,7 @@ from math import ceil
|
|
9
9
|
from os import path
|
10
10
|
from pathlib import Path
|
11
11
|
from re import compile as re_compile
|
12
|
-
from typing import Any, cast, Dict, List, Tuple, TypeVar, Union
|
12
|
+
from typing import Any, cast, Dict, List, Optional, Tuple, TypeVar, Union
|
13
13
|
from numpy import (
|
14
14
|
array,
|
15
15
|
cumprod,
|
@@ -35,7 +35,7 @@ from pandas import (
|
|
35
35
|
from pandas.tseries.offsets import CustomBusinessDay
|
36
36
|
from plotly.graph_objs import Figure
|
37
37
|
from plotly.offline import plot
|
38
|
-
from pydantic import BaseModel,
|
38
|
+
from pydantic import BaseModel, conlist, field_validator, model_validator
|
39
39
|
from scipy.stats import kurtosis, norm, skew
|
40
40
|
from stdnum import isin as isincode
|
41
41
|
from stdnum.exceptions import InvalidChecksum
|
@@ -43,10 +43,10 @@ from stdnum.exceptions import InvalidChecksum
|
|
43
43
|
from openseries.datefixer import date_offset_foll, date_fix, holiday_calendar
|
44
44
|
from openseries.load_plotly import load_plotly_dict
|
45
45
|
from openseries.types import (
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
CountryStringType,
|
47
|
+
CurrencyStringType,
|
48
|
+
DatabaseIdStringType,
|
49
|
+
DateListType,
|
50
50
|
LiteralQuantileInterp,
|
51
51
|
LiteralBizDayFreq,
|
52
52
|
LiteralPandasResampleConvention,
|
@@ -130,8 +130,13 @@ class ValueType(str, Enum):
|
|
130
130
|
ROLLVOL = "Rolling volatility"
|
131
131
|
|
132
132
|
|
133
|
-
|
134
|
-
|
133
|
+
class OpenTimeSeries(
|
134
|
+
BaseModel,
|
135
|
+
arbitrary_types_allowed=True,
|
136
|
+
validate_assignment=True,
|
137
|
+
revalidate_instances="always",
|
138
|
+
extra="allow",
|
139
|
+
):
|
135
140
|
"""Object of the class OpenTimeSeries. Subclass of the Pydantic BaseModel
|
136
141
|
|
137
142
|
Parameters
|
@@ -140,23 +145,13 @@ class OpenTimeSeries(BaseModel):
|
|
140
145
|
Database identifier of the timeseries
|
141
146
|
instrumentId: str
|
142
147
|
Database identifier of the instrument associated with the timeseries
|
143
|
-
currency : str
|
144
|
-
ISO 4217 currency code of the timeseries
|
145
|
-
dates : List[str]
|
146
|
-
Dates of the individual timeseries items
|
147
|
-
These dates will not be altered by methods
|
148
|
-
domestic : str
|
149
|
-
ISO 4217 currency code of the user's home currency
|
150
148
|
name : str
|
151
149
|
string identifier of the timeseries and/or instrument
|
152
|
-
isin : str
|
153
|
-
ISO 6166 identifier code of the associated instrument
|
154
|
-
label : str
|
155
|
-
Placeholder for a name of the timeseries
|
156
|
-
countries: list | str, default: "SE"
|
157
|
-
(List of) country code(s) according to ISO 3166-1 alpha-2
|
158
150
|
valuetype : ValueType
|
159
151
|
Identifies if the series is a series of values or returns
|
152
|
+
dates : List[str]
|
153
|
+
Dates of the individual timeseries items
|
154
|
+
These dates will not be altered by methods
|
160
155
|
values : List[float]
|
161
156
|
The value or return values of the timeseries items
|
162
157
|
These values will not be altered by methods
|
@@ -164,41 +159,34 @@ class OpenTimeSeries(BaseModel):
|
|
164
159
|
Boolean flag indicating if timeseries is in local currency
|
165
160
|
tsdf: pandas.DataFrame
|
166
161
|
Pandas object holding dates and values that can be altered via methods
|
162
|
+
currency : str
|
163
|
+
ISO 4217 currency code of the timeseries
|
164
|
+
domestic : str, default: "SEK"
|
165
|
+
ISO 4217 currency code of the user's home currency
|
166
|
+
countries: str, default: "SE"
|
167
|
+
(List of) country code(s) according to ISO 3166-1 alpha-2
|
168
|
+
isin : str, optional
|
169
|
+
ISO 6166 identifier code of the associated instrument
|
170
|
+
label : str, optional
|
171
|
+
Placeholder for a name of the timeseries
|
167
172
|
"""
|
168
173
|
|
169
|
-
timeseriesId:
|
170
|
-
instrumentId:
|
171
|
-
currency: constr(regex=CURRENCYPATTERN, to_upper=True, min_length=3, max_length=3)
|
172
|
-
dates: conlist(
|
173
|
-
item_type=constr(regex=DATEPATTERN),
|
174
|
-
min_items=1,
|
175
|
-
unique_items=True,
|
176
|
-
)
|
177
|
-
domestic: constr(
|
178
|
-
regex=CURRENCYPATTERN, to_upper=True, min_length=3, max_length=3
|
179
|
-
) = "SEK"
|
174
|
+
timeseriesId: DatabaseIdStringType
|
175
|
+
instrumentId: DatabaseIdStringType
|
180
176
|
name: str
|
181
|
-
isin: str | None = None
|
182
|
-
label: str | None = None
|
183
|
-
countries: conlist(
|
184
|
-
item_type=constr(
|
185
|
-
regex=COUNTRYPATTERN, to_upper=True, min_length=2, max_length=2
|
186
|
-
),
|
187
|
-
min_items=1,
|
188
|
-
unique_items=True,
|
189
|
-
) | constr(regex=COUNTRYPATTERN, to_upper=True, min_length=2, max_length=2) = "SE"
|
190
177
|
valuetype: ValueType
|
191
|
-
|
178
|
+
dates: DateListType
|
179
|
+
values: conlist(float, min_length=2)
|
192
180
|
local_ccy: bool
|
193
181
|
tsdf: DataFrame
|
182
|
+
currency: CurrencyStringType
|
183
|
+
domestic: CurrencyStringType = "SEK"
|
184
|
+
countries: CountryStringType = "SE"
|
185
|
+
isin: Optional[str] = None
|
186
|
+
label: Optional[str] = None
|
194
187
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
arbitrary_types_allowed = True
|
199
|
-
validate_assignment = True
|
200
|
-
|
201
|
-
@validator("isin")
|
188
|
+
@field_validator("isin")
|
189
|
+
@classmethod
|
202
190
|
def check_isincode(cls, isin_code: str) -> str:
|
203
191
|
"""Pydantic validator to ensure that the ISIN code is valid if provided"""
|
204
192
|
if isin_code:
|
@@ -210,6 +198,15 @@ class OpenTimeSeries(BaseModel):
|
|
210
198
|
) from exc
|
211
199
|
return isin_code
|
212
200
|
|
201
|
+
@model_validator(mode="after")
|
202
|
+
def check_dates_unique(self) -> "OpenTimeSeries":
|
203
|
+
"""Pydantic validator to ensure that the dates are unique"""
|
204
|
+
dates_list_length = len(self.dates)
|
205
|
+
dates_set_length = len(set(self.dates))
|
206
|
+
if dates_list_length != dates_set_length:
|
207
|
+
raise ValueError("Dates are not unique")
|
208
|
+
return self
|
209
|
+
|
213
210
|
@classmethod
|
214
211
|
def setup_class(
|
215
212
|
cls, domestic_ccy: str = "SEK", countries: List[str] | str = "SE"
|
@@ -223,8 +220,8 @@ class OpenTimeSeries(BaseModel):
|
|
223
220
|
countries: List[str] | str, default: "SE"
|
224
221
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
225
222
|
"""
|
226
|
-
ccy_pattern = re_compile(
|
227
|
-
ctry_pattern = re_compile(
|
223
|
+
ccy_pattern = re_compile(r"^[A-Z]{3}$")
|
224
|
+
ctry_pattern = re_compile(r"^[A-Z]{2}$")
|
228
225
|
try:
|
229
226
|
ccy_ok = ccy_pattern.match(domestic_ccy)
|
230
227
|
except TypeError as exc:
|
openseries/sim_price.py
CHANGED
@@ -5,7 +5,7 @@ stochastic processes generated using the stoch_process.py module.
|
|
5
5
|
from typing import cast
|
6
6
|
from numpy import insert, random, sqrt
|
7
7
|
from pandas import DataFrame
|
8
|
-
from pydantic import BaseModel
|
8
|
+
from pydantic import ConfigDict, BaseModel
|
9
9
|
|
10
10
|
from openseries.stoch_processes import (
|
11
11
|
ModelParameters,
|
@@ -40,12 +40,7 @@ class ReturnSimulation(BaseModel):
|
|
40
40
|
mean_annual_return: float
|
41
41
|
mean_annual_vol: float
|
42
42
|
dframe: DataFrame
|
43
|
-
|
44
|
-
class Config:
|
45
|
-
"""Configurations for the ReturnSimulation class"""
|
46
|
-
|
47
|
-
arbitrary_types_allowed = True
|
48
|
-
validate_assignment = True
|
43
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)
|
49
44
|
|
50
45
|
@property
|
51
46
|
def results(self: "ReturnSimulation") -> DataFrame:
|
openseries/types.py
CHANGED
@@ -2,12 +2,27 @@
|
|
2
2
|
Declaring types used throughout the project
|
3
3
|
"""
|
4
4
|
from typing import Literal, List
|
5
|
-
from pydantic import BaseModel
|
5
|
+
from pydantic import BaseModel, conlist, constr
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
|
8
|
+
CountryStringType = conlist(
|
9
|
+
constr(
|
10
|
+
pattern=r"^[A-Z]{2}$", to_upper=True, min_length=2, max_length=2, strict=True
|
11
|
+
),
|
12
|
+
min_length=1,
|
13
|
+
) | constr(
|
14
|
+
pattern=r"^[A-Z]{2}$", to_upper=True, min_length=2, max_length=2, strict=True
|
15
|
+
)
|
16
|
+
|
17
|
+
CurrencyStringType = constr(
|
18
|
+
pattern=r"^[A-Z]{3}$", to_upper=True, min_length=3, max_length=3, strict=True
|
19
|
+
)
|
20
|
+
|
21
|
+
DateListType = conlist(
|
22
|
+
constr(pattern=r"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$"), min_length=2
|
23
|
+
)
|
24
|
+
|
25
|
+
DatabaseIdStringType = constr(pattern=r"^([0-9a-f]{24})?$")
|
11
26
|
|
12
27
|
LiteralLinePlotMode = Literal[
|
13
28
|
"lines",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openseries
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Package for simple financial time series analysis.
|
5
5
|
Home-page: https://github.com/CaptorAB/OpenSeries
|
6
6
|
License: BSD-3-Clause
|
@@ -24,13 +24,11 @@ Requires-Dist: numpy (>=1.25.1,<2.0.0)
|
|
24
24
|
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
25
25
|
Requires-Dist: pandas (>=2.0.3,<3.0.0)
|
26
26
|
Requires-Dist: plotly (>=5.15.0,<6.0.0)
|
27
|
-
Requires-Dist: pydantic (>=1.
|
27
|
+
Requires-Dist: pydantic (>=2.1.1,<3.0.0)
|
28
28
|
Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
|
29
29
|
Requires-Dist: python-stdnum (>=1.18,<2.0)
|
30
|
-
Requires-Dist: requests (>=2.28.1,<3.0.0)
|
31
30
|
Requires-Dist: scipy (>=1.11.1,<2.0.0)
|
32
|
-
Requires-Dist: statsmodels (>=0.
|
33
|
-
Requires-Dist: urllib3 (>=1.26.9,<2.0.0)
|
31
|
+
Requires-Dist: statsmodels (>=0.14.0,<0.15.0)
|
34
32
|
Project-URL: Repository, https://github.com/CaptorAB/OpenSeries
|
35
33
|
Description-Content-Type: text/markdown
|
36
34
|
|
@@ -50,7 +48,7 @@ width="81" height="100" align="left" float="right"/><br/>
|
|
50
48
|

|
51
49
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
52
50
|
|
53
|
-
**OpenSeries** is a project with tools to
|
51
|
+
**OpenSeries** is a project with tools to analyse financial timeseries of a single
|
54
52
|
asset or a group of assets. It is solely made for daily or less frequent data.
|
55
53
|
|
56
54
|
<span style="font-size:2em;">[Changelog](https://github.com/CaptorAB/OpenSeries/blob/master/CHANGELOG.md)</span>
|
@@ -64,8 +62,12 @@ To install:
|
|
64
62
|
pip install openseries
|
65
63
|
```
|
66
64
|
|
67
|
-
An overview of an OpenTimeSeries object is shown in the below example.
|
68
|
-
|
65
|
+
An overview of an OpenTimeSeries object is shown in the below example. It shows how to
|
66
|
+
create an object from a constructing classmethod. The design aligns with how we within
|
67
|
+
our fund company's code base have a subclass of OpenTimeSeries with class methods
|
68
|
+
for our different data sources. Combined with some additional tools it allows us to
|
69
|
+
efficiently present investment cases to clients.
|
70
|
+
|
69
71
|
The OpenTimeSeries and OpenFrame classes are both subclasses of
|
70
72
|
the [Pydantic BaseModel](https://docs.pydantic.dev/usage/models/).
|
71
73
|
|
@@ -75,16 +77,16 @@ and [OpenFrame](https://github.com/CaptorAB/OpenSeries/blob/master/openseries/fr
|
|
75
77
|
classes have an attribute `tsdf`
|
76
78
|
which is a DataFrame constructed from the raw data in the lists `dates` and `values`.
|
77
79
|
|
78
|
-
```
|
80
|
+
```python
|
79
81
|
from openseries.series import OpenTimeSeries
|
80
|
-
|
82
|
+
import yfinance as yf
|
83
|
+
|
84
|
+
msft=yf.Ticker("MSFT")
|
85
|
+
history=msft.history(period="max")
|
86
|
+
series=OpenTimeSeries.from_df(history.loc[:, "Close"])
|
87
|
+
_=series.value_to_log().set_new_label("Microsoft Log Returns of Close Prices")
|
88
|
+
_,_=series.plot_series()
|
81
89
|
|
82
|
-
```
|
83
|
-
series = OpenTimeSeries.from_arrays(
|
84
|
-
name="Timeseries",
|
85
|
-
dates=["2023-05-08", "2023-05-09", "2023-05-10", "2023-05-11", "2023-05-12"],
|
86
|
-
values=[90.2533, 89.9977, 90.1052, 90.9142, 90.5574],
|
87
|
-
)
|
88
90
|
```
|
89
91
|
|
90
92
|
### Sample output using the OpenFrame.all_properties() method:
|
@@ -130,7 +132,7 @@ own way.
|
|
130
132
|
|
131
133
|
### Windows Powershell
|
132
134
|
|
133
|
-
```
|
135
|
+
```powershell
|
134
136
|
git clone https://github.com/CaptorAB/OpenSeries.git
|
135
137
|
cd OpenSeries
|
136
138
|
./make.ps1 -task make
|
@@ -138,12 +140,13 @@ cd OpenSeries
|
|
138
140
|
|
139
141
|
### Mac Terminal/Linux
|
140
142
|
|
141
|
-
```
|
143
|
+
```bash
|
142
144
|
git clone https://github.com/CaptorAB/OpenSeries.git
|
143
145
|
cd OpenSeries
|
144
146
|
make
|
145
147
|
source source_me
|
146
148
|
make install
|
149
|
+
|
147
150
|
```
|
148
151
|
|
149
152
|
## Testing and Linting / Type-checking
|
@@ -157,16 +160,18 @@ file.
|
|
157
160
|
|
158
161
|
### Windows Powershell
|
159
162
|
|
160
|
-
```
|
163
|
+
```powershell
|
161
164
|
./make.ps1 -task test
|
162
165
|
./make.ps1 -task lint
|
166
|
+
|
163
167
|
```
|
164
168
|
|
165
169
|
### Mac Terminal/Linux
|
166
170
|
|
167
|
-
```
|
171
|
+
```bash
|
168
172
|
make test
|
169
173
|
make lint
|
174
|
+
|
170
175
|
```
|
171
176
|
|
172
177
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
openseries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
openseries/datefixer.py,sha256=h4zshiUkJmRmbBgiCCVulxVUa2SO1dRdJMAKLMxE-tc,9970
|
3
|
-
openseries/frame.py,sha256=
|
3
|
+
openseries/frame.py,sha256=nHRVfYRYPDIV32W6KCMEaJ7d9wG1qWMaeK_6JwfHnOM,115113
|
4
4
|
openseries/load_plotly.py,sha256=DfpacL-aL5z-W0Cw7FL4YtDSbgeSI8Q-8DO6940wiJc,1119
|
5
5
|
openseries/plotly_captor_logo.json,sha256=pGMuPVu4cEO3ZsCH1wU03hxqbIQkHFNoJUs1k1WK89Y,178
|
6
6
|
openseries/plotly_layouts.json,sha256=xhrMOqW8LXb4QMtPiNBGdkPX518OHThiIJ68jpQk524,1429
|
7
7
|
openseries/risk.py,sha256=_NJd8V-6pMx8pTodW-QpGKlmCDbCn4TsEjieKnCkIxU,4404
|
8
|
-
openseries/series.py,sha256=
|
9
|
-
openseries/sim_price.py,sha256=
|
8
|
+
openseries/series.py,sha256=ytojrTbUtgi6Pmh4DbJd_SFIDP-A4xJE2BLaShStwqs,84308
|
9
|
+
openseries/sim_price.py,sha256=2UQKJ9p2_0A10PbxadP5EhjeC9LRBP7IsoQdwQBKHNA,13822
|
10
10
|
openseries/stoch_processes.py,sha256=6O4C_nC2iBseWggvDDC2gTpTqS5fI5nfjSRpccaazLE,14673
|
11
|
-
openseries/types.py,sha256=
|
12
|
-
openseries-1.
|
13
|
-
openseries-1.
|
14
|
-
openseries-1.
|
15
|
-
openseries-1.
|
11
|
+
openseries/types.py,sha256=wz-G8BrlB4NjxDpcJUwYO5PhEjfKI52uoO53k3VkJEQ,7082
|
12
|
+
openseries-1.1.0.dist-info/LICENSE.md,sha256=NJjeq3wyB7EnnHLmsdK1EK6zT00T1eB3FgAmHAPT_vM,1521
|
13
|
+
openseries-1.1.0.dist-info/METADATA,sha256=l7BJzQc--wMAzmYRy2mjo1Gq3bI8VaeZu9YAmJn-z3s,47925
|
14
|
+
openseries-1.1.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
15
|
+
openseries-1.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|