openseries 1.7.6__py3-none-any.whl → 1.7.8__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 CHANGED
@@ -23,20 +23,20 @@ from .types import ValueType
23
23
 
24
24
  __all__ = [
25
25
  "OpenFrame",
26
+ "OpenTimeSeries",
27
+ "ReturnSimulation",
28
+ "ValueType",
26
29
  "constrain_optimized_portfolios",
27
- "efficient_frontier",
28
- "prepare_plot_data",
29
- "sharpeplot",
30
- "simulate_portfolios",
31
30
  "date_fix",
32
31
  "date_offset_foll",
32
+ "efficient_frontier",
33
33
  "generate_calendar_date_range",
34
34
  "get_previous_business_day_before_today",
35
35
  "holiday_calendar",
36
- "offset_business_days",
37
36
  "load_plotly_dict",
38
- "OpenTimeSeries",
37
+ "offset_business_days",
38
+ "prepare_plot_data",
39
+ "sharpeplot",
40
+ "simulate_portfolios",
39
41
  "timeseries_chain",
40
- "ReturnSimulation",
41
- "ValueType",
42
42
  ]
openseries/frame.py CHANGED
@@ -13,6 +13,7 @@ if TYPE_CHECKING:
13
13
 
14
14
  import statsmodels.api as sm # type: ignore[import-untyped,unused-ignore]
15
15
  from numpy import (
16
+ array,
16
17
  cov,
17
18
  divide,
18
19
  isinf,
@@ -1456,7 +1457,7 @@ class OpenFrame(_CommonModel):
1456
1457
  raise NotImplementedError(msg)
1457
1458
 
1458
1459
  return DataFrame(
1459
- data=(returns @ self.weights).add(1.0).cumprod(),
1460
+ data=(returns @ array(self.weights)).add(1.0).cumprod(),
1460
1461
  index=self.tsdf.index,
1461
1462
  columns=[[name], [ValueType.PRICE]],
1462
1463
  dtype="float64",
openseries/load_plotly.py CHANGED
@@ -8,7 +8,7 @@ from pathlib import Path
8
8
  from typing import TYPE_CHECKING
9
9
 
10
10
  import requests
11
- from requests.exceptions import ConnectionError
11
+ from requests.exceptions import ConnectionError as RequestsConnectionError
12
12
 
13
13
  if TYPE_CHECKING:
14
14
  from .types import CaptorLogoType, PlotlyLayoutType # pragma: no cover
@@ -36,7 +36,7 @@ def _check_remote_file_existence(url: str) -> bool:
36
36
  response = requests.head(url, timeout=30)
37
37
  if response.status_code != ok_code:
38
38
  return False
39
- except ConnectionError:
39
+ except RequestsConnectionError:
40
40
  return False
41
41
  return True
42
42
 
@@ -189,7 +189,7 @@ def efficient_frontier( # noqa: C901
189
189
  frontier_max = cleaned_arithmetic_means.max()
190
190
 
191
191
  def _check_sum(weights: NDArray[float64]) -> float64:
192
- return cast(float64, npsum(weights) - 1)
192
+ return npsum(weights) - 1
193
193
 
194
194
  def _get_ret_vol_sr(
195
195
  lg_ret: DataFrame,
openseries/series.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import datetime as dt
6
+ from collections.abc import Iterable
6
7
  from copy import deepcopy
7
8
  from logging import warning
8
9
  from typing import Any, TypeVar, cast
@@ -35,7 +36,6 @@ from .types import (
35
36
  CountriesType,
36
37
  Currency,
37
38
  CurrencyStringType,
38
- DatabaseIdStringType,
39
39
  DateListType,
40
40
  DaysInYearType,
41
41
  LiteralBizDayFreq,
@@ -60,9 +60,9 @@ class OpenTimeSeries(_CommonModel):
60
60
 
61
61
  Parameters
62
62
  ----------
63
- timeseries_id : DatabaseIdStringType
63
+ timeseries_id : str
64
64
  Database identifier of the timeseries
65
- instrument_id: DatabaseIdStringType
65
+ instrument_id: str
66
66
  Database identifier of the instrument associated with the timeseries
67
67
  name : str
68
68
  string identifier of the timeseries and/or instrument
@@ -91,8 +91,8 @@ class OpenTimeSeries(_CommonModel):
91
91
 
92
92
  """
93
93
 
94
- timeseries_id: DatabaseIdStringType
95
- instrument_id: DatabaseIdStringType
94
+ timeseries_id: str
95
+ instrument_id: str
96
96
  name: str
97
97
  valuetype: ValueType
98
98
  dates: DateListType
@@ -147,8 +147,8 @@ class OpenTimeSeries(_CommonModel):
147
147
  dates: DateListType,
148
148
  values: ValueListType,
149
149
  valuetype: ValueType = ValueType.PRICE,
150
- timeseries_id: DatabaseIdStringType = "",
151
- instrument_id: DatabaseIdStringType = "",
150
+ timeseries_id: str = "",
151
+ instrument_id: str = "",
152
152
  isin: str | None = None,
153
153
  baseccy: CurrencyStringType = "SEK",
154
154
  *,
@@ -166,9 +166,9 @@ class OpenTimeSeries(_CommonModel):
166
166
  Array of float values
167
167
  valuetype : ValueType, default: ValueType.PRICE
168
168
  Identifies if the series is a series of values or returns
169
- timeseries_id : DatabaseIdStringType, optional
169
+ timeseries_id : str, optional
170
170
  Database identifier of the timeseries
171
- instrument_id: DatabaseIdStringType, optional
171
+ instrument_id: str, optional
172
172
  Database identifier of the instrument associated with the timeseries
173
173
  isin : str, optional
174
174
  ISO 6166 identifier code of the associated instrument
@@ -234,12 +234,13 @@ class OpenTimeSeries(_CommonModel):
234
234
 
235
235
  """
236
236
  msg = "Argument dframe must be pandas Series or DataFrame."
237
+ values: list[float]
237
238
  if isinstance(dframe, Series):
238
239
  if isinstance(dframe.name, tuple):
239
240
  label, _ = dframe.name
240
241
  else:
241
242
  label = dframe.name
242
- values = dframe.to_numpy().tolist()
243
+ values = cast(list[float], dframe.to_numpy().tolist())
243
244
  elif isinstance(dframe, DataFrame):
244
245
  values = dframe.iloc[:, column_nmbr].to_list()
245
246
  if isinstance(dframe.columns, MultiIndex):
@@ -331,24 +332,19 @@ class OpenTimeSeries(_CommonModel):
331
332
  An OpenTimeSeries object
332
333
 
333
334
  """
334
- if not isinstance(d_range, DatetimeIndex) and all([days, end_dt]):
335
+ if not isinstance(d_range, Iterable) and all([days, end_dt]):
335
336
  d_range = DatetimeIndex(
336
337
  [d.date() for d in date_range(periods=days, end=end_dt, freq="D")],
337
338
  )
338
- elif not isinstance(d_range, DatetimeIndex) and not all([days, end_dt]):
339
+ elif not isinstance(d_range, Iterable) and not all([days, end_dt]):
339
340
  msg = "If d_range is not provided both days and end_dt must be."
340
341
  raise ValueError(msg)
341
342
 
342
343
  deltas = array(
343
- [
344
- i.days
345
- for i in cast(DatetimeIndex, d_range)[1:]
346
- - cast(DatetimeIndex, d_range)[:-1]
347
- ],
344
+ [i.days for i in DatetimeIndex(d_range)[1:] - DatetimeIndex(d_range)[:-1]], # type: ignore[arg-type]
348
345
  )
349
- # noinspection PyTypeChecker
350
- arr = list(cumprod(insert(1 + deltas * rate / 365, 0, 1.0)))
351
- dates = [d.strftime("%Y-%m-%d") for d in cast(DatetimeIndex, d_range)]
346
+ arr: list[float] = list(cumprod(insert(1 + deltas * rate / 365, 0, 1.0)))
347
+ dates = [d.strftime("%Y-%m-%d") for d in DatetimeIndex(d_range)] # type: ignore[arg-type]
352
348
 
353
349
  return cls(
354
350
  timeseries_id="",
openseries/types.py CHANGED
@@ -77,16 +77,6 @@ DateListType = Annotated[
77
77
 
78
78
  ValueListType = Annotated[list[float], conlist(float, min_length=1)]
79
79
 
80
- DatabaseIdStringType = Annotated[
81
- str,
82
- StringConstraints(
83
- pattern=r"^([0-9a-f]{24})?$",
84
- strict=True,
85
- strip_whitespace=True,
86
- max_length=24,
87
- ),
88
- ]
89
-
90
80
  DaysInYearType = Annotated[int, Field(strict=True, ge=1, le=366)]
91
81
 
92
82
  DateType = str | dt.date | dt.datetime | datetime64 | Timestamp
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openseries
3
- Version: 1.7.6
3
+ Version: 1.7.8
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,<3.13
10
+ Requires-Python: >=3.10,<3.14
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Framework :: Pydantic
13
13
  Classifier: Intended Audience :: Financial and Insurance Industry
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
21
22
  Classifier: Topic :: Office/Business :: Financial :: Investment
22
23
  Requires-Dist: holidays (>=0.30,<1.0)
23
24
  Requires-Dist: numpy (>=1.23.2,<3.0.0)
@@ -33,21 +34,18 @@ Requires-Dist: statsmodels (>=0.14.0,!=0.14.2,<1.0.0)
33
34
  Project-URL: Repository, https://github.com/CaptorAB/openseries
34
35
  Description-Content-Type: text/markdown
35
36
 
36
- <img src="https://sales.captor.se/captor_logo_sv_1600_icketransparent.png" alt="Captor
37
- Fund Management AB"
38
- width="81" height="100" align="left" float="right"/><br/>
37
+ <a href="https://captor.se/"><img src="https://sales.captor.se/captor_logo_sv_1600_icketransparent.png" alt="Captor Fund Management AB" width="81" height="100" align="left" float="right"/></a><br/>
39
38
 
40
39
  <br><br>
41
40
 
42
41
  # openseries
43
42
 
44
43
  [![PyPI version](https://img.shields.io/pypi/v/openseries.svg)](https://pypi.org/project/openseries/)
45
- [![Conda version](https://img.shields.io/conda/vn/conda-forge/openseries.svg)](https://anaconda.org/conda-forge/openseries)
44
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/openseries.svg)](https://anaconda.org/conda-forge/openseries)
46
45
  [![Conda platforms](https://img.shields.io/conda/pn/conda-forge/openseries.svg)](https://anaconda.org/conda-forge/openseries)
47
46
  [![Python version](https://img.shields.io/pypi/pyversions/openseries.svg)](https://www.python.org/)
48
47
  [![GitHub Action Test Suite](https://github.com/CaptorAB/openseries/actions/workflows/test.yml/badge.svg)](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
49
48
  [![Coverage](https://cdn.jsdelivr.net/gh/CaptorAB/openseries@master/coverage.svg)](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
50
- [![Styling, Linting & Type checks](https://github.com/CaptorAB/openseries/actions/workflows/check.yml/badge.svg)](https://github.com/CaptorAB/openseries/actions/workflows/check.yml)
51
49
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
52
50
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://beta.ruff.rs/docs/)
53
51
  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
@@ -55,8 +53,6 @@ width="81" height="100" align="left" float="right"/><br/>
55
53
  This is a project with tools to analyze financial timeseries of a single
56
54
  asset or a group of assets. It is solely made for daily or less frequent data.
57
55
 
58
- <span style="font-size:2em;">[CHANGELOG](https://github.com/CaptorAB/openseries/blob/master/CHANGELOG.md)</span>
59
-
60
56
 
61
57
  ## Basic Usage
62
58
 
@@ -66,6 +62,8 @@ To install:
66
62
  pip install openseries
67
63
  ```
68
64
 
65
+ or:
66
+
69
67
  ```bash
70
68
  conda install -c conda-forge openseries
71
69
  ```
@@ -82,10 +80,10 @@ Install openseries and yfinance first.
82
80
  from openseries import OpenTimeSeries
83
81
  import yfinance as yf
84
82
 
85
- msft=yf.Ticker("MSFT")
86
- history=msft.history(period="max")
83
+ move=yf.Ticker("^MOVE")
84
+ history=move.history(period="max")
87
85
  series=OpenTimeSeries.from_df(history.loc[:, "Close"])
88
- _=series.value_to_log().set_new_label("Microsoft Log Returns of Close Prices")
86
+ _=series.set_new_label("ICE BofAML MOVE Index")
89
87
  _,_=series.plot_series()
90
88
 
91
89
  ```
@@ -0,0 +1,16 @@
1
+ openseries/__init__.py,sha256=gWSOyzR78BMAANZokCz2CoC1RxZM4eSpJOHFGQfFToc,1032
2
+ openseries/_common_model.py,sha256=R9PhG5hrOk5pJjv3aox9fI1-Pv90wXYjbdbOU_YNlVA,73768
3
+ openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
4
+ openseries/datefixer.py,sha256=3E8Ddf3Ps9k5qUWqL13ONelyMECZsvtyrsFJg7r3bxE,12298
5
+ openseries/frame.py,sha256=nGqqLlENLuSj0YuR1AXtgLg-w8kPCfUQf6xkjGiOTEI,55378
6
+ openseries/load_plotly.py,sha256=vL4nZuX20d3F5q-NbaHldIsKInUc9tXOu6S-rDGHuDw,1956
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=B4oJkT_j44h3IsRsFAQcepGonvXda8uriAWGXEHyWmE,19087
10
+ openseries/series.py,sha256=vvwpTH-My5ju-m2LOQOYzXV0VCU4DJCxOo6v-DXpWHI,27514
11
+ openseries/simulation.py,sha256=Gc5h3KD3K5AySWqXzm1lbsn2_mwOEWjHr6EVNHb1R-w,13878
12
+ openseries/types.py,sha256=J102TI1x1X6BQxsF65RN3U1heBUfzrCFVRwXAJj_R7k,7302
13
+ openseries-1.7.8.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
14
+ openseries-1.7.8.dist-info/METADATA,sha256=8030LLO_xBVZTcuFhmR4_YJieAG17NepGvoi7M_hgZ8,43744
15
+ openseries-1.7.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
+ openseries-1.7.8.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- openseries/__init__.py,sha256=gD2dMKRTJ9HMXLca_5sR67xGiU5sWExwaNUi-9N_RGQ,1032
2
- openseries/_common_model.py,sha256=R9PhG5hrOk5pJjv3aox9fI1-Pv90wXYjbdbOU_YNlVA,73768
3
- openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
4
- openseries/datefixer.py,sha256=3E8Ddf3Ps9k5qUWqL13ONelyMECZsvtyrsFJg7r3bxE,12298
5
- openseries/frame.py,sha256=bg9R0KDjSw29sPQClKJ4Cvyj7_O3eVtIGM-ISbD75xk,55360
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=s8bQ1SfcXF-xY3GbpyOvMHfypPBXtEl6jDZwVRcrSY4,19102
10
- openseries/series.py,sha256=i-zVf3lsk4u_4VlWCSFRQax51LAStMewKIVgiqlo7gQ,27654
11
- openseries/simulation.py,sha256=Gc5h3KD3K5AySWqXzm1lbsn2_mwOEWjHr6EVNHb1R-w,13878
12
- openseries/types.py,sha256=IbzW9iVuA3MEx3WtjyB6QYeSd3TkGjTOkFnnpSADKlY,7491
13
- openseries-1.7.6.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
14
- openseries-1.7.6.dist-info/METADATA,sha256=e6wq3V6hQOzCPnuZB0V-ogpETHWfcWp537EYBpYORkw,43981
15
- openseries-1.7.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
- openseries-1.7.6.dist-info/RECORD,,