openseries 1.7.0__py3-none-any.whl → 1.7.1__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
@@ -3,7 +3,6 @@
3
3
  from .datefixer import (
4
4
  date_fix,
5
5
  date_offset_foll,
6
- do_resample_to_business_period_ends,
7
6
  generate_calendar_date_range,
8
7
  get_previous_business_day_before_today,
9
8
  holiday_calendar,
@@ -31,7 +30,6 @@ __all__ = [
31
30
  "simulate_portfolios",
32
31
  "date_fix",
33
32
  "date_offset_foll",
34
- "do_resample_to_business_period_ends",
35
33
  "generate_calendar_date_range",
36
34
  "get_previous_business_day_before_today",
37
35
  "holiday_calendar",
@@ -447,7 +447,7 @@ class _CommonModel(BaseModel):
447
447
  interpolation: LiteralQuantileInterp = "lower"
448
448
  return self.vol_from_var_func(level=level, interpolation=interpolation)
449
449
 
450
- def calc_range( # noqa: C901
450
+ def calc_range(
451
451
  self: Self,
452
452
  months_offset: int | None = None,
453
453
  from_dt: dt.date | None = None,
@@ -471,42 +471,38 @@ class _CommonModel(BaseModel):
471
471
  Start and end date of the chosen date range
472
472
 
473
473
  """
474
- earlier, later = self.tsdf.index[0], self.tsdf.index[-1]
475
- if any([months_offset, from_dt, to_dt]):
476
- if months_offset is not None:
477
- earlier = date_offset_foll(
478
- raw_date=DatetimeIndex(self.tsdf.index)[-1],
479
- months_offset=-months_offset,
480
- adjust=False,
481
- following=True,
474
+ earlier, later = self.first_idx, self.last_idx
475
+ if months_offset is not None:
476
+ earlier = date_offset_foll(
477
+ raw_date=self.last_idx,
478
+ months_offset=-months_offset,
479
+ adjust=False,
480
+ following=True,
481
+ )
482
+ if earlier < self.first_idx:
483
+ msg = (
484
+ "Argument months_offset implies start"
485
+ "date before first date in series."
482
486
  )
483
- if earlier < self.tsdf.index[0]:
484
- msg = "Function calc_range returned earlier date < series start"
485
- raise ValueError(
486
- msg,
487
- )
488
- later = self.tsdf.index[-1]
489
- elif from_dt is not None and to_dt is None:
490
- if from_dt < self.tsdf.index[0]:
487
+ raise ValueError(
488
+ msg,
489
+ )
490
+ later = self.last_idx
491
+ else:
492
+ if from_dt is not None:
493
+ if from_dt < self.first_idx:
491
494
  msg = "Given from_dt date < series start"
492
495
  raise ValueError(msg)
493
- earlier, later = from_dt, self.tsdf.index[-1]
494
- elif from_dt is None and to_dt is not None:
495
- if to_dt > self.tsdf.index[-1]:
496
+ earlier = from_dt
497
+ if to_dt is not None:
498
+ if to_dt > self.last_idx:
496
499
  msg = "Given to_dt date > series end"
497
500
  raise ValueError(msg)
498
- earlier, later = self.tsdf.index[0], to_dt
499
- elif from_dt is not None and to_dt is not None:
500
- if to_dt > self.tsdf.index[-1] or from_dt < self.tsdf.index[0]:
501
- msg = "Given from_dt or to_dt dates outside series range"
502
- raise ValueError(
503
- msg,
504
- )
505
- earlier, later = from_dt, to_dt
506
- while earlier not in self.tsdf.index.tolist():
507
- earlier -= dt.timedelta(days=1)
508
- while later not in self.tsdf.index.tolist():
509
- later += dt.timedelta(days=1)
501
+ later = to_dt
502
+ while earlier not in self.tsdf.index:
503
+ earlier -= dt.timedelta(days=1)
504
+ while later not in self.tsdf.index:
505
+ later += dt.timedelta(days=1)
510
506
 
511
507
  return earlier, later
512
508
 
openseries/datefixer.py CHANGED
@@ -15,15 +15,14 @@ from pandas import (
15
15
  DataFrame,
16
16
  DatetimeIndex,
17
17
  Index,
18
- Series,
19
18
  Timestamp,
20
19
  concat,
21
20
  date_range,
22
21
  )
23
22
  from pandas.tseries.offsets import CustomBusinessDay
24
23
 
25
- if TYPE_CHECKING: # pragma: no cover
26
- from .types import (
24
+ if TYPE_CHECKING:
25
+ from .types import ( # pragma: no cover
27
26
  CountriesType,
28
27
  DateType,
29
28
  HolidayType,
@@ -33,7 +32,6 @@ if TYPE_CHECKING: # pragma: no cover
33
32
  __all__ = [
34
33
  "date_fix",
35
34
  "date_offset_foll",
36
- "do_resample_to_business_period_ends",
37
35
  "generate_calendar_date_range",
38
36
  "get_previous_business_day_before_today",
39
37
  "holiday_calendar",
@@ -379,10 +377,9 @@ def generate_calendar_date_range(
379
377
  )
380
378
 
381
379
 
382
- def do_resample_to_business_period_ends(
380
+ # noinspection PyUnusedLocal
381
+ def _do_resample_to_business_period_ends(
383
382
  data: DataFrame,
384
- head: Series[float],
385
- tail: Series[float],
386
383
  freq: LiteralBizDayFreq,
387
384
  countries: CountriesType,
388
385
  ) -> DatetimeIndex:
@@ -394,10 +391,6 @@ def do_resample_to_business_period_ends(
394
391
  ----------
395
392
  data: pandas.DataFrame
396
393
  The timeseries data
397
- head: pandas:Series[float]
398
- Data point at maximum first date of all series
399
- tail: pandas:Series[float]
400
- Data point at minimum last date of all series
401
394
  freq: LiteralBizDayFreq
402
395
  The date offset string that sets the resampled frequency
403
396
  countries: CountriesType
@@ -410,25 +403,16 @@ def do_resample_to_business_period_ends(
410
403
  A date range aligned to business period ends
411
404
 
412
405
  """
413
- newhead = head.to_frame().T
414
- newtail = tail.to_frame().T
415
- data.index = DatetimeIndex(data.index)
416
- data = data.resample(rule=freq).last()
417
- data = data.drop(index=data.index[-1])
418
- data.index = Index(d.date() for d in DatetimeIndex(data.index))
406
+ copydata = data.copy()
407
+ copydata.index = DatetimeIndex(copydata.index)
408
+ copydata = copydata.resample(rule=freq).last()
409
+ copydata = copydata.drop(index=copydata.index[-1])
410
+ copydata.index = Index(d.date() for d in DatetimeIndex(copydata.index))
419
411
 
420
- if newhead.index[0] not in data.index:
421
- # noinspection PyUnreachableCode
422
- data = concat([data, newhead])
423
-
424
- if newtail.index[0] not in data.index:
425
- # noinspection PyUnreachableCode
426
- data = concat([data, newtail])
427
-
428
- data = data.sort_index()
412
+ copydata = concat([data.head(n=1), copydata, data.tail(n=1)]).sort_index()
429
413
 
430
414
  dates = DatetimeIndex(
431
- [data.index[0]]
415
+ [copydata.index[0]]
432
416
  + [
433
417
  date_offset_foll(
434
418
  dt.date(d.year, d.month, 1)
@@ -439,8 +423,8 @@ def do_resample_to_business_period_ends(
439
423
  adjust=True,
440
424
  following=False,
441
425
  )
442
- for d in data.index[1:-1]
426
+ for d in copydata.index[1:-1]
443
427
  ]
444
- + [data.index[-1]],
428
+ + [copydata.index[-1]],
445
429
  )
446
430
  return dates.drop_duplicates()
openseries/frame.py CHANGED
@@ -43,7 +43,7 @@ from statsmodels.regression.linear_model import ( # type: ignore[import-untyped
43
43
  from typing_extensions import Self
44
44
 
45
45
  from ._common_model import _CommonModel
46
- from .datefixer import do_resample_to_business_period_ends
46
+ from .datefixer import _do_resample_to_business_period_ends
47
47
  from .series import OpenTimeSeries
48
48
  from .types import (
49
49
  CountriesType,
@@ -443,21 +443,18 @@ class OpenFrame(_CommonModel):
443
443
  An OpenFrame object
444
444
 
445
445
  """
446
- head: Series[float] = self.tsdf.loc[self.first_indices.max()].copy()
447
- tail: Series[float] = self.tsdf.loc[self.last_indices.min()].copy()
448
- dates = do_resample_to_business_period_ends(
449
- data=self.tsdf,
450
- head=head,
451
- tail=tail,
452
- freq=freq,
453
- countries=countries,
454
- )
455
- self.tsdf = self.tsdf.reindex([deyt.date() for deyt in dates], method=method)
456
446
  for xerie in self.constituents:
447
+ dates = _do_resample_to_business_period_ends(
448
+ data=xerie.tsdf,
449
+ freq=freq,
450
+ countries=countries,
451
+ )
457
452
  xerie.tsdf = xerie.tsdf.reindex(
458
- [deyt.date() for deyt in dates],
459
- method=method,
453
+ [deyt.date() for deyt in dates], method=method,
460
454
  )
455
+
456
+ self._set_tsdf()
457
+
461
458
  return self
462
459
 
463
460
  def ewma_risk(
@@ -1111,6 +1108,9 @@ class OpenFrame(_CommonModel):
1111
1108
  ratios.append(
1112
1109
  (up_rtrn / up_idx_return) / (down_return / down_idx_return),
1113
1110
  )
1111
+ else:
1112
+ msg = "ratio must be one of 'up', 'down' or 'both'."
1113
+ raise ValueError(msg)
1114
1114
 
1115
1115
  if ratio == "up":
1116
1116
  resultname = f"Up Capture Ratios vs {short_label}"
@@ -13,6 +13,7 @@ from numpy import (
13
13
  dot,
14
14
  float64,
15
15
  inf,
16
+ isnan,
16
17
  linspace,
17
18
  nan,
18
19
  sqrt,
@@ -182,10 +183,11 @@ def efficient_frontier( # noqa: C901
182
183
  simulated = simulate_portfolios(simframe=copi, num_ports=num_ports, seed=seed)
183
184
 
184
185
  frontier_min = simulated.loc[simulated["stdev"].idxmin()]["ret"]
185
- arithmetic_mean = log_ret.mean() * copi.periods_in_a_year
186
- frontier_max = 0.0
187
- if isinstance(arithmetic_mean, Series):
188
- frontier_max = arithmetic_mean.max()
186
+
187
+ arithmetic_means = array(log_ret.mean() * copi.periods_in_a_year)
188
+ cleaned_arithmetic_means = arithmetic_means[~isnan(arithmetic_means)]
189
+
190
+ frontier_max = cleaned_arithmetic_means.max()
189
191
 
190
192
  def _check_sum(weights: NDArray[float64]) -> float64:
191
193
  return cast(float64, npsum(weights) - 1)
@@ -286,7 +288,6 @@ def efficient_frontier( # noqa: C901
286
288
  frontier_x.append(result["fun"])
287
289
  frontier_weights.append(result["x"])
288
290
 
289
- # noinspection PyUnreachableCode
290
291
  line_df = concat(
291
292
  [
292
293
  DataFrame(data=frontier_weights, columns=eframe.columns_lvl_zero),
@@ -509,6 +510,10 @@ def sharpeplot( # noqa: C901
509
510
  fig, logo = load_plotly_dict()
510
511
  figure = Figure(fig)
511
512
 
513
+ if sim_frame is None and line_frame is None and point_frame is None:
514
+ msg = "One of sim_frame, line_frame or point_frame must be provided."
515
+ raise ValueError(msg)
516
+
512
517
  if sim_frame is not None:
513
518
  returns.extend(list(sim_frame.loc[:, "ret"]))
514
519
  risk.extend(list(sim_frame.loc[:, "stdev"]))
@@ -543,11 +548,11 @@ def sharpeplot( # noqa: C901
543
548
  name="Efficient frontier",
544
549
  )
545
550
 
546
- colorway = fig["layout"].get("colorway")[ # type: ignore[union-attr]
547
- : len(cast(DataFrame, point_frame).columns)
548
- ]
549
-
550
551
  if point_frame is not None:
552
+ colorway = cast(
553
+ dict[str, str | int | float | bool | list[str]],
554
+ fig["layout"],
555
+ ).get("colorway")[: len(point_frame.columns)]
551
556
  for col, clr in zip(point_frame.columns, colorway):
552
557
  returns.extend([point_frame.loc["ret", col]])
553
558
  risk.extend([point_frame.loc["stdev", col]])
openseries/series.py CHANGED
@@ -25,11 +25,11 @@ from pandas import (
25
25
  Series,
26
26
  date_range,
27
27
  )
28
- from pydantic import model_validator
28
+ from pydantic import field_validator, model_validator
29
29
  from typing_extensions import Self
30
30
 
31
31
  from ._common_model import _CommonModel
32
- from .datefixer import date_fix, do_resample_to_business_period_ends
32
+ from .datefixer import _do_resample_to_business_period_ends, date_fix
33
33
  from .types import (
34
34
  Countries,
35
35
  CountriesType,
@@ -105,6 +105,20 @@ class OpenTimeSeries(_CommonModel):
105
105
  isin: str | None = None
106
106
  label: str | None = None
107
107
 
108
+ @field_validator("domestic", mode="before")
109
+ @classmethod
110
+ def validate_domestic(cls, value: CurrencyStringType) -> CurrencyStringType:
111
+ """Pydantic validator to ensure domestic field is validated."""
112
+ _ = Currency(ccy=value)
113
+ return value
114
+
115
+ @field_validator("countries", mode="before")
116
+ @classmethod
117
+ def validate_countries(cls, value: CountriesType) -> CountriesType:
118
+ """Pydantic validator to ensure countries field is validated."""
119
+ _ = Countries(countryinput=value)
120
+ return value
121
+
108
122
  @model_validator(mode="after") # type: ignore[misc,unused-ignore]
109
123
  def dates_and_values_validate(self: Self) -> Self:
110
124
  """Pydantic validator to ensure dates and values are validated."""
@@ -126,28 +140,6 @@ class OpenTimeSeries(_CommonModel):
126
140
  raise ValueError(msg)
127
141
  return self
128
142
 
129
- @classmethod
130
- def setup_class(
131
- cls: type[OpenTimeSeries],
132
- domestic_ccy: CurrencyStringType = "SEK",
133
- countries: CountriesType = "SE",
134
- ) -> None:
135
- """Set the domestic currency and calendar of the user.
136
-
137
- Parameters
138
- ----------
139
- domestic_ccy : CurrencyStringType, default: "SEK"
140
- Currency code according to ISO 4217
141
- countries: CountriesType, default: "SE"
142
- (List of) country code(s) according to ISO 3166-1 alpha-2
143
-
144
- """
145
- _ = Currency(ccy=domestic_ccy)
146
- _ = Countries(countryinput=countries)
147
-
148
- cls.domestic = domestic_ccy
149
- cls.countries = countries
150
-
151
143
  @classmethod
152
144
  def from_arrays(
153
145
  cls: type[OpenTimeSeries],
@@ -247,8 +239,8 @@ class OpenTimeSeries(_CommonModel):
247
239
  else:
248
240
  label = dframe.name
249
241
  values = dframe.to_numpy().tolist()
250
- else:
251
- values = cast(DataFrame, dframe).iloc[:, column_nmbr].tolist()
242
+ elif isinstance(dframe, DataFrame):
243
+ values = dframe.iloc[:, column_nmbr].to_list()
252
244
  if isinstance(dframe.columns, MultiIndex):
253
245
  if _check_if_none(
254
246
  dframe.columns.get_level_values(0).to_numpy()[column_nmbr],
@@ -270,6 +262,10 @@ class OpenTimeSeries(_CommonModel):
270
262
  ]
271
263
  else:
272
264
  label = cast(MultiIndex, dframe.columns).to_numpy()[column_nmbr]
265
+ else:
266
+ msg = "Argument dframe must be pandas Series or DataFrame."
267
+ raise TypeError(msg)
268
+
273
269
  dates = [date_fix(d).strftime("%Y-%m-%d") for d in dframe.index]
274
270
 
275
271
  return cls(
@@ -584,12 +580,8 @@ class OpenTimeSeries(_CommonModel):
584
580
  An OpenTimeSeries object
585
581
 
586
582
  """
587
- head = self.tsdf.iloc[0].copy()
588
- tail = self.tsdf.iloc[-1].copy()
589
- dates = do_resample_to_business_period_ends(
583
+ dates = _do_resample_to_business_period_ends(
590
584
  data=self.tsdf,
591
- head=head,
592
- tail=tail,
593
585
  freq=freq,
594
586
  countries=self.countries,
595
587
  )
openseries/simulation.py CHANGED
@@ -153,8 +153,8 @@ class ReturnSimulation(BaseModel):
153
153
  mean_annual_return: float,
154
154
  mean_annual_vol: PositiveFloat,
155
155
  trading_days: PositiveInt,
156
- seed: int,
157
156
  trading_days_in_year: DaysInYearType = 252,
157
+ seed: int | None = None,
158
158
  randomizer: Generator | None = None,
159
159
  ) -> ReturnSimulation:
160
160
  """Create a Normal distribution simulation.
@@ -169,11 +169,10 @@ class ReturnSimulation(BaseModel):
169
169
  Mean return
170
170
  mean_annual_vol: PositiveFloat
171
171
  Mean standard deviation
172
- seed: int
173
- Seed for random process initiation
174
- trading_days_in_year: DaysInYearType,
175
- default: 252
172
+ trading_days_in_year: DaysInYearType, default: 252
176
173
  Number of trading days used to annualize
174
+ seed: int, optional
175
+ Seed for random process initiation
177
176
  randomizer: numpy.random.Generator, optional
178
177
  Random process generator
179
178
 
@@ -209,8 +208,8 @@ class ReturnSimulation(BaseModel):
209
208
  mean_annual_return: float,
210
209
  mean_annual_vol: PositiveFloat,
211
210
  trading_days: PositiveInt,
212
- seed: int,
213
211
  trading_days_in_year: DaysInYearType = 252,
212
+ seed: int | None = None,
214
213
  randomizer: Generator | None = None,
215
214
  ) -> ReturnSimulation:
216
215
  """Create a Lognormal distribution simulation.
@@ -225,11 +224,10 @@ class ReturnSimulation(BaseModel):
225
224
  Mean return
226
225
  mean_annual_vol: PositiveFloat
227
226
  Mean standard deviation
228
- seed: int
229
- Seed for random process initiation
230
- trading_days_in_year: DaysInYearType,
231
- default: 252
227
+ trading_days_in_year: DaysInYearType, default: 252
232
228
  Number of trading days used to annualize
229
+ seed: int, optional
230
+ Seed for random process initiation
233
231
  randomizer: numpy.random.Generator, optional
234
232
  Random process generator
235
233
 
@@ -268,8 +266,8 @@ class ReturnSimulation(BaseModel):
268
266
  mean_annual_return: float,
269
267
  mean_annual_vol: PositiveFloat,
270
268
  trading_days: PositiveInt,
271
- seed: int,
272
269
  trading_days_in_year: DaysInYearType = 252,
270
+ seed: int | None = None,
273
271
  randomizer: Generator | None = None,
274
272
  ) -> ReturnSimulation:
275
273
  """Create a Geometric Brownian Motion simulation.
@@ -284,10 +282,10 @@ class ReturnSimulation(BaseModel):
284
282
  Mean return
285
283
  mean_annual_vol: PositiveFloat
286
284
  Mean standard deviation
287
- seed: int
288
- Seed for random process initiation
289
285
  trading_days_in_year: DaysInYearType, default: 252
290
286
  Number of trading days used to annualize
287
+ seed: int, optional
288
+ Seed for random process initiation
291
289
  randomizer: numpy.random.Generator, optional
292
290
  Random process generator
293
291
 
@@ -330,11 +328,11 @@ class ReturnSimulation(BaseModel):
330
328
  trading_days: PositiveInt,
331
329
  mean_annual_return: float,
332
330
  mean_annual_vol: PositiveFloat,
333
- seed: int,
334
331
  jumps_lamda: NonNegativeFloat,
335
332
  jumps_sigma: NonNegativeFloat = 0.0,
336
333
  jumps_mu: float = 0.0,
337
334
  trading_days_in_year: DaysInYearType = 252,
335
+ seed: int | None = None,
338
336
  randomizer: Generator | None = None,
339
337
  ) -> ReturnSimulation:
340
338
  """Create a Merton Jump-Diffusion model simulation.
@@ -349,8 +347,6 @@ class ReturnSimulation(BaseModel):
349
347
  Mean return
350
348
  mean_annual_vol: PositiveFloat
351
349
  Mean standard deviation
352
- seed: int
353
- Seed for random process initiation
354
350
  jumps_lamda: NonNegativeFloat
355
351
  This is the probability of a jump happening at each point in time
356
352
  jumps_sigma: NonNegativeFloat, default: 0.0
@@ -359,6 +355,8 @@ class ReturnSimulation(BaseModel):
359
355
  This is the average jump size
360
356
  trading_days_in_year: DaysInYearType, default: 252
361
357
  Number of trading days used to annualize
358
+ seed: int, optional
359
+ Seed for random process initiation
362
360
  randomizer: numpy.random.Generator, optional
363
361
  Random process generator
364
362
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openseries
3
- Version: 1.7.0
3
+ Version: 1.7.1
4
4
  Summary: Tools for analyzing financial timeseries.
5
5
  Home-page: https://github.com/CaptorAB/openseries
6
6
  License: BSD-3-Clause
@@ -0,0 +1,16 @@
1
+ openseries/__init__.py,sha256=gD2dMKRTJ9HMXLca_5sR67xGiU5sWExwaNUi-9N_RGQ,1032
2
+ openseries/_common_model.py,sha256=qa0MejnuLcLszaeF9IGbrRycv94O3Xf1rBnAjASI-M4,73805
3
+ openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
4
+ openseries/datefixer.py,sha256=Gj9r8xXGm0jcWiDlC0IR0mN64vceaZAnXrei-sXcuqE,12345
5
+ openseries/frame.py,sha256=rl0MNUWrQMffS1beNQWzyLHwuLO9AL_9DI_chUoQweA,55466
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=0H3IKq3kA2nol-NJcbytIflC3cVMde7xWWzh4ebQkyM,18961
10
+ openseries/series.py,sha256=Jn_2NEYGUGrdWhP-Nm3LBA041FzFClqTvmWg6eHhG7E,27882
11
+ openseries/simulation.py,sha256=P5nkX7o3O_3pOL22MAZTqL_i4TB2IUmPGCodegsAM04,13932
12
+ openseries/types.py,sha256=KoqDGI-DOJGP3zPzhx0an7IGIttWG0zYw-VJqolc1xA,7908
13
+ openseries-1.7.1.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
14
+ openseries-1.7.1.dist-info/METADATA,sha256=sDuycWQUg_jmcAv9LY4uTuZp97rnSIjgfg0gz9Epnis,44166
15
+ openseries-1.7.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
16
+ openseries-1.7.1.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- openseries/__init__.py,sha256=k2r-yXfmxqBT7_voQ-4HL5dBxfkQIItsm-o77ot3aDQ,1116
2
- openseries/_common_model.py,sha256=smkqaErhDGbcihsqzFeF7tbwstlmlkgcPF2C1KaaGbU,74369
3
- openseries/_risk.py,sha256=PReIfkzhInvIgJkzI4k1wYvhmLZ4cCurYKuQAvlHLlE,2082
4
- openseries/datefixer.py,sha256=CFsZfooXIl2q7w8x8O2xRwfmQP67offwbWEaNYpEJGU,12778
5
- openseries/frame.py,sha256=6u5UGLSVyaBC3YdB84mF3iBSw70Gwnrk4iBQiNeJppg,55580
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=asD8n8m8roEN0SuJK_LoLc5OnTcPmFVl64598dG2sUQ,18749
10
- openseries/series.py,sha256=WqDSGOEBFuVQkfdrysXS4PBi2B7HFT-v9f41vt9JaSA,27984
11
- openseries/simulation.py,sha256=QpeEC2nsG3DAqd51spAccrYWhUbsFWfCyyCkrjCMd7Y,13860
12
- openseries/types.py,sha256=KoqDGI-DOJGP3zPzhx0an7IGIttWG0zYw-VJqolc1xA,7908
13
- openseries-1.7.0.dist-info/LICENSE.md,sha256=IQ8_IMXgHxyv4M48G14fJsjcrkiSASdalASTXWCOsj4,1515
14
- openseries-1.7.0.dist-info/METADATA,sha256=G82OxH9BK1fRJVI45Lr-PNu_hbHKmdo1uKnZZa8JIx0,44166
15
- openseries-1.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
16
- openseries-1.7.0.dist-info/RECORD,,