openseries 1.9.6__py3-none-any.whl → 2.0.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/simulation.py CHANGED
@@ -1,15 +1,14 @@
1
- """Defining the ReturnSimulation class.
2
-
3
- Copyright (c) Captor Fund Management AB. This file is part of the openseries project.
4
-
5
- Licensed under the BSD 3-Clause License. You may obtain a copy of the License at:
6
- https://github.com/CaptorAB/openseries/blob/master/LICENSE.md
7
- SPDX-License-Identifier: BSD-3-Clause
8
- """
1
+ """The ReturnSimulation class."""
9
2
 
10
3
  from __future__ import annotations
11
4
 
12
- from typing import TYPE_CHECKING, cast
5
+ from functools import cached_property
6
+ from typing import TYPE_CHECKING, TypedDict, cast
7
+
8
+ try:
9
+ from typing import Unpack
10
+ except ImportError: # pragma: no cover
11
+ from typing_extensions import Unpack
13
12
 
14
13
  if TYPE_CHECKING:
15
14
  import datetime as dt # pragma: no cover
@@ -41,6 +40,14 @@ from .owntypes import (
41
40
  __all__ = ["ReturnSimulation"]
42
41
 
43
42
 
43
+ class _JumpParams(TypedDict, total=False):
44
+ """TypedDict for jump diffusion parameters."""
45
+
46
+ jumps_lamda: NonNegativeFloat
47
+ jumps_sigma: NonNegativeFloat
48
+ jumps_mu: float
49
+
50
+
44
51
  def _random_generator(seed: int | None) -> Generator:
45
52
  """Make a Numpy Random Generator object.
46
53
 
@@ -50,7 +57,7 @@ def _random_generator(seed: int | None) -> Generator:
50
57
  Random seed
51
58
 
52
59
  Returns:
53
- -------
60
+ --------
54
61
  numpy.random.Generator
55
62
  Numpy random process generator
56
63
 
@@ -60,6 +67,58 @@ def _random_generator(seed: int | None) -> Generator:
60
67
  return Generator(bit_generator=bg)
61
68
 
62
69
 
70
+ def _create_base_simulation(
71
+ cls: type[ReturnSimulation],
72
+ returns: DataFrame,
73
+ number_of_sims: PositiveInt,
74
+ trading_days: PositiveInt,
75
+ trading_days_in_year: DaysInYearType,
76
+ mean_annual_return: float,
77
+ mean_annual_vol: PositiveFloat,
78
+ seed: int | None = None,
79
+ **kwargs: Unpack[_JumpParams],
80
+ ) -> ReturnSimulation:
81
+ """Common logic for creating simulations.
82
+
83
+ Parameters
84
+ ----------
85
+ cls: type[ReturnSimulation]
86
+ The ReturnSimulation class
87
+ returns: pandas.DataFrame
88
+ The calculated returns data
89
+ number_of_sims: PositiveInt
90
+ Number of simulations to generate
91
+ trading_days: PositiveInt
92
+ Number of trading days to simulate
93
+ trading_days_in_year: DaysInYearType
94
+ Number of trading days used to annualize
95
+ mean_annual_return: float
96
+ Mean annual return
97
+ mean_annual_vol: PositiveFloat
98
+ Mean annual volatility
99
+ seed: int, optional
100
+ Seed for random process initiation
101
+ **kwargs
102
+ Additional keyword arguments for jump parameters
103
+
104
+ Returns:
105
+ --------
106
+ ReturnSimulation
107
+ A ReturnSimulation instance
108
+
109
+ """
110
+ return cls(
111
+ number_of_sims=number_of_sims,
112
+ trading_days=trading_days,
113
+ trading_days_in_year=trading_days_in_year,
114
+ mean_annual_return=mean_annual_return,
115
+ mean_annual_vol=mean_annual_vol,
116
+ dframe=returns,
117
+ seed=seed,
118
+ **kwargs,
119
+ )
120
+
121
+
63
122
  class ReturnSimulation(BaseModel):
64
123
  """The class ReturnSimulation allows for simulating financial timeseries.
65
124
 
@@ -105,12 +164,12 @@ class ReturnSimulation(BaseModel):
105
164
  revalidate_instances="always",
106
165
  )
107
166
 
108
- @property
167
+ @cached_property
109
168
  def results(self: Self) -> DataFrame:
110
169
  """Simulation data.
111
170
 
112
171
  Returns:
113
- -------
172
+ --------
114
173
  pandas.DataFrame
115
174
  Simulation data
116
175
 
@@ -122,7 +181,7 @@ class ReturnSimulation(BaseModel):
122
181
  """Annualized arithmetic mean of returns.
123
182
 
124
183
  Returns:
125
- -------
184
+ --------
126
185
  float
127
186
  Annualized arithmetic mean of returns
128
187
 
@@ -139,7 +198,7 @@ class ReturnSimulation(BaseModel):
139
198
  """Annualized volatility.
140
199
 
141
200
  Returns:
142
- -------
201
+ --------
143
202
  float
144
203
  Annualized volatility
145
204
 
@@ -183,7 +242,7 @@ class ReturnSimulation(BaseModel):
183
242
  Random process generator
184
243
 
185
244
  Returns:
186
- -------
245
+ --------
187
246
  ReturnSimulation
188
247
  Normal distribution simulation
189
248
 
@@ -197,13 +256,14 @@ class ReturnSimulation(BaseModel):
197
256
  size=(number_of_sims, trading_days),
198
257
  )
199
258
 
200
- return cls(
259
+ return _create_base_simulation(
260
+ cls=cls,
261
+ returns=DataFrame(data=returns, dtype="float64"),
201
262
  number_of_sims=number_of_sims,
202
263
  trading_days=trading_days,
203
264
  trading_days_in_year=trading_days_in_year,
204
265
  mean_annual_return=mean_annual_return,
205
266
  mean_annual_vol=mean_annual_vol,
206
- dframe=DataFrame(data=returns, dtype="float64"),
207
267
  seed=seed,
208
268
  )
209
269
 
@@ -238,7 +298,7 @@ class ReturnSimulation(BaseModel):
238
298
  Random process generator
239
299
 
240
300
  Returns:
241
- -------
301
+ --------
242
302
  ReturnSimulation
243
303
  Lognormal distribution simulation
244
304
 
@@ -255,13 +315,14 @@ class ReturnSimulation(BaseModel):
255
315
  - 1
256
316
  )
257
317
 
258
- return cls(
318
+ return _create_base_simulation(
319
+ cls=cls,
320
+ returns=DataFrame(data=returns, dtype="float64"),
259
321
  number_of_sims=number_of_sims,
260
322
  trading_days=trading_days,
261
323
  trading_days_in_year=trading_days_in_year,
262
324
  mean_annual_return=mean_annual_return,
263
325
  mean_annual_vol=mean_annual_vol,
264
- dframe=DataFrame(data=returns, dtype="float64"),
265
326
  seed=seed,
266
327
  )
267
328
 
@@ -296,7 +357,7 @@ class ReturnSimulation(BaseModel):
296
357
  Random process generator
297
358
 
298
359
  Returns:
299
- -------
360
+ --------
300
361
  ReturnSimulation
301
362
  Geometric Brownian Motion simulation
302
363
 
@@ -317,13 +378,14 @@ class ReturnSimulation(BaseModel):
317
378
 
318
379
  returns = drift + wiener
319
380
 
320
- return cls(
381
+ return _create_base_simulation(
382
+ cls=cls,
383
+ returns=DataFrame(data=returns, dtype="float64"),
321
384
  number_of_sims=number_of_sims,
322
385
  trading_days=trading_days,
323
386
  trading_days_in_year=trading_days_in_year,
324
387
  mean_annual_return=mean_annual_return,
325
388
  mean_annual_vol=mean_annual_vol,
326
- dframe=DataFrame(data=returns, dtype="float64"),
327
389
  seed=seed,
328
390
  )
329
391
 
@@ -367,7 +429,7 @@ class ReturnSimulation(BaseModel):
367
429
  Random process generator
368
430
 
369
431
  Returns:
370
- -------
432
+ --------
371
433
  ReturnSimulation
372
434
  Merton Jump-Diffusion model simulation
373
435
 
@@ -404,17 +466,18 @@ class ReturnSimulation(BaseModel):
404
466
 
405
467
  returns[:, 0] = 0.0
406
468
 
407
- return cls(
469
+ return _create_base_simulation(
470
+ cls=cls,
471
+ returns=DataFrame(data=returns, dtype="float64"),
408
472
  number_of_sims=number_of_sims,
409
473
  trading_days=trading_days,
410
474
  trading_days_in_year=trading_days_in_year,
411
475
  mean_annual_return=mean_annual_return,
412
476
  mean_annual_vol=mean_annual_vol,
477
+ seed=seed,
413
478
  jumps_lamda=jumps_lamda,
414
479
  jumps_sigma=jumps_sigma,
415
480
  jumps_mu=jumps_mu,
416
- dframe=DataFrame(data=returns, dtype="float64"),
417
- seed=seed,
418
481
  )
419
482
 
420
483
  def to_dataframe(
@@ -441,7 +504,7 @@ class ReturnSimulation(BaseModel):
441
504
  (List of) markets code(s) according to pandas-market-calendars
442
505
 
443
506
  Returns:
444
- -------
507
+ --------
445
508
  pandas.DataFrame
446
509
  The simulation(s) data
447
510
 
@@ -465,15 +528,17 @@ class ReturnSimulation(BaseModel):
465
528
  )
466
529
  return sdf
467
530
 
468
- fdf = DataFrame()
469
- for item in range(self.number_of_sims):
470
- sdf = self.dframe.iloc[item].T.to_frame()
471
- sdf.index = Index(d_range)
472
- sdf.columns = MultiIndex.from_arrays(
473
- [
474
- [f"{name}_{item}"],
475
- [ValueType.RTRN],
476
- ],
531
+ df_list = [
532
+ DataFrame(
533
+ data=self.dframe.iloc[item].values,
534
+ index=Index(d_range),
535
+ columns=MultiIndex.from_arrays(
536
+ [
537
+ [f"{name}_{item}"],
538
+ [ValueType.RTRN],
539
+ ],
540
+ ),
477
541
  )
478
- fdf = concat([fdf, sdf], axis="columns", sort=True)
479
- return fdf
542
+ for item in range(self.number_of_sims)
543
+ ]
544
+ return concat(df_list, axis="columns", sort=True)
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: openseries
3
+ Version: 2.0.0
4
+ Summary: Tools for analyzing financial timeseries.
5
+ License: # BSD 3-Clause License
6
+
7
+ ## Copyright (c) Captor Fund Management AB
8
+
9
+ Redistribution and use in source and binary forms, with or without modification, are
10
+ permitted provided that the following conditions are met:
11
+
12
+ 1. Redistributions of source code must retain the above copyright notice, this list of
13
+ conditions and the following disclaimer.
14
+
15
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
16
+ of conditions and the following disclaimer in the documentation and/or other
17
+ materials provided with the distribution.
18
+
19
+ 3. Neither the name of the copyright holder nor the names of its contributors may be
20
+ used to endorse or promote products derived from this software without specific prior
21
+ written permission.
22
+
23
+ This software is provided by the copyright holders and contributors “as is” and any
24
+ express or implied warranties, including, but not limited to, the implied warranties of
25
+ merchantability and fitness for a particular purpose, are disclaimed. In no event shall
26
+ the copyright holder or contributors be liable for any direct, indirect, incidental,
27
+ special, exemplary, or consequential damages (including, but not limited to, procurement
28
+ of substitute goods or services; loss of use, data, or profits; or business interruption)
29
+ however caused and on any theory of liability, whether in contract, strict liability,
30
+ or tort (including negligence or otherwise) arising in any way out of the use of this
31
+ software, even if advised of the possibility of such damage.
32
+ License-File: LICENSE.md
33
+ Keywords: python,finance,fintech,data-science,timeseries,timeseries-data,timeseries-analysis,investment,investment-analysis,investing
34
+ Author: Martin Karrin
35
+ Author-email: martin.karrin@captor.se
36
+ Maintainer: Martin Karrin
37
+ Maintainer-email: martin.karrin@captor.se
38
+ Requires-Python: >=3.10,<3.14
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: License :: OSI Approved :: BSD License
44
+ Classifier: Intended Audience :: Financial and Insurance Industry
45
+ Classifier: Topic :: Office/Business :: Financial :: Investment
46
+ Classifier: Natural Language :: English
47
+ Classifier: Development Status :: 5 - Production/Stable
48
+ Classifier: Operating System :: OS Independent
49
+ Classifier: Framework :: Pydantic
50
+ Requires-Dist: exchange-calendars (>=4.8,<6.0)
51
+ Requires-Dist: holidays (>=0.30,<1.0)
52
+ Requires-Dist: numpy (>=1.23.2,!=2.3.0,<3.0.0)
53
+ Requires-Dist: openpyxl (>=3.1.2,<5.0.0)
54
+ Requires-Dist: pandas (>=2.1.2,<3.0.0)
55
+ Requires-Dist: plotly (>=5.18.0,<7.0.0)
56
+ Requires-Dist: pydantic (>=2.5.2,<3.0.0)
57
+ Requires-Dist: python-dateutil (>=2.8.2,<4.0.0)
58
+ Requires-Dist: requests (>=2.20.0,<3.0.0)
59
+ Requires-Dist: scikit-learn (>=1.4.0,<2.0.0)
60
+ Requires-Dist: scipy (>=1.11.4,<2.0.0)
61
+ Project-URL: Documentation, https://openseries.readthedocs.io/
62
+ Project-URL: Homepage, https://github.com/CaptorAB/openseries
63
+ Project-URL: Issue Tracker, https://github.com/CaptorAB/openseries/issues
64
+ Project-URL: Release Notes, https://github.com/CaptorAB/openseries/releases
65
+ Project-URL: Source, https://github.com/CaptorAB/openseries
66
+ Description-Content-Type: text/markdown
67
+
68
+ <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/>
69
+
70
+ <br><br>
71
+
72
+ # openseries
73
+
74
+ [![PyPI version](https://img.shields.io/pypi/v/openseries.svg)](https://pypi.org/project/openseries/)
75
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/openseries.svg)](https://anaconda.org/conda-forge/openseries)
76
+ ![Platform](https://img.shields.io/badge/platforms-Windows%20%7C%20macOS%20%7C%20Linux-blue)
77
+ [![Python version](https://img.shields.io/pypi/pyversions/openseries.svg)](https://www.python.org/)
78
+ [![GitHub Action Test Suite](https://github.com/CaptorAB/openseries/actions/workflows/test.yml/badge.svg)](https://github.com/CaptorAB/openseries/actions/workflows/test.yml)
79
+ [![codecov](https://img.shields.io/codecov/c/gh/CaptorAB/openseries?logo=codecov)](https://codecov.io/gh/CaptorAB/openseries/branch/master)
80
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
81
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://beta.ruff.rs/docs/)
82
+ [![GitHub License](https://img.shields.io/github/license/CaptorAB/openseries)](https://github.com/CaptorAB/openseries/blob/master/LICENSE.md)
83
+ [![Code Sample](https://img.shields.io/badge/-Code%20Sample-blue)](https://nbviewer.org/github/karrmagadgeteer2/NoteBook/blob/master/openseriesnotebook.ipynb)
84
+
85
+ Tools for analyzing financial timeseries of a single asset or a group of assets. Designed for daily or less frequent data.
86
+
87
+ ## Documentation
88
+
89
+ Complete documentation is available at: [https://openseries.readthedocs.io](https://openseries.readthedocs.io/)
90
+
91
+ The documentation includes:
92
+
93
+ - Quick start guide
94
+ - API reference
95
+ - Tutorials and examples
96
+ - Installation instructions
97
+
98
+ ## Installation
99
+
100
+ ```bash
101
+ pip install openseries
102
+ ```
103
+
104
+ or:
105
+
106
+ ```bash
107
+ conda install -c conda-forge openseries
108
+ ```
109
+
110
+ ## Quick Start
111
+
112
+ ```python
113
+ from openseries import OpenTimeSeries
114
+ import yfinance as yf
115
+
116
+ move=yf.Ticker(ticker="^MOVE")
117
+ history=move.history(period="max")
118
+ series=OpenTimeSeries.from_df(dframe=history.loc[:, "Close"])
119
+ _=series.set_new_label(lvl_zero="ICE BofAML MOVE Index")
120
+ _,_=series.plot_series()
121
+ ```
122
+
123
+ ### Sample output using the report_html() function
124
+
125
+ <img src="https://raw.githubusercontent.com/CaptorAB/openseries/master/openseries_plot.png" alt="Two Assets Compared" width="1000" />
126
+
@@ -0,0 +1,18 @@
1
+ openseries/__init__.py,sha256=WVAO2vtZUZHp7wlXCXV_OKaLkPHfGUjfxTGgBsMdORc,1104
2
+ openseries/_common_model.py,sha256=vXVsSuD6ULTDT6A_sg58uS_yfoazQQvwtjo_jxKMQHA,89131
3
+ openseries/_risk.py,sha256=YisMnI8DQT0w9n9SQbrvq0ZZqmZHrz7-jhZtngObJRk,2094
4
+ openseries/datefixer.py,sha256=U1Kc6QdW3UEzAp61NIUALOllyLWb-mJemiL7KLfSAto,15512
5
+ openseries/frame.py,sha256=OCx4soNy_PzjOwpEzxhmdBUIbXjM2WzXv-JaW5GJ4U8,57343
6
+ openseries/load_plotly.py,sha256=sVssTMzJ2tPPHceCa9OCavI4Mv5BFgSKR6wnTltnqQQ,1997
7
+ openseries/owntypes.py,sha256=I709YjKqN9W9bJNNezhCQbnmTZgTIZZnoxzoUkbHF8w,9436
8
+ openseries/plotly_captor_logo.json,sha256=F5nhMzEyxKywtjvQqMTKgKRCJQYMDIiBgDSxdte8Clo,178
9
+ openseries/plotly_layouts.json,sha256=MvDEQuiqIhMBXBelXb1sedTOlTPheizv6NZRLeE9YS4,1431
10
+ openseries/portfoliotools.py,sha256=v7s9-AgJFlvPIbPuPf6J7d0VjP-dDT-rsm086EoqSAE,19073
11
+ openseries/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ openseries/report.py,sha256=FYN79MroQfY8DrDSSdsSDBcy6S9PwIS0FyujnqPEQV0,14106
13
+ openseries/series.py,sha256=Wp5G3EmzsBqABtkIPvFQ0Y4T77RhXM9uzvtJBPFWMrQ,28354
14
+ openseries/simulation.py,sha256=J58uHuakeIbZ2Pabha-RtsaO-k-MVsRfXSdZexrMAkI,16071
15
+ openseries-2.0.0.dist-info/METADATA,sha256=8L-PeC1b2pv8VfrC5upsvunrh1WNSiaOMvWg2BfxXZs,6085
16
+ openseries-2.0.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
17
+ openseries-2.0.0.dist-info/licenses/LICENSE.md,sha256=wNupG-KLsG0aTncb_SMNDh1ExtrKXlpxSJ6RC-g-SWs,1516
18
+ openseries-2.0.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.0
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any