AnomalyLab 0.2.5__tar.gz → 0.2.7__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 (48) hide show
  1. {anomalylab-0.2.5 → anomalylab-0.2.7/AnomalyLab.egg-info}/PKG-INFO +1 -1
  2. {anomalylab-0.2.5/AnomalyLab.egg-info → anomalylab-0.2.7}/PKG-INFO +1 -1
  3. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/core/core.py +6 -4
  4. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/fm_regression.py +74 -19
  5. {anomalylab-0.2.5 → anomalylab-0.2.7}/setup.py +1 -1
  6. {anomalylab-0.2.5 → anomalylab-0.2.7}/.gitattributes +0 -0
  7. {anomalylab-0.2.5 → anomalylab-0.2.7}/.github/workflows/python-publish.yml +0 -0
  8. {anomalylab-0.2.5 → anomalylab-0.2.7}/.gitignore +0 -0
  9. {anomalylab-0.2.5 → anomalylab-0.2.7}/AnomalyLab.egg-info/SOURCES.txt +0 -0
  10. {anomalylab-0.2.5 → anomalylab-0.2.7}/AnomalyLab.egg-info/dependency_links.txt +0 -0
  11. {anomalylab-0.2.5 → anomalylab-0.2.7}/AnomalyLab.egg-info/requires.txt +0 -0
  12. {anomalylab-0.2.5 → anomalylab-0.2.7}/AnomalyLab.egg-info/top_level.txt +0 -0
  13. {anomalylab-0.2.5 → anomalylab-0.2.7}/LICENSE +0 -0
  14. {anomalylab-0.2.5 → anomalylab-0.2.7}/MANIFEST.in +0 -0
  15. {anomalylab-0.2.5 → anomalylab-0.2.7}/README.md +0 -0
  16. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/__init__.py +0 -0
  17. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/config.py +0 -0
  18. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/core/__init__.py +0 -0
  19. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/datasets/__init__.py +0 -0
  20. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/datasets/dataset.py +0 -0
  21. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/datasets/panel_data.csv +0 -0
  22. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/datasets/time_series_data.csv +0 -0
  23. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/datasets/transition_matrix.png +0 -0
  24. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/__init__.py +0 -0
  25. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/correlation.py +0 -0
  26. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/empirical.py +0 -0
  27. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/persistence.py +0 -0
  28. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/portfolio.py +0 -0
  29. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/empirical/summary.py +0 -0
  30. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/__init__.py +0 -0
  31. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/fillna.py +0 -0
  32. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/normalize.py +0 -0
  33. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/outliers.py +0 -0
  34. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/preprocessor.py +0 -0
  35. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/shift.py +0 -0
  36. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/preprocess/truncate.py +0 -0
  37. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/structure/__init__.py +0 -0
  38. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/structure/data.py +0 -0
  39. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/structure/panel_data.py +0 -0
  40. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/structure/time_series.py +0 -0
  41. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/utils/__init__.py +0 -0
  42. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/utils/imports.py +0 -0
  43. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/utils/utils.py +0 -0
  44. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/visualization/__init__.py +0 -0
  45. {anomalylab-0.2.5 → anomalylab-0.2.7}/anomalylab/visualization/format.py +0 -0
  46. {anomalylab-0.2.5 → anomalylab-0.2.7}/requirements.txt +0 -0
  47. {anomalylab-0.2.5 → anomalylab-0.2.7}/setup.cfg +0 -0
  48. {anomalylab-0.2.5 → anomalylab-0.2.7}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AnomalyLab
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: A Python package for empirical asset pricing analysis.
5
5
  Author: FinPhd
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AnomalyLab
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: A Python package for empirical asset pricing analysis.
5
5
  Author: FinPhd
6
6
  Classifier: Programming Language :: Python :: 3
@@ -19,7 +19,7 @@ from anomalylab.visualization import FormatExcel
19
19
 
20
20
  @dataclass
21
21
  class Panel:
22
- df: DataFrame
22
+ _df: pd.DataFrame = field(repr=False)
23
23
  name: Optional[str] = None
24
24
  id: str = "permno"
25
25
  time: str = "date"
@@ -30,7 +30,7 @@ class Panel:
30
30
 
31
31
  def __post_init__(self) -> None:
32
32
  self.panel_data: PanelData = PanelData(
33
- df=self.df,
33
+ df=self._df,
34
34
  name=self.name,
35
35
  id=self.id,
36
36
  time=self.time,
@@ -54,9 +54,9 @@ class Panel:
54
54
  return repr(self.panel_data)
55
55
 
56
56
  def get_original_data(self) -> DataFrame:
57
- return self.df
57
+ return self._df
58
58
 
59
- def get_data(self) -> DataFrame:
59
+ def get_processed_data(self) -> DataFrame:
60
60
  return self.panel_data.df
61
61
 
62
62
  @property
@@ -331,6 +331,7 @@ class Panel:
331
331
  is_winsorize: bool = False,
332
332
  is_normalize: bool = False,
333
333
  decimal: Optional[int] = None,
334
+ return_intermediate: bool = False,
334
335
  ) -> DataFrame:
335
336
  return self.fm_preprocessor.fit(
336
337
  endog=endog,
@@ -344,6 +345,7 @@ class Panel:
344
345
  is_winsorize=is_winsorize,
345
346
  is_normalize=is_normalize,
346
347
  decimal=decimal,
348
+ return_intermediate=return_intermediate,
347
349
  )
348
350
 
349
351
  def format_excel(self, path: str) -> None:
@@ -11,12 +11,12 @@ from anomalylab.utils.utils import RegModels, RegResult
11
11
  class FamaMacBethRegression(Empirical):
12
12
  """Class for performing Fama-MacBeth regression analysis.
13
13
 
14
- Inherits from the Empirical class and provides methods for
15
- winsorizing, calculating industry-weighted returns, fitting
16
- the regression model, and formatting the output results.
14
+ This class inherits from the Empirical class and provides methods to
15
+ winsorize data, calculate industry-weighted returns, fit the Fama-MacBeth
16
+ regression model, and format the output results.
17
17
 
18
18
  Attributes:
19
- temp_panel (PanelData): Temporary panel data used for analysis.
19
+ panel_data (PanelData): Panel data used for analysis.
20
20
  """
21
21
 
22
22
  def _winsorize(self, is_winsorize: bool, exog: list[str]):
@@ -38,7 +38,8 @@ class FamaMacBethRegression(Empirical):
38
38
  OutlierHandler(panel_data=self.panel_data)
39
39
  .winsorize(
40
40
  columns=exog,
41
- process_all_characteristics=False,
41
+ method="winsorize",
42
+ group_columns=self.panel_data.time,
42
43
  )
43
44
  .panel_data
44
45
  )
@@ -52,6 +53,9 @@ class FamaMacBethRegression(Empirical):
52
53
  ) -> None:
53
54
  """Calculates industry-weighted returns for the specified endogenous variables.
54
55
 
56
+ This method adjusts the endogenous variables by industry-specific returns,
57
+ either using equal weights or value weights (based on the 'industry_weighed_method').
58
+
55
59
  Args:
56
60
  endog (list[str]): List of endogenous variable names to adjust.
57
61
  industry (Optional[str]): The industry column to group by.
@@ -89,9 +93,14 @@ class FamaMacBethRegression(Empirical):
89
93
  df: DataFrame,
90
94
  reg: RegModel,
91
95
  is_normalize: bool,
96
+ return_intermediate: bool = False,
92
97
  ) -> RegResult:
93
98
  """Performs Fama-MacBeth regression on the provided DataFrame.
94
99
 
100
+ This method runs the Fama-MacBeth two-step regression on a given dataset.
101
+ It can optionally normalize the exogenous variables and return intermediate
102
+ results for each time period.
103
+
95
104
  Args:
96
105
  df (DataFrame): DataFrame containing the data for regression.
97
106
  reg (RegModel): Model specification containing endogenous and exogenous variables.
@@ -112,6 +121,23 @@ class FamaMacBethRegression(Empirical):
112
121
  )
113
122
  df[self.time] = df[self.time].dt.to_timestamp()
114
123
  df = df.set_index([self.id, self.time])
124
+
125
+ if return_intermediate:
126
+ coef_df = []
127
+ for time, group in df.groupby(self.time):
128
+ y = group[dependent]
129
+ X = sm.add_constant(group[exogenous]) # Add constant term
130
+ model = sm.OLS(y, X)
131
+ results = model.fit()
132
+ coefs = results.params
133
+ coefs[self.time] = time
134
+ coef_df.append(coefs)
135
+ coef_df = pd.DataFrame(coef_df)
136
+ coef_df = coef_df[
137
+ [self.time] + [col for col in coef_df.columns if col != self.time]
138
+ ]
139
+ return pd.DataFrame(coef_df)
140
+
115
141
  # Fama-MacBeth regression with Newey-West adjustment
116
142
  fmb = FamaMacBeth(
117
143
  dependent=df[dependent],
@@ -141,6 +167,9 @@ class FamaMacBethRegression(Empirical):
141
167
  def _cal_adjusted_r2(self, group, dependent: str, exogenous: list[str]):
142
168
  """Calculates the adjusted R² for the given group of data.
143
169
 
170
+ This method fits an OLS model to the provided group of data and computes
171
+ the adjusted R².
172
+
144
173
  Args:
145
174
  group: DataFrame group to fit the OLS model.
146
175
  dependent (str): Name of the dependent variable.
@@ -168,6 +197,9 @@ class FamaMacBethRegression(Empirical):
168
197
  ) -> Series:
169
198
  """Formats the regression results into a Pandas Series.
170
199
 
200
+ This method prepares the output of the regression results, rounding values
201
+ to the specified decimal places and adding significance stars.
202
+
171
203
  Args:
172
204
  reg_result (RegResult): Results of the regression.
173
205
  decimal (int): Number of decimal places for rounding.
@@ -202,6 +234,9 @@ class FamaMacBethRegression(Empirical):
202
234
  ) -> RegModels:
203
235
  """Parses the model specifications into a RegModels object.
204
236
 
237
+ This method parses the model specifications and converts them into a `RegModels` object.
238
+ It supports input in multiple formats, including lists and dictionaries.
239
+
205
240
  Args:
206
241
  regs (Optional[list[list[str] | dict[str, list[str]]] | list | dict]): Model specifications.
207
242
  endog (Optional[str]): Name of the dependent variable.
@@ -244,8 +279,13 @@ class FamaMacBethRegression(Empirical):
244
279
  is_winsorize: bool = False,
245
280
  is_normalize: bool = False,
246
281
  decimal: Optional[int] = None,
282
+ return_intermediate: bool = False, # New parameter to control whether intermediate results are returned
247
283
  ) -> DataFrame:
248
- """Fits the Fama-MacBeth regression model and returns the results DataFrame.
284
+ """Fits the Fama-MacBeth regression model and returns the results DataFrame or intermediate results.
285
+
286
+ This method fits the Fama-MacBeth regression model, processes data
287
+ (including winsorization, industry weighting, normalization), and
288
+ returns either the final regression results or intermediate results.
249
289
 
250
290
  Args:
251
291
  endog (Optional[str]): Name of the dependent variable.
@@ -259,12 +299,12 @@ class FamaMacBethRegression(Empirical):
259
299
  is_winsorize (bool): Indicates whether to apply winsorization.
260
300
  is_normalize (bool): Indicates whether to normalize exogenous variables.
261
301
  decimal (Optional[int]): Number of decimal places for rounding in output.
302
+ return_intermediate (bool): If True, returns the intermediate results (e.g., coefficients for each time period).
262
303
 
263
304
  Returns:
264
- DataFrame: DataFrame containing the regression results including parameters, t-values, and other statistics.
305
+ DataFrame: DataFrame containing the regression results or intermediate results based on `return_intermediate`.
265
306
  """
266
307
  # Preparation
267
- # self.temp_panel: PanelData = self.panel_data.copy()
268
308
  reg_models: RegModels = self._model_parse(
269
309
  regs=regs, endog=endog, exog=columns_to_list(exog)
270
310
  )
@@ -276,6 +316,19 @@ class FamaMacBethRegression(Empirical):
276
316
  weight=weight,
277
317
  )
278
318
  exog_order = (exog_order or reg_models.exogenous) + ["const"]
319
+
320
+ if return_intermediate:
321
+ intermediate_results = [
322
+ self._reg(
323
+ df=self.panel_data.df,
324
+ reg=model,
325
+ is_normalize=is_normalize,
326
+ return_intermediate=True,
327
+ )
328
+ for model in reg_models.models
329
+ ]
330
+ return intermediate_results
331
+
279
332
  # Regression
280
333
  df: DataFrame = (
281
334
  pd.concat(
@@ -315,13 +368,13 @@ if __name__ == "__main__":
315
368
  result = fm.fit(
316
369
  # endog="return",
317
370
  # exog="MktCap",
318
- exog_order=["MktCap"],
371
+ # exog_order=["MktCap", "Illiq", "IdioVol"],
319
372
  regs=[
320
- "return",
321
- "MktCap",
322
- # ["return", "Illiq"],
323
- # ["return", "IdioVol"],
324
- # ["return", "MktCap", "Illiq", "IdioVol"],
373
+ # "return",
374
+ # "MktCap",
375
+ ["return", "Illiq"],
376
+ ["return", "IdioVol"],
377
+ ["return", "MktCap", "Illiq", "IdioVol"],
325
378
  ],
326
379
  # models=[
327
380
  # {"return": ["MktCap"]},
@@ -329,11 +382,13 @@ if __name__ == "__main__":
329
382
  # {"return": ["IdioVol"]},
330
383
  # {"return": ["MktCap", "Illiq", "IdioVol"]},
331
384
  # ],
332
- industry="industry",
333
- industry_weighed_method="value",
334
- weight="MktCap",
335
- # is_winsorize=True,
385
+ # industry="industry",
386
+ # industry_weighed_method="value",
387
+ # weight="MktCap",
388
+ is_winsorize=True,
336
389
  is_normalize=True,
390
+ return_intermediate=True,
337
391
  # decimal=2,
338
392
  )
339
- pp(object=result)
393
+ pp(result)
394
+ pp(result[0])
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
2
2
 
3
3
  setup(
4
4
  name="AnomalyLab",
5
- version="0.2.5",
5
+ version="0.2.7",
6
6
  author="FinPhd",
7
7
  # author_email="your.email@example.com",
8
8
  description="A Python package for empirical asset pricing analysis.",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes