sovai 0.2.30__tar.gz → 0.2.31__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 (95) hide show
  1. {sovai-0.2.30 → sovai-0.2.31}/PKG-INFO +1 -1
  2. {sovai-0.2.30 → sovai-0.2.31}/pyproject.toml +1 -1
  3. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/pandas_extensions.py +80 -1
  4. {sovai-0.2.30 → sovai-0.2.31}/sovai/get_plots.py +1 -0
  5. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/earnings_surprise/earnings_surprise_plots.py +70 -0
  6. {sovai-0.2.30 → sovai-0.2.31}/LICENSE +0 -0
  7. {sovai-0.2.30 → sovai-0.2.31}/README.md +0 -0
  8. {sovai-0.2.30 → sovai-0.2.31}/sovai/__init__.py +0 -0
  9. {sovai-0.2.30 → sovai-0.2.31}/sovai/api_config.py +0 -0
  10. {sovai-0.2.30 → sovai-0.2.31}/sovai/assets/dropdown.css +0 -0
  11. {sovai-0.2.30 → sovai-0.2.31}/sovai/assets/features_mapping.parq +0 -0
  12. {sovai-0.2.30 → sovai-0.2.31}/sovai/basic_auth.py +0 -0
  13. {sovai-0.2.30 → sovai-0.2.31}/sovai/computations/__init__.py +0 -0
  14. {sovai-0.2.30 → sovai-0.2.31}/sovai/computations/functions.py +0 -0
  15. {sovai-0.2.30 → sovai-0.2.31}/sovai/errors/__init__.py +0 -0
  16. {sovai-0.2.30 → sovai-0.2.31}/sovai/errors/sovai_errors.py +0 -0
  17. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/__init__.py +0 -0
  18. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/anomalies.py +0 -0
  19. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/ask_df_llm.py +0 -0
  20. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/change_point_generator.py +0 -0
  21. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/clustering.py +0 -0
  22. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/core_kshape.py +0 -0
  23. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/cum_sum_torch.py +0 -0
  24. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/cusum.py +0 -0
  25. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/dimensionality_reduction.py +0 -0
  26. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/feature_extraction.py +0 -0
  27. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/feature_importance.py +0 -0
  28. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/feature_neutralizer.py +0 -0
  29. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/filter_df.py +0 -0
  30. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/fractional_differencing.py +0 -0
  31. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/nowcasting.py +0 -0
  32. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/pairwise.py +0 -0
  33. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/parallel_functions.py +0 -0
  34. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/pfa_feature_selector.py +0 -0
  35. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/regime_change.py +0 -0
  36. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/regime_change_pca.py +0 -0
  37. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/shapley_global_importance.py +0 -0
  38. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/shapley_importance.py +0 -0
  39. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/signal_evaluation.py +0 -0
  40. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/technical_indicators.py +0 -0
  41. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/time_decomposition.py +0 -0
  42. {sovai-0.2.30 → sovai-0.2.31}/sovai/extensions/weight_optimization.py +0 -0
  43. {sovai-0.2.30 → sovai-0.2.31}/sovai/get_compute.py +0 -0
  44. {sovai-0.2.30 → sovai-0.2.31}/sovai/get_data.py +0 -0
  45. {sovai-0.2.30 → sovai-0.2.31}/sovai/get_reports.py +0 -0
  46. {sovai-0.2.30 → sovai-0.2.31}/sovai/get_tools.py +0 -0
  47. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/__init__.py +0 -0
  48. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/accounting/__init__.py +0 -0
  49. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/accounting/accounting_plots.py +0 -0
  50. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/allocation/__init__.py +0 -0
  51. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/allocation/allocation_plots.py +0 -0
  52. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/bankruptcy/__init__.py +0 -0
  53. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/bankruptcy/bankruptcy_plots.py +0 -0
  54. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/breakout/__init__.py +0 -0
  55. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/breakout/breakout_plots.py +0 -0
  56. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/corp_risk/__init__.py +0 -0
  57. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/corp_risk/corp_risk_plots.py +0 -0
  58. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/earnings_surprise/__init__.py +0 -0
  59. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/insider/__init__.py +0 -0
  60. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/insider/insider_plots.py +0 -0
  61. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/institutional/__init__.py +0 -0
  62. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/institutional/institutional_plots.py +0 -0
  63. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/news/__init__.py +0 -0
  64. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/news/news_plots.py +0 -0
  65. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/ratios/__init__.py +0 -0
  66. {sovai-0.2.30 → sovai-0.2.31}/sovai/plots/ratios/ratios_plots.py +0 -0
  67. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/accounting/__init__.py +0 -0
  68. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/accounting/accounting_balance_sheet.py +0 -0
  69. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/bankruptcy/__init__.py +0 -0
  70. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/bankruptcy/bankruptcy_monthly_top.py +0 -0
  71. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/general/__init__.py +0 -0
  72. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/general/general_plots.py +0 -0
  73. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/news/__inti__.py +0 -0
  74. {sovai-0.2.30 → sovai-0.2.31}/sovai/reports/news/news_econometric_analysis.py +0 -0
  75. {sovai-0.2.30 → sovai-0.2.31}/sovai/studies/nowcasting.py +0 -0
  76. {sovai-0.2.30 → sovai-0.2.31}/sovai/token_auth.py +0 -0
  77. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/authentication/__init__.py +0 -0
  78. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/authentication/authentication.py +0 -0
  79. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/sec/__init__.py +0 -0
  80. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/sec/graphs.py +0 -0
  81. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/sec/llm_code_generator.py +0 -0
  82. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/sec/sec_10_k_8_k_filings.py +0 -0
  83. {sovai-0.2.30 → sovai-0.2.31}/sovai/tools/sec/sec_edgar_search.py +0 -0
  84. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/__init__.py +0 -0
  85. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/client_side.py +0 -0
  86. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/client_side_s3.py +0 -0
  87. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/converter.py +0 -0
  88. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/datetime_formats.py +0 -0
  89. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/file_management.py +0 -0
  90. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/get_tickers.py +0 -0
  91. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/helpers.py +0 -0
  92. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/pandas_extensions copy.py +0 -0
  93. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/plot.py +0 -0
  94. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/port_manager.py +0 -0
  95. {sovai-0.2.30 → sovai-0.2.31}/sovai/utils/stream.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sovai
3
- Version: 0.2.30
3
+ Version: 0.2.31
4
4
  Summary: python for asset management
5
5
  License: Proprietary License
6
6
  Author: Derek Snow
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "sovai"
3
- version = "0.2.30"
3
+ version = "0.2.31"
4
4
  description = "python for asset management"
5
5
  authors = ["Derek Snow <d.snow@outlook.com>"]
6
6
  license = "Proprietary License"
@@ -101,7 +101,10 @@ import pandas as pd
101
101
  from typing import Union, List
102
102
  from sovai.extensions.ask_df_llm import Ask
103
103
  from sovai.extensions.filter_df import Filter
104
-
104
+ import pandas as pd
105
+ from functools import lru_cache
106
+ import re
107
+ from typing import Union, Tuple
105
108
 
106
109
  class CustomDataFrame(pd.DataFrame):
107
110
  @property
@@ -125,6 +128,82 @@ class CustomDataFrame(pd.DataFrame):
125
128
  filtered_df = Filter.filter(conditions, df_multi=self, verbose=verbose)
126
129
  return CustomDataFrame(filtered_df)
127
130
 
131
+ @staticmethod
132
+ @lru_cache(maxsize=1)
133
+ def _load_combined_df():
134
+ df = pd.read_parquet("https://storage.googleapis.com/sovai-public/concats/filters/latest.parquet")
135
+ # print("Columns in combined DataFrame:", df.columns) # Debug print
136
+ # print("Index name:", df.index.name) # Debug print for index name
137
+ return df
138
+
139
+ def merge_data(self, column: str) -> 'CustomDataFrame':
140
+ """
141
+ Merge the current DataFrame with the combined DataFrame based on ticker and a specified column.
142
+
143
+ :param column: The column from the combined DataFrame to merge.
144
+ :return: A new CustomDataFrame with the merged data.
145
+ """
146
+ # Load the combined DataFrame
147
+ df_combined = self._load_combined_df()
148
+
149
+ # Ensure the specified column exists in the combined DataFrame
150
+ if column not in df_combined.columns:
151
+ raise ValueError(f"Column '{column}' not found in the combined DataFrame.")
152
+
153
+ # Identify the ticker information in the current DataFrame
154
+ ticker_info = self._identify_ticker_info()
155
+
156
+ # Prepare the current DataFrame for merging
157
+ df_to_merge = self.copy()
158
+ if ticker_info[0] != 'column':
159
+ df_to_merge = df_to_merge.reset_index()
160
+
161
+ # Standardize ticker format in the current DataFrame
162
+
163
+ # Prepare the combined DataFrame for merging
164
+ df_combined_merged = df_combined.reset_index()
165
+
166
+ # Perform the merge
167
+ merged_df = pd.merge(df_to_merge, df_combined_merged[['ticker', column]],
168
+ left_on=ticker_info[1], right_on='ticker',
169
+ how='left')
170
+
171
+ # Drop the redundant 'ticker' column from the merge if it's not the original ticker column
172
+ if 'ticker' in merged_df.columns and 'ticker' != ticker_info[1]:
173
+ merged_df = merged_df.drop('ticker', axis=1)
174
+
175
+ # Restore the original index structure
176
+ if ticker_info[0] == 'index':
177
+ merged_df = merged_df.set_index(ticker_info[1])
178
+ elif ticker_info[0] == 'multi_index':
179
+ index_cols = [col for col in df_to_merge.columns if col not in self.columns]
180
+ merged_df = merged_df.set_index(index_cols)
181
+
182
+ return CustomDataFrame(merged_df)
183
+
184
+ def _identify_ticker_info(self) -> Tuple[str, str]:
185
+ """
186
+ Identify the location and name of ticker information in the DataFrame.
187
+
188
+ :return: A tuple of (location, column_name).
189
+ Location can be 'index', 'multi_index', or 'column'.
190
+ """
191
+ # Check if ticker is in the index
192
+ if self.index.name and 'ticker' in self.index.name.lower():
193
+ return ('index', self.index.name)
194
+ elif isinstance(self.index, pd.MultiIndex):
195
+ for name in self.index.names:
196
+ if name and 'ticker' in name.lower():
197
+ return ('multi_index', name)
198
+
199
+ # If ticker is not in the index, check the columns
200
+ for col in self.columns:
201
+ if 'ticker' in col.lower():
202
+ return ('column', col)
203
+
204
+ raise ValueError("Couldn't identify ticker information in the DataFrame.")
205
+
206
+
128
207
  def get_latest(self, column=None):
129
208
  # Your get_latest implementation
130
209
  if isinstance(self.index, pd.MultiIndex) and "date" in self.index.names:
@@ -95,6 +95,7 @@ PLOT_FUNCTION_MAPPER = {
95
95
  ("allocation", "line", "local", True): create_line_plot_allocation,
96
96
  ("allocation", "stacked", "local", True): create_stacked_bar_plot_allocation,
97
97
  ("earnings", "line", "local", True): create_earnings_surprise_plot,
98
+ ("earnings", "tree", "local", True): earnings_tree,
98
99
  ("bankruptcy", "compare", "local", True): plot_bankruptcy_monthly_line,
99
100
  ("bankruptcy", "pca_clusters", "local", True): plot_pca_clusters,
100
101
  ("bankruptcy", "predictions", "local", True): plot_ticker_widget,
@@ -114,3 +114,73 @@ def create_earnings_surprise_plot():
114
114
  return app.run_server(
115
115
  debug=False, port=get_unique_port(app_name)
116
116
  ) # Apply exponential moving average to smooth the data
117
+
118
+
119
+ import plotly.express as px
120
+ import pandas as pd
121
+ import numpy as np
122
+
123
+ def earnings_tree():
124
+ df_earn = data("earnings/surprise")
125
+ df_earn = df_earn.merge_data("market_cap")
126
+ # Ensure 'ticker' is a column, not an index
127
+ if 'ticker' not in df_earn.columns:
128
+ df_earn = df_earn.reset_index()
129
+
130
+ # Calculate market cap deciles and handle NaN values
131
+ df_earn['market_cap_decile'] = pd.qcut(df_earn['market_cap'].rank(method='first'), q=10, labels=range(1, 11))
132
+ df_earn['market_cap_decile'] = df_earn['market_cap_decile'].astype(str).replace('nan', 'Unknown')
133
+
134
+ # Update decile labels
135
+ df_earn['market_cap_decile'] = df_earn['market_cap_decile'].apply(lambda x: f"{x} Cap Decile" if x != 'Unknown' else x)
136
+
137
+ # Create the main treemap
138
+ fig = px.treemap(
139
+ df_earn,
140
+ path=[px.Constant("All"), 'market_cap_decile', "ticker"],
141
+ values="market_cap",
142
+ color="surprise_probability",
143
+ color_continuous_scale="RdYlBu",
144
+ color_continuous_midpoint=0,
145
+ hover_data=["surprise_probability", "market_cap", "date"],
146
+ title="Earnings Surprise Probability and Market Cap Treemap",
147
+ )
148
+
149
+ # Update layout for better appearance
150
+ fig.update_layout(
151
+ font=dict(family="Arial", size=14),
152
+ title=dict(font=dict(size=20, color="lightgrey")),
153
+ coloraxis_colorbar=dict(
154
+ title="Surprise Probability",
155
+ tickformat=".2%",
156
+ len=0.75,
157
+ thickness=20,
158
+ title_font=dict(size=16),
159
+ tickfont=dict(size=14),
160
+ ),
161
+ height=900,
162
+ # width=1200,
163
+ # plot_bgcolor='rgba(240,240,240,0.8)',
164
+ # paper_bgcolor='rgba(240,240,240,0.8)',
165
+ margin=dict(t=50, l=25, r=25, b=25),
166
+ )
167
+
168
+ # Update traces for better text visibility and style
169
+ fig.update_traces(
170
+ textposition="middle center",
171
+ textfont=dict(family="Arial", size=12, color="black"),
172
+ hovertemplate=(
173
+ "<b>%{label}</b><br>"
174
+ "Date: %{customdata[2]}<br>"
175
+ "Surprise Probability: %{customdata[0]:.2%}<br>"
176
+ "Market Cap: $%{customdata[1]:,.0f}M"
177
+ "<extra></extra>"
178
+ ),
179
+ marker=dict(
180
+ cornerradius=5,
181
+ line=dict(width=1, color="white"),
182
+ ),
183
+ )
184
+
185
+ # Show the plot
186
+ fig.show()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes