AnomalyLab 0.2.7__tar.gz → 0.2.8__tar.gz

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.
Files changed (50) hide show
  1. {anomalylab-0.2.7 → anomalylab-0.2.8/AnomalyLab.egg-info}/PKG-INFO +1 -1
  2. {anomalylab-0.2.7 → anomalylab-0.2.8}/AnomalyLab.egg-info/SOURCES.txt +1 -0
  3. {anomalylab-0.2.7/AnomalyLab.egg-info → anomalylab-0.2.8}/PKG-INFO +1 -1
  4. anomalylab-0.2.8/anomalylab/config.py +1 -0
  5. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/core/core.py +12 -3
  6. anomalylab-0.2.8/anomalylab/empirical/factor_return.py +43 -0
  7. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/fm_regression.py +0 -1
  8. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/portfolio.py +12 -4
  9. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/visualization/format.py +46 -10
  10. {anomalylab-0.2.7 → anomalylab-0.2.8}/setup.py +1 -1
  11. anomalylab-0.2.7/anomalylab/config.py +0 -11
  12. {anomalylab-0.2.7 → anomalylab-0.2.8}/.gitattributes +0 -0
  13. {anomalylab-0.2.7 → anomalylab-0.2.8}/.github/workflows/python-publish.yml +0 -0
  14. {anomalylab-0.2.7 → anomalylab-0.2.8}/.gitignore +0 -0
  15. {anomalylab-0.2.7 → anomalylab-0.2.8}/AnomalyLab.egg-info/dependency_links.txt +0 -0
  16. {anomalylab-0.2.7 → anomalylab-0.2.8}/AnomalyLab.egg-info/requires.txt +0 -0
  17. {anomalylab-0.2.7 → anomalylab-0.2.8}/AnomalyLab.egg-info/top_level.txt +0 -0
  18. {anomalylab-0.2.7 → anomalylab-0.2.8}/LICENSE +0 -0
  19. {anomalylab-0.2.7 → anomalylab-0.2.8}/MANIFEST.in +0 -0
  20. {anomalylab-0.2.7 → anomalylab-0.2.8}/README.md +0 -0
  21. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/__init__.py +0 -0
  22. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/core/__init__.py +0 -0
  23. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/datasets/__init__.py +0 -0
  24. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/datasets/dataset.py +0 -0
  25. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/datasets/panel_data.csv +0 -0
  26. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/datasets/time_series_data.csv +0 -0
  27. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/datasets/transition_matrix.png +0 -0
  28. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/__init__.py +0 -0
  29. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/correlation.py +0 -0
  30. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/empirical.py +0 -0
  31. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/persistence.py +0 -0
  32. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/empirical/summary.py +0 -0
  33. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/__init__.py +0 -0
  34. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/fillna.py +0 -0
  35. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/normalize.py +0 -0
  36. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/outliers.py +0 -0
  37. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/preprocessor.py +0 -0
  38. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/shift.py +0 -0
  39. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/preprocess/truncate.py +0 -0
  40. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/structure/__init__.py +0 -0
  41. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/structure/data.py +0 -0
  42. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/structure/panel_data.py +0 -0
  43. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/structure/time_series.py +0 -0
  44. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/utils/__init__.py +0 -0
  45. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/utils/imports.py +0 -0
  46. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/utils/utils.py +0 -0
  47. {anomalylab-0.2.7 → anomalylab-0.2.8}/anomalylab/visualization/__init__.py +0 -0
  48. {anomalylab-0.2.7 → anomalylab-0.2.8}/requirements.txt +0 -0
  49. {anomalylab-0.2.7 → anomalylab-0.2.8}/setup.cfg +0 -0
  50. {anomalylab-0.2.7 → anomalylab-0.2.8}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AnomalyLab
3
- Version: 0.2.7
3
+ Version: 0.2.8
4
4
  Summary: A Python package for empirical asset pricing analysis.
5
5
  Author: FinPhd
6
6
  Classifier: Programming Language :: Python :: 3
@@ -23,6 +23,7 @@ anomalylab/datasets/transition_matrix.png
23
23
  anomalylab/empirical/__init__.py
24
24
  anomalylab/empirical/correlation.py
25
25
  anomalylab/empirical/empirical.py
26
+ anomalylab/empirical/factor_return.py
26
27
  anomalylab/empirical/fm_regression.py
27
28
  anomalylab/empirical/persistence.py
28
29
  anomalylab/empirical/portfolio.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AnomalyLab
3
- Version: 0.2.7
3
+ Version: 0.2.8
4
4
  Summary: A Python package for empirical asset pricing analysis.
5
5
  Author: FinPhd
6
6
  Classifier: Programming Language :: Python :: 3
@@ -0,0 +1 @@
1
+ DECIMAL = 2
@@ -280,6 +280,7 @@ class Panel:
280
280
  factors_series: Optional[TimeSeries] = None,
281
281
  format: bool = False,
282
282
  decimal: Optional[int] = None,
283
+ factor_return: bool = False,
283
284
  ) -> tuple:
284
285
  return self.portfolio_analysis_processor(
285
286
  endog=endog, weight=weight, models=models, factors_series=factors_series
@@ -288,6 +289,7 @@ class Panel:
288
289
  core_g=core_g,
289
290
  format=format,
290
291
  decimal=decimal,
292
+ factor_return=factor_return,
291
293
  )
292
294
 
293
295
  def bivariate_analysis(
@@ -304,6 +306,7 @@ class Panel:
304
306
  format: bool = False,
305
307
  type: str = "dependent",
306
308
  decimal: Optional[int] = None,
309
+ factor_return: bool = False,
307
310
  ) -> tuple:
308
311
  return self.portfolio_analysis_processor(
309
312
  endog=endog, weight=weight, models=models, factors_series=factors_series
@@ -316,6 +319,7 @@ class Panel:
316
319
  format=format,
317
320
  type=type,
318
321
  decimal=decimal,
322
+ factor_return=factor_return,
319
323
  )
320
324
 
321
325
  def fm_reg(
@@ -348,8 +352,12 @@ class Panel:
348
352
  return_intermediate=return_intermediate,
349
353
  )
350
354
 
351
- def format_excel(self, path: str) -> None:
352
- self.format_preprocessor(path=path).process()
355
+ def format_excel(
356
+ self, path: str, align=True, line=True, convert_brackets=False
357
+ ) -> None:
358
+ self.format_preprocessor(path=path).process(
359
+ align=align, line=line, convert_brackets=convert_brackets
360
+ )
353
361
 
354
362
 
355
363
  if __name__ == "__main__":
@@ -402,7 +410,7 @@ if __name__ == "__main__":
402
410
  )
403
411
  )
404
412
  uni_ew, uni_vw = panel.univariate_analysis(
405
- "return", "MktCap", "Illiq", 10, Models, time_series
413
+ "return", "MktCap", "Illiq", 10, Models, time_series, factor_return=True
406
414
  )
407
415
  pp(uni_ew)
408
416
  pp(uni_vw)
@@ -419,6 +427,7 @@ if __name__ == "__main__":
419
427
  True,
420
428
  False,
421
429
  "dependent",
430
+ factor_return=True,
422
431
  )
423
432
  pp(bi_ew)
424
433
  pp(bi_vw)
@@ -0,0 +1,43 @@
1
+ from pandas.core.frame import DataFrame
2
+
3
+ from anomalylab.config import *
4
+ from anomalylab.empirical.empirical import Empirical
5
+ from anomalylab.empirical.portfolio import PortfolioAnalysis
6
+ from anomalylab.structure import PanelData, TimeSeries
7
+ from anomalylab.utils.imports import *
8
+ from anomalylab.utils.utils import *
9
+
10
+ if __name__ == "__main__":
11
+ from anomalylab.datasets import DataSet
12
+
13
+ df: DataFrame = DataSet.get_panel_data()
14
+ ts: DataFrame = DataSet.get_time_series_data()
15
+ Models: dict[str, list[str]] = {
16
+ "CAPM": ["MKT(3F)"],
17
+ "FF3": ["MKT(3F)", "SMB(3F)", "HML(3F)"],
18
+ "FF5": ["MKT(5F)", "SMB(5F)", "HML(5F)", "RMW(5F)", "CMA(5F)"],
19
+ }
20
+
21
+ panel: PanelData = PanelData(df=df, name="Stocks", classifications="industry")
22
+ time_series: TimeSeries = TimeSeries(df=ts, name="Factor Series")
23
+
24
+ portfolio = PortfolioAnalysis(
25
+ panel,
26
+ endog="return",
27
+ weight="MktCap",
28
+ # models=Models,
29
+ # factors_series=time_series,
30
+ )
31
+
32
+ group = portfolio.GroupN(["MktCap", "Illiq", "IdioVol"], [3, 3, 3])
33
+ pp(group)
34
+
35
+ # uni_ew, uni_vw = portfolio.univariate_analysis("Illiq", 10)
36
+ # pp(uni_ew)
37
+ # pp(uni_vw)
38
+
39
+ # bi_ew, bi_vw = portfolio.bivariate_analysis(
40
+ # "Illiq", "IdioVol", 10, 10, True, False, "dependent"
41
+ # )
42
+ # pp(bi_ew)
43
+ # pp(bi_vw)
@@ -4,7 +4,6 @@ from anomalylab.preprocess import OutlierHandler
4
4
  from anomalylab.structure import PanelData
5
5
  from anomalylab.utils.imports import *
6
6
  from anomalylab.utils.utils import *
7
- from anomalylab.utils.utils import RegModels, RegResult
8
7
 
9
8
 
10
9
  @dataclass
@@ -267,6 +267,7 @@ class PortfolioAnalysis(Empirical):
267
267
  core_g: int,
268
268
  format: bool = False,
269
269
  decimal: Optional[int] = None,
270
+ factor_return: bool = False,
270
271
  ) -> tuple:
271
272
  """Perform univariate analysis on the specified core variable.
272
273
 
@@ -332,6 +333,9 @@ class PortfolioAnalysis(Empirical):
332
333
  .reset_index(level=0, drop=True)
333
334
  )
334
335
 
336
+ if factor_return:
337
+ return ew_ret_d, vw_ret_d
338
+
335
339
  def generate_time_series_dict(series: Series) -> dict:
336
340
  """Generate a dictionary of time series data from the DataFrame.
337
341
 
@@ -422,6 +426,7 @@ class PortfolioAnalysis(Empirical):
422
426
  format: bool = False,
423
427
  type: str = "dependent",
424
428
  decimal: Optional[int] = None,
429
+ factor_return: bool = False,
425
430
  ) -> tuple:
426
431
  """Perform bivariate analysis on two specified variables.
427
432
 
@@ -519,6 +524,9 @@ class PortfolioAnalysis(Empirical):
519
524
  .reset_index(level=0, drop=True)
520
525
  )
521
526
 
527
+ if factor_return:
528
+ return ew_ret_d, vw_ret_d
529
+
522
530
  def generate_time_series_dict(df: pd.DataFrame) -> dict:
523
531
  """Generate a dictionary of time series data from the DataFrame.
524
532
 
@@ -677,19 +685,19 @@ if __name__ == "__main__":
677
685
  panel,
678
686
  endog="return",
679
687
  weight="MktCap",
680
- # models=Models,
681
- # factors_series=time_series,
688
+ models=Models,
689
+ factors_series=time_series,
682
690
  )
683
691
 
684
692
  group = portfolio.GroupN("Illiq", 10)
685
693
  pp(group)
686
694
 
687
- uni_ew, uni_vw = portfolio.univariate_analysis("Illiq", 10)
695
+ uni_ew, uni_vw = portfolio.univariate_analysis("Illiq", 10, factor_return=False)
688
696
  pp(uni_ew)
689
697
  pp(uni_vw)
690
698
 
691
699
  bi_ew, bi_vw = portfolio.bivariate_analysis(
692
- "Illiq", "IdioVol", 10, 10, True, False, "dependent"
700
+ "Illiq", "IdioVol", 10, 10, False, False, "dependent", factor_return=False
693
701
  )
694
702
  pp(bi_ew)
695
703
  pp(bi_vw)
@@ -60,30 +60,66 @@ class FormatExcel:
60
60
  for cell in ws[max_row]:
61
61
  cell.border = Border(bottom=thin)
62
62
 
63
+ def convert_brackets(self, direction="to_square"):
64
+ """Converts parentheses () to square brackets [] and vice versa in the Excel cells.
65
+
66
+ This method goes through all the cells in the workbook and:
67
+ - Converts () to [] if direction is 'to_square'.
68
+ - Converts [] to () if direction is 'to_round'.
69
+
70
+ Args:
71
+ direction (str): Direction of the bracket conversion.
72
+ - 'to_square' for converting () to [].
73
+ - 'to_round' for converting [] to ().
74
+ Default is 'to_square'.
75
+ """
76
+ # Validate the direction parameter
77
+ if direction not in ["to_square", "to_round"]:
78
+ raise ValueError(
79
+ "Invalid direction. Choose either 'to_square' or 'to_round'."
80
+ )
81
+
82
+ for ws in self.wb.worksheets:
83
+ for row in ws.iter_rows(
84
+ min_row=1, max_row=ws.max_row, min_col=1, max_col=ws.max_column
85
+ ):
86
+ for cell in row:
87
+ if isinstance(
88
+ cell.value, str
89
+ ): # Check if the cell contains a string
90
+ if direction == "to_square":
91
+ cell.value = cell.value.replace("(", "[").replace(")", "]")
92
+ elif direction == "to_round":
93
+ cell.value = cell.value.replace("[", "(").replace("]", ")")
94
+
63
95
  def save(self):
64
96
  """Saves the currently loaded workbook to its file path."""
65
97
  self.wb.save(self.file_path)
66
98
 
67
- def process(self):
99
+ def process(self, align=True, line=True, convert_brackets=False):
68
100
  """Processes and formats Excel files.
69
101
 
70
102
  - If the provided path is a directory, it formats all Excel files in that directory.
71
103
  - If the provided path is a file, it formats that specific Excel file.
72
104
  """
73
- if os.path.isdir(self.path):
74
- for file in glob(os.path.join(self.path, "*.xlsx")):
75
- self.load_workbook(file)
105
+ files_to_process = (
106
+ glob(os.path.join(self.path, "*.xlsx"))
107
+ if os.path.isdir(self.path)
108
+ else [self.path]
109
+ )
110
+
111
+ for file in files_to_process:
112
+ self.load_workbook(file)
113
+ if align:
76
114
  self.align()
115
+ if line:
77
116
  self.line()
78
- self.save()
79
- else:
80
- self.load_workbook(self.path)
81
- self.align()
82
- self.line()
117
+ if convert_brackets:
118
+ self.convert_brackets()
83
119
  self.save()
84
120
 
85
121
 
86
122
  if __name__ == "__main__":
87
123
  path = "..."
88
124
  excel_formatter = FormatExcel(path)
89
- excel_formatter.process()
125
+ excel_formatter.process(convert_brackets=True)
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
2
2
 
3
3
  setup(
4
4
  name="AnomalyLab",
5
- version="0.2.7",
5
+ version="0.2.8",
6
6
  author="FinPhd",
7
7
  # author_email="your.email@example.com",
8
8
  description="A Python package for empirical asset pricing analysis.",
@@ -1,11 +0,0 @@
1
- # CLASSIFICATIONS: list[str] = ["industry"]
2
-
3
-
4
- DECIMAL = 2
5
-
6
-
7
- # SIGNIFICANCE = {
8
- # (0, 0.01): "***",
9
- # (0.01, 0.05): "**",
10
- # (0.05, 0.1): "*",
11
- # }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes