openseries 1.8.3__py3-none-any.whl → 1.9.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/__init__.py +10 -1
- openseries/_common_model.py +55 -5
- openseries/_risk.py +8 -1
- openseries/datefixer.py +127 -33
- openseries/frame.py +10 -7
- openseries/load_plotly.py +8 -1
- openseries/owntypes.py +12 -11
- openseries/portfoliotools.py +8 -1
- openseries/report.py +479 -0
- openseries/series.py +32 -1
- openseries/simulation.py +12 -1
- {openseries-1.8.3.dist-info → openseries-1.9.0.dist-info}/METADATA +46 -73
- openseries-1.9.0.dist-info/RECORD +17 -0
- openseries-1.8.3.dist-info/RECORD +0 -16
- {openseries-1.8.3.dist-info → openseries-1.9.0.dist-info}/LICENSE.md +0 -0
- {openseries-1.8.3.dist-info → openseries-1.9.0.dist-info}/WHEEL +0 -0
openseries/__init__.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""openseries.openseries.__init__.py.
|
1
|
+
"""openseries.openseries.__init__.py.
|
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
|
+
"""
|
2
9
|
|
3
10
|
from .datefixer import (
|
4
11
|
date_fix,
|
@@ -18,6 +25,7 @@ from .portfoliotools import (
|
|
18
25
|
sharpeplot,
|
19
26
|
simulate_portfolios,
|
20
27
|
)
|
28
|
+
from .report import report_html
|
21
29
|
from .series import OpenTimeSeries, timeseries_chain
|
22
30
|
from .simulation import ReturnSimulation
|
23
31
|
|
@@ -37,6 +45,7 @@ __all__ = [
|
|
37
45
|
"load_plotly_dict",
|
38
46
|
"offset_business_days",
|
39
47
|
"prepare_plot_data",
|
48
|
+
"report_html",
|
40
49
|
"sharpeplot",
|
41
50
|
"simulate_portfolios",
|
42
51
|
"timeseries_chain",
|
openseries/_common_model.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Defining the _CommonModel class.
|
1
|
+
"""Defining the _CommonModel 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
|
+
"""
|
2
9
|
|
3
10
|
# mypy: disable-error-code="no-any-return"
|
4
11
|
from __future__ import annotations
|
@@ -58,7 +65,7 @@ from plotly.figure_factory import create_distplot # type: ignore[import-untyped
|
|
58
65
|
from plotly.graph_objs import Figure # type: ignore[import-untyped]
|
59
66
|
from plotly.io import to_html # type: ignore[import-untyped]
|
60
67
|
from plotly.offline import plot # type: ignore[import-untyped]
|
61
|
-
from pydantic import BaseModel, ConfigDict, DirectoryPath
|
68
|
+
from pydantic import BaseModel, ConfigDict, DirectoryPath, ValidationError
|
62
69
|
from scipy.stats import ( # type: ignore[import-untyped]
|
63
70
|
kurtosis,
|
64
71
|
norm,
|
@@ -377,13 +384,23 @@ class _CommonModel(BaseModel): # type: ignore[misc]
|
|
377
384
|
|
378
385
|
"""
|
379
386
|
method: LiteralPandasReindexMethod = "nearest"
|
380
|
-
|
387
|
+
|
388
|
+
try:
|
389
|
+
countries = self.countries
|
390
|
+
markets = self.markets
|
391
|
+
except AttributeError:
|
392
|
+
countries = self.constituents[0].countries
|
393
|
+
markets = self.constituents[0].markets
|
394
|
+
|
381
395
|
wmdf = self.tsdf.copy()
|
396
|
+
|
382
397
|
dates = _do_resample_to_business_period_ends(
|
383
398
|
data=wmdf,
|
384
399
|
freq="BME",
|
385
400
|
countries=countries,
|
401
|
+
markets=markets,
|
386
402
|
)
|
403
|
+
|
387
404
|
wmdf = wmdf.reindex(index=[deyt.date() for deyt in dates], method=method)
|
388
405
|
wmdf.index = DatetimeIndex(wmdf.index)
|
389
406
|
result = wmdf.ffill().pct_change().min()
|
@@ -539,14 +556,20 @@ class _CommonModel(BaseModel): # type: ignore[misc]
|
|
539
556
|
|
540
557
|
def align_index_to_local_cdays(
|
541
558
|
self: Self,
|
542
|
-
countries: CountriesType =
|
559
|
+
countries: CountriesType | None = None,
|
560
|
+
markets: list[str] | str | None = None,
|
561
|
+
custom_holidays: list[str] | str | None = None,
|
543
562
|
) -> Self:
|
544
563
|
"""Align the index of .tsdf with local calendar business days.
|
545
564
|
|
546
565
|
Parameters
|
547
566
|
----------
|
548
|
-
countries: CountriesType,
|
567
|
+
countries: CountriesType, optional
|
549
568
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
569
|
+
markets: list[str] | str, optional
|
570
|
+
(List of) markets code(s) according to pandas-market-calendars
|
571
|
+
custom_holidays: list[str] | str, optional
|
572
|
+
Argument where missing holidays can be added
|
550
573
|
|
551
574
|
Returns:
|
552
575
|
-------
|
@@ -556,10 +579,37 @@ class _CommonModel(BaseModel): # type: ignore[misc]
|
|
556
579
|
"""
|
557
580
|
startyear = cast("int", to_datetime(self.tsdf.index[0]).year)
|
558
581
|
endyear = cast("int", to_datetime(self.tsdf.index[-1]).year)
|
582
|
+
|
583
|
+
if countries:
|
584
|
+
try:
|
585
|
+
self.countries = countries
|
586
|
+
except ValidationError:
|
587
|
+
for serie in self.constituents:
|
588
|
+
serie.countries = countries
|
589
|
+
else:
|
590
|
+
try:
|
591
|
+
countries = self.countries
|
592
|
+
except AttributeError:
|
593
|
+
countries = self.constituents[0].countries
|
594
|
+
|
595
|
+
if markets:
|
596
|
+
try:
|
597
|
+
self.markets = markets
|
598
|
+
except ValidationError:
|
599
|
+
for serie in self.constituents:
|
600
|
+
serie.markets = markets
|
601
|
+
else:
|
602
|
+
try:
|
603
|
+
markets = self.markets
|
604
|
+
except AttributeError:
|
605
|
+
markets = self.constituents[0].markets
|
606
|
+
|
559
607
|
calendar = holiday_calendar(
|
560
608
|
startyear=startyear,
|
561
609
|
endyear=endyear,
|
562
610
|
countries=countries,
|
611
|
+
markets=markets,
|
612
|
+
custom_holidays=custom_holidays,
|
563
613
|
)
|
564
614
|
|
565
615
|
d_range = [
|
openseries/_risk.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Various risk related functions.
|
1
|
+
"""Various risk related functions.
|
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
|
+
"""
|
2
9
|
|
3
10
|
from __future__ import annotations
|
4
11
|
|
openseries/datefixer.py
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
"""Date related utilities.
|
1
|
+
"""Date related utilities.
|
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
|
+
"""
|
2
9
|
|
3
10
|
from __future__ import annotations
|
4
11
|
|
5
12
|
import datetime as dt
|
6
13
|
from typing import TYPE_CHECKING, cast
|
7
14
|
|
15
|
+
import exchange_calendars as exchcal
|
8
16
|
from dateutil.relativedelta import relativedelta
|
9
17
|
from holidays import (
|
10
18
|
country_holidays,
|
@@ -24,6 +32,7 @@ from pandas.tseries.offsets import CustomBusinessDay
|
|
24
32
|
from .owntypes import (
|
25
33
|
BothStartAndEndError,
|
26
34
|
CountriesNotStringNorListStrError,
|
35
|
+
MarketsNotStringNorListStrError,
|
27
36
|
TradingDaysNotAboveZeroError,
|
28
37
|
)
|
29
38
|
|
@@ -31,7 +40,6 @@ if TYPE_CHECKING:
|
|
31
40
|
from .owntypes import ( # pragma: no cover
|
32
41
|
CountriesType,
|
33
42
|
DateType,
|
34
|
-
HolidayType,
|
35
43
|
LiteralBizDayFreq,
|
36
44
|
)
|
37
45
|
|
@@ -45,11 +53,58 @@ __all__ = [
|
|
45
53
|
]
|
46
54
|
|
47
55
|
|
56
|
+
def market_holidays(
|
57
|
+
startyear: int,
|
58
|
+
endyear: int,
|
59
|
+
markets: str | list[str],
|
60
|
+
) -> list[str]:
|
61
|
+
"""Return a dict of holiday dates mapping to list of markets closed.
|
62
|
+
|
63
|
+
Parameters
|
64
|
+
----------
|
65
|
+
startyear: int
|
66
|
+
First year (inclusive) to consider.
|
67
|
+
endyear: int
|
68
|
+
Last year (inclusive) to consider.
|
69
|
+
markets: str | list[str]
|
70
|
+
String or list of market codes supported by pandas_market_calendars.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
-------
|
74
|
+
list[str]
|
75
|
+
list of holiday dates.
|
76
|
+
"""
|
77
|
+
market_list = [markets] if isinstance(markets, str) else list(markets)
|
78
|
+
|
79
|
+
supported = exchcal.get_calendar_names()
|
80
|
+
|
81
|
+
if not all(m in supported for m in market_list):
|
82
|
+
msg = (
|
83
|
+
"Argument markets must be a string market code or a list of market "
|
84
|
+
"codes supported by pandas_market_calendars."
|
85
|
+
)
|
86
|
+
raise MarketsNotStringNorListStrError(msg)
|
87
|
+
|
88
|
+
holidays: list[str] = []
|
89
|
+
for m in market_list:
|
90
|
+
cal = exchcal.get_calendar(m)
|
91
|
+
cal_hols = cal.regular_holidays.holidays()
|
92
|
+
my_hols: list[str] = [
|
93
|
+
date.date().strftime("%Y-%m-%d")
|
94
|
+
for date in cal_hols
|
95
|
+
if (startyear <= date.date().year <= endyear)
|
96
|
+
]
|
97
|
+
holidays.extend(my_hols)
|
98
|
+
|
99
|
+
return list(set(holidays))
|
100
|
+
|
101
|
+
|
48
102
|
def holiday_calendar(
|
49
103
|
startyear: int,
|
50
104
|
endyear: int,
|
51
105
|
countries: CountriesType = "SE",
|
52
|
-
|
106
|
+
markets: list[str] | str | None = None,
|
107
|
+
custom_holidays: list[str] | str | None = None,
|
53
108
|
) -> busdaycalendar:
|
54
109
|
"""Generate a business calendar.
|
55
110
|
|
@@ -61,9 +116,10 @@ def holiday_calendar(
|
|
61
116
|
Last year in date range generated
|
62
117
|
countries: CountriesType, default: "SE"
|
63
118
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
64
|
-
|
65
|
-
|
66
|
-
|
119
|
+
markets: list[str] | str, optional
|
120
|
+
(List of) markets code(s) according to pandas-market-calendars
|
121
|
+
custom_holidays: list[str] | str, optional
|
122
|
+
Argument where missing holidays can be added
|
67
123
|
|
68
124
|
Returns:
|
69
125
|
-------
|
@@ -79,20 +135,16 @@ def holiday_calendar(
|
|
79
135
|
|
80
136
|
if isinstance(countries, str) and countries in list_supported_countries():
|
81
137
|
staging = country_holidays(country=countries, years=years)
|
82
|
-
|
83
|
-
|
84
|
-
hols = array(sorted(staging.keys()), dtype="datetime64[D]")
|
85
|
-
elif isinstance(countries, list) and all(
|
138
|
+
hols = list(staging.keys())
|
139
|
+
elif isinstance(countries, (list, set)) and all(
|
86
140
|
country in list_supported_countries() for country in countries
|
87
141
|
):
|
88
142
|
country: str
|
89
143
|
countryholidays: list[dt.date | str] = []
|
90
|
-
for
|
144
|
+
for country in countries:
|
91
145
|
staging = country_holidays(country=country, years=years)
|
92
|
-
if i == 0 and custom_holidays is not None:
|
93
|
-
staging.update(custom_holidays)
|
94
146
|
countryholidays += list(staging)
|
95
|
-
hols =
|
147
|
+
hols = list(countryholidays)
|
96
148
|
else:
|
97
149
|
msg = (
|
98
150
|
"Argument countries must be a string country code or "
|
@@ -100,7 +152,22 @@ def holiday_calendar(
|
|
100
152
|
)
|
101
153
|
raise CountriesNotStringNorListStrError(msg)
|
102
154
|
|
103
|
-
|
155
|
+
if markets:
|
156
|
+
market_hols = market_holidays(
|
157
|
+
startyear=startyear, endyear=endyear, markets=markets
|
158
|
+
)
|
159
|
+
dt_mkt_hols = [date_fix(fixerdate=ddate) for ddate in market_hols]
|
160
|
+
hols.extend(dt_mkt_hols)
|
161
|
+
|
162
|
+
if custom_holidays:
|
163
|
+
custom_list = (
|
164
|
+
[custom_holidays]
|
165
|
+
if isinstance(custom_holidays, str)
|
166
|
+
else list(custom_holidays) # type: ignore[arg-type]
|
167
|
+
)
|
168
|
+
hols.extend([date_fix(fixerdate=ddate) for ddate in custom_list])
|
169
|
+
|
170
|
+
return busdaycalendar(holidays=array(sorted(set(hols)), dtype="datetime64[D]"))
|
104
171
|
|
105
172
|
|
106
173
|
def date_fix(
|
@@ -137,7 +204,8 @@ def date_offset_foll(
|
|
137
204
|
raw_date: DateType,
|
138
205
|
months_offset: int = 12,
|
139
206
|
countries: CountriesType = "SE",
|
140
|
-
|
207
|
+
markets: list[str] | str | None = None,
|
208
|
+
custom_holidays: list[str] | str | None = None,
|
141
209
|
*,
|
142
210
|
adjust: bool = False,
|
143
211
|
following: bool = True,
|
@@ -152,9 +220,10 @@ def date_offset_foll(
|
|
152
220
|
Number of months as integer
|
153
221
|
countries: CountriesType, default: "SE"
|
154
222
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
155
|
-
|
156
|
-
|
157
|
-
|
223
|
+
markets: list[str] | str, optional
|
224
|
+
(List of) markets code(s) according to pandas-market-calendars
|
225
|
+
custom_holidays: list[str] | str, optional
|
226
|
+
Argument where missing holidays can be added
|
158
227
|
adjust: bool, default: False
|
159
228
|
Determines if offset should adjust for business days
|
160
229
|
following: bool, default: True
|
@@ -180,6 +249,7 @@ def date_offset_foll(
|
|
180
249
|
startyear=startyear,
|
181
250
|
endyear=endyear,
|
182
251
|
countries=countries,
|
252
|
+
markets=markets,
|
183
253
|
custom_holidays=custom_holidays,
|
184
254
|
)
|
185
255
|
while not is_busday(dates=new_date, busdaycal=calendar):
|
@@ -191,7 +261,8 @@ def date_offset_foll(
|
|
191
261
|
def get_previous_business_day_before_today(
|
192
262
|
today: dt.date | None = None,
|
193
263
|
countries: CountriesType = "SE",
|
194
|
-
|
264
|
+
markets: list[str] | str | None = None,
|
265
|
+
custom_holidays: list[str] | str | None = None,
|
195
266
|
) -> dt.date:
|
196
267
|
"""Bump date backwards to find the previous business day.
|
197
268
|
|
@@ -201,9 +272,10 @@ def get_previous_business_day_before_today(
|
|
201
272
|
Manual input of the day from where the previous business day is found
|
202
273
|
countries: CountriesType, default: "SE"
|
203
274
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
204
|
-
|
205
|
-
|
206
|
-
|
275
|
+
markets: list[str] | str, optional
|
276
|
+
(List of) markets code(s) according to pandas-market-calendars
|
277
|
+
custom_holidays: list[str] | str, optional
|
278
|
+
Argument where missing holidays can be added
|
207
279
|
|
208
280
|
Returns:
|
209
281
|
-------
|
@@ -215,10 +287,11 @@ def get_previous_business_day_before_today(
|
|
215
287
|
today = dt.datetime.now().astimezone().date()
|
216
288
|
|
217
289
|
return date_offset_foll(
|
218
|
-
today - dt.timedelta(days=1),
|
290
|
+
raw_date=today - dt.timedelta(days=1),
|
291
|
+
months_offset=0,
|
219
292
|
countries=countries,
|
293
|
+
markets=markets,
|
220
294
|
custom_holidays=custom_holidays,
|
221
|
-
months_offset=0,
|
222
295
|
adjust=True,
|
223
296
|
following=False,
|
224
297
|
)
|
@@ -228,7 +301,8 @@ def offset_business_days(
|
|
228
301
|
ddate: dt.date,
|
229
302
|
days: int,
|
230
303
|
countries: CountriesType = "SE",
|
231
|
-
|
304
|
+
markets: list[str] | str | None = None,
|
305
|
+
custom_holidays: list[str] | str | None = None,
|
232
306
|
) -> dt.date:
|
233
307
|
"""Bump date by business days.
|
234
308
|
|
@@ -244,9 +318,10 @@ def offset_business_days(
|
|
244
318
|
If days is set as anything other than an integer its value is set to zero
|
245
319
|
countries: CountriesType, default: "SE"
|
246
320
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
247
|
-
|
248
|
-
|
249
|
-
|
321
|
+
markets: list[str] | str, optional
|
322
|
+
(List of) markets code(s) according to pandas-market-calendars
|
323
|
+
custom_holidays: list[str] | str, optional
|
324
|
+
Argument where missing holidays can be added
|
250
325
|
|
251
326
|
Returns:
|
252
327
|
-------
|
@@ -266,6 +341,7 @@ def offset_business_days(
|
|
266
341
|
startyear=ndate.year,
|
267
342
|
endyear=ddate.year,
|
268
343
|
countries=countries,
|
344
|
+
markets=markets,
|
269
345
|
custom_holidays=custom_holidays,
|
270
346
|
)
|
271
347
|
local_bdays: list[dt.date] = [
|
@@ -283,6 +359,7 @@ def offset_business_days(
|
|
283
359
|
startyear=ddate.year,
|
284
360
|
endyear=ndate.year,
|
285
361
|
countries=countries,
|
362
|
+
markets=markets,
|
286
363
|
custom_holidays=custom_holidays,
|
287
364
|
)
|
288
365
|
local_bdays = [
|
@@ -310,6 +387,8 @@ def generate_calendar_date_range(
|
|
310
387
|
start: dt.date | None = None,
|
311
388
|
end: dt.date | None = None,
|
312
389
|
countries: CountriesType = "SE",
|
390
|
+
markets: list[str] | str | None = None,
|
391
|
+
custom_holidays: list[str] | str | None = None,
|
313
392
|
) -> list[dt.date]:
|
314
393
|
"""Generate a list of business day calendar dates.
|
315
394
|
|
@@ -323,6 +402,10 @@ def generate_calendar_date_range(
|
|
323
402
|
Date when the range ends
|
324
403
|
countries: CountriesType, default: "SE"
|
325
404
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
405
|
+
markets: list[str] | str, optional
|
406
|
+
(List of) markets code(s) according to pandas-market-calendars
|
407
|
+
custom_holidays: list[str] | str, optional
|
408
|
+
Argument where missing holidays can be added
|
326
409
|
|
327
410
|
Returns:
|
328
411
|
-------
|
@@ -344,6 +427,8 @@ def generate_calendar_date_range(
|
|
344
427
|
startyear=start.year,
|
345
428
|
endyear=date_fix(tmp_range.tolist()[-1]).year,
|
346
429
|
countries=countries,
|
430
|
+
markets=markets,
|
431
|
+
custom_holidays=custom_holidays,
|
347
432
|
)
|
348
433
|
return [
|
349
434
|
d.date()
|
@@ -360,6 +445,8 @@ def generate_calendar_date_range(
|
|
360
445
|
startyear=date_fix(tmp_range.tolist()[0]).year,
|
361
446
|
endyear=end.year,
|
362
447
|
countries=countries,
|
448
|
+
markets=markets,
|
449
|
+
custom_holidays=custom_holidays,
|
363
450
|
)
|
364
451
|
return [
|
365
452
|
d.date()
|
@@ -381,6 +468,8 @@ def _do_resample_to_business_period_ends(
|
|
381
468
|
data: DataFrame,
|
382
469
|
freq: LiteralBizDayFreq,
|
383
470
|
countries: CountriesType,
|
471
|
+
markets: list[str] | str | None = None,
|
472
|
+
custom_holidays: list[str] | str | None = None,
|
384
473
|
) -> DatetimeIndex:
|
385
474
|
"""Resample timeseries frequency to business calendar month end dates.
|
386
475
|
|
@@ -394,7 +483,10 @@ def _do_resample_to_business_period_ends(
|
|
394
483
|
The date offset string that sets the resampled frequency
|
395
484
|
countries: CountriesType
|
396
485
|
(List of) country code(s) according to ISO 3166-1 alpha-2
|
397
|
-
|
486
|
+
markets: list[str] | str, optional
|
487
|
+
(List of) markets code(s) according to pandas-market-calendars
|
488
|
+
custom_holidays: list[str] | str, optional
|
489
|
+
Argument where missing holidays can be added
|
398
490
|
|
399
491
|
Returns:
|
400
492
|
-------
|
@@ -413,12 +505,14 @@ def _do_resample_to_business_period_ends(
|
|
413
505
|
dates = DatetimeIndex(
|
414
506
|
[copydata.index[0]]
|
415
507
|
+ [
|
416
|
-
date_offset_foll(
|
417
|
-
dt.date(d.year, d.month, 1)
|
508
|
+
date_offset_foll( # type: ignore[misc]
|
509
|
+
raw_date=dt.date(d.year, d.month, 1)
|
418
510
|
+ relativedelta(months=1)
|
419
511
|
- dt.timedelta(days=1),
|
420
|
-
countries=countries,
|
421
512
|
months_offset=0,
|
513
|
+
countries=countries,
|
514
|
+
markets=markets,
|
515
|
+
custom_holidays=custom_holidays,
|
422
516
|
adjust=True,
|
423
517
|
following=False,
|
424
518
|
)
|
openseries/frame.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Defining the OpenFrame class.
|
1
|
+
"""Defining the OpenFrame 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
|
+
"""
|
2
9
|
|
3
10
|
# mypy: disable-error-code="index,assignment,arg-type,no-any-return"
|
4
11
|
from __future__ import annotations
|
@@ -41,7 +48,6 @@ from pydantic import field_validator
|
|
41
48
|
from ._common_model import _CommonModel
|
42
49
|
from .datefixer import _do_resample_to_business_period_ends
|
43
50
|
from .owntypes import (
|
44
|
-
CountriesType,
|
45
51
|
DaysInYearType,
|
46
52
|
LabelsNotUniqueError,
|
47
53
|
LiteralBizDayFreq,
|
@@ -429,7 +435,6 @@ class OpenFrame(_CommonModel):
|
|
429
435
|
def resample_to_business_period_ends(
|
430
436
|
self: Self,
|
431
437
|
freq: LiteralBizDayFreq = "BME",
|
432
|
-
countries: CountriesType = "SE",
|
433
438
|
method: LiteralPandasReindexMethod = "nearest",
|
434
439
|
) -> Self:
|
435
440
|
"""Resamples timeseries frequency to the business calendar month end dates.
|
@@ -440,9 +445,6 @@ class OpenFrame(_CommonModel):
|
|
440
445
|
----------
|
441
446
|
freq: LiteralBizDayFreq, default "BME"
|
442
447
|
The date offset string that sets the resampled frequency
|
443
|
-
countries: CountriesType, default: "SE"
|
444
|
-
(List of) country code(s) according to ISO 3166-1 alpha-2
|
445
|
-
to create a business day calendar used for date adjustments
|
446
448
|
method: LiteralPandasReindexMethod, default: nearest
|
447
449
|
Controls the method used to align values across columns
|
448
450
|
|
@@ -456,7 +458,8 @@ class OpenFrame(_CommonModel):
|
|
456
458
|
dates = _do_resample_to_business_period_ends(
|
457
459
|
data=xerie.tsdf,
|
458
460
|
freq=freq,
|
459
|
-
countries=countries,
|
461
|
+
countries=xerie.countries,
|
462
|
+
markets=xerie.markets,
|
460
463
|
)
|
461
464
|
xerie.tsdf = xerie.tsdf.reindex(
|
462
465
|
[deyt.date() for deyt in dates],
|
openseries/load_plotly.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Function to load plotly layout and configuration from local json file.
|
1
|
+
"""Function to load plotly layout and configuration from local json file.
|
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
|
+
"""
|
2
9
|
|
3
10
|
from __future__ import annotations
|
4
11
|
|
openseries/owntypes.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Declaring types used throughout the project.
|
1
|
+
"""Declaring types used throughout the project.
|
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
|
+
"""
|
2
9
|
|
3
10
|
from __future__ import annotations
|
4
11
|
|
@@ -86,16 +93,6 @@ DaysInYearType = Annotated[int, Field(strict=True, ge=1, le=366)]
|
|
86
93
|
|
87
94
|
DateType = str | dt.date | dt.datetime | datetime64 | Timestamp
|
88
95
|
|
89
|
-
HolidayType = (
|
90
|
-
dict[dt.date | dt.datetime | str | float | int, str]
|
91
|
-
| list[dt.date | dt.datetime | str | float | int]
|
92
|
-
| dt.date
|
93
|
-
| dt.datetime
|
94
|
-
| str
|
95
|
-
| float
|
96
|
-
| int
|
97
|
-
)
|
98
|
-
|
99
96
|
PlotlyLayoutType = dict[
|
100
97
|
str,
|
101
98
|
str
|
@@ -356,6 +353,10 @@ class CountriesNotStringNorListStrError(Exception):
|
|
356
353
|
"""Raised when countries argument is not provided in correct format."""
|
357
354
|
|
358
355
|
|
356
|
+
class MarketsNotStringNorListStrError(Exception):
|
357
|
+
"""Raised when markets argument is not provided in correct format."""
|
358
|
+
|
359
|
+
|
359
360
|
class TradingDaysNotAboveZeroError(Exception):
|
360
361
|
"""Raised when trading days argument is not above zero."""
|
361
362
|
|
openseries/portfoliotools.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
"""Defining the portfolio tools for the OpenFrame class.
|
1
|
+
"""Defining the portfolio tools for the OpenFrame 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
|
+
"""
|
2
9
|
|
3
10
|
# mypy: disable-error-code="index,assignment"
|
4
11
|
from __future__ import annotations
|