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 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 BaseModel, validator
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
- arbitrary_types_allowed = True
94
- validate_assignment = True
91
+ model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)
95
92
 
96
- @validator("constituents")
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, constr, conlist, validator
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
- COUNTRYPATTERN,
47
- CURRENCYPATTERN,
48
- DATABASEIDPATTERN,
49
- DATEPATTERN,
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
- # noinspection PyMethodParameters
134
- class OpenTimeSeries(BaseModel):
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: constr(regex=DATABASEIDPATTERN)
170
- instrumentId: constr(regex=DATABASEIDPATTERN)
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
- values: conlist(item_type=float, min_items=1)
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
- class Config:
196
- """Configurations for the OpenTimeSeries class"""
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(CURRENCYPATTERN)
227
- ctry_pattern = re_compile(COUNTRYPATTERN)
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
- COUNTRYPATTERN = r"^[A-Z]{2}$"
8
- CURRENCYPATTERN = r"^[A-Z]{3}$"
9
- DATEPATTERN = r"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$"
10
- DATABASEIDPATTERN = r"^([0-9a-f]{24})?$"
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.0.0
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.10.11,<2.0.0)
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.13.5,<0.14.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
  ![pylint](https://github.com/CaptorAB/OpenSeries/actions/workflows/pylint.yml/badge.svg)
51
49
  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
52
50
 
53
- **OpenSeries** is a project with tools to perform timeseries analysis on a single
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. My preference
68
- is to instantiate an object from a constructing class methods such as this.
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=p0xHGTEe6eUlakoxgAldwXjquTSfyvXMektdsYEgJnI,115141
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=Xw7ppt2bCVspkjYIqZKcMNfVIlrsmrnV7XWtp99qxrg,84385
9
- openseries/sim_price.py,sha256=dWzmj22nq4TW4BZBwP8Ajtid_g322No6D_m7t5bT8No,13878
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=t5xeqoD-e9fm0aU5I9chbzLcZ-MHmb9-jInCz3NrIfk,6698
12
- openseries-1.0.0.dist-info/LICENSE.md,sha256=NJjeq3wyB7EnnHLmsdK1EK6zT00T1eB3FgAmHAPT_vM,1521
13
- openseries-1.0.0.dist-info/METADATA,sha256=DfsJ-HSIyPGdL_33nJK7OhCSuEStkm6duUGhnTA1rNQ,47713
14
- openseries-1.0.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
15
- openseries-1.0.0.dist-info/RECORD,,
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,,