sovai 0.2.34__tar.gz → 0.2.35__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 (97) hide show
  1. {sovai-0.2.34 → sovai-0.2.35}/PKG-INFO +2 -1
  2. {sovai-0.2.34 → sovai-0.2.35}/pyproject.toml +2 -1
  3. {sovai-0.2.34 → sovai-0.2.35}/sovai/get_data.py +5 -1
  4. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/authentication/authentication.py +57 -5
  5. sovai-0.2.35/sovai/utils/client_side_s3 copy.py +206 -0
  6. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/client_side_s3.py +8 -0
  7. {sovai-0.2.34 → sovai-0.2.35}/LICENSE +0 -0
  8. {sovai-0.2.34 → sovai-0.2.35}/README.md +0 -0
  9. {sovai-0.2.34 → sovai-0.2.35}/sovai/.DS_Store +0 -0
  10. {sovai-0.2.34 → sovai-0.2.35}/sovai/__init__.py +0 -0
  11. {sovai-0.2.34 → sovai-0.2.35}/sovai/api_config.py +0 -0
  12. {sovai-0.2.34 → sovai-0.2.35}/sovai/assets/dropdown.css +0 -0
  13. {sovai-0.2.34 → sovai-0.2.35}/sovai/assets/features_mapping.parq +0 -0
  14. {sovai-0.2.34 → sovai-0.2.35}/sovai/basic_auth.py +0 -0
  15. {sovai-0.2.34 → sovai-0.2.35}/sovai/computations/__init__.py +0 -0
  16. {sovai-0.2.34 → sovai-0.2.35}/sovai/computations/functions.py +0 -0
  17. {sovai-0.2.34 → sovai-0.2.35}/sovai/errors/__init__.py +0 -0
  18. {sovai-0.2.34 → sovai-0.2.35}/sovai/errors/sovai_errors.py +0 -0
  19. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/__init__.py +0 -0
  20. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/anomalies.py +0 -0
  21. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/ask_df_llm.py +0 -0
  22. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/change_point_generator.py +0 -0
  23. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/clustering.py +0 -0
  24. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/core_kshape.py +0 -0
  25. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/cum_sum_torch.py +0 -0
  26. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/cusum.py +0 -0
  27. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/dimensionality_reduction.py +0 -0
  28. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/feature_extraction.py +0 -0
  29. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/feature_importance.py +0 -0
  30. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/feature_neutralizer.py +0 -0
  31. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/filter_df.py +0 -0
  32. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/fractional_differencing.py +0 -0
  33. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/nowcasting.py +0 -0
  34. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/pairwise.py +0 -0
  35. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/pandas_extensions.py +0 -0
  36. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/parallel_functions.py +0 -0
  37. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/pfa_feature_selector.py +0 -0
  38. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/regime_change.py +0 -0
  39. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/regime_change_pca.py +0 -0
  40. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/shapley_global_importance.py +0 -0
  41. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/shapley_importance.py +0 -0
  42. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/signal_evaluation.py +0 -0
  43. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/technical_indicators.py +0 -0
  44. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/time_decomposition.py +0 -0
  45. {sovai-0.2.34 → sovai-0.2.35}/sovai/extensions/weight_optimization.py +0 -0
  46. {sovai-0.2.34 → sovai-0.2.35}/sovai/get_compute.py +0 -0
  47. {sovai-0.2.34 → sovai-0.2.35}/sovai/get_plots.py +0 -0
  48. {sovai-0.2.34 → sovai-0.2.35}/sovai/get_reports.py +0 -0
  49. {sovai-0.2.34 → sovai-0.2.35}/sovai/get_tools.py +0 -0
  50. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/__init__.py +0 -0
  51. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/accounting/__init__.py +0 -0
  52. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/accounting/accounting_plots.py +0 -0
  53. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/allocation/__init__.py +0 -0
  54. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/allocation/allocation_plots.py +0 -0
  55. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/bankruptcy/__init__.py +0 -0
  56. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/bankruptcy/bankruptcy_plots.py +0 -0
  57. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/breakout/__init__.py +0 -0
  58. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/breakout/breakout_plots.py +0 -0
  59. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/corp_risk/__init__.py +0 -0
  60. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/corp_risk/corp_risk_plots.py +0 -0
  61. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/earnings_surprise/__init__.py +0 -0
  62. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/earnings_surprise/earnings_surprise_plots.py +0 -0
  63. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/insider/__init__.py +0 -0
  64. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/insider/insider_plots.py +0 -0
  65. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/institutional/__init__.py +0 -0
  66. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/institutional/institutional_plots.py +0 -0
  67. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/news/__init__.py +0 -0
  68. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/news/news_plots.py +0 -0
  69. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/ratios/__init__.py +0 -0
  70. {sovai-0.2.34 → sovai-0.2.35}/sovai/plots/ratios/ratios_plots.py +0 -0
  71. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/accounting/__init__.py +0 -0
  72. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/accounting/accounting_balance_sheet.py +0 -0
  73. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/bankruptcy/__init__.py +0 -0
  74. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/bankruptcy/bankruptcy_monthly_top.py +0 -0
  75. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/general/__init__.py +0 -0
  76. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/general/general_plots.py +0 -0
  77. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/news/__inti__.py +0 -0
  78. {sovai-0.2.34 → sovai-0.2.35}/sovai/reports/news/news_econometric_analysis.py +0 -0
  79. {sovai-0.2.34 → sovai-0.2.35}/sovai/studies/nowcasting.py +0 -0
  80. {sovai-0.2.34 → sovai-0.2.35}/sovai/token_auth.py +0 -0
  81. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/authentication/__init__.py +0 -0
  82. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/sec/__init__.py +0 -0
  83. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/sec/graphs.py +0 -0
  84. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/sec/llm_code_generator.py +0 -0
  85. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/sec/sec_10_k_8_k_filings.py +0 -0
  86. {sovai-0.2.34 → sovai-0.2.35}/sovai/tools/sec/sec_edgar_search.py +0 -0
  87. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/__init__.py +0 -0
  88. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/client_side.py +0 -0
  89. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/converter.py +0 -0
  90. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/datetime_formats.py +0 -0
  91. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/file_management.py +0 -0
  92. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/get_tickers.py +0 -0
  93. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/helpers.py +0 -0
  94. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/pandas_extensions copy.py +0 -0
  95. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/plot.py +0 -0
  96. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/port_manager.py +0 -0
  97. {sovai-0.2.34 → sovai-0.2.35}/sovai/utils/stream.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sovai
3
- Version: 0.2.34
3
+ Version: 0.2.35
4
4
  Summary: python for asset management
5
5
  License: Proprietary License
6
6
  Author: Derek Snow
@@ -39,6 +39,7 @@ Requires-Dist: pyvis (>=0.3.2,<0.4.0)
39
39
  Requires-Dist: rapidfuzz (>=3.9.7,<4.0.0)
40
40
  Requires-Dist: requests (>=2.20)
41
41
  Requires-Dist: ruptures (>=1.0) ; extra == "full"
42
+ Requires-Dist: s3fs (>=2024.10.0,<2025.0.0)
42
43
  Requires-Dist: scikit-learn (>=1.0) ; extra == "full"
43
44
  Requires-Dist: scipy (>=1.0) ; extra == "full"
44
45
  Requires-Dist: seaborn (>=0.13.2,<0.14.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "sovai"
3
- version = "0.2.34"
3
+ version = "0.2.35"
4
4
  description = "python for asset management"
5
5
  authors = ["Derek Snow <d.snow@outlook.com>"]
6
6
  license = "Proprietary License"
@@ -65,6 +65,7 @@ yachalk = "^0.1.6"
65
65
  pyvis = "^0.3.2"
66
66
  networkx = "^3.3"
67
67
  seaborn = "^0.13.2"
68
+ s3fs = "^2024.10.0"
68
69
 
69
70
 
70
71
  [tool.poetry.extras]
@@ -267,6 +267,10 @@ endpoint_to_ticker = {
267
267
  "/market/closeadj": "",
268
268
  "/lobbying/public": "",
269
269
 
270
+ "/liquidity/price_improvement":"",
271
+ "/liquidity/market_opportunity":"",
272
+
273
+
270
274
 
271
275
  ## remember to add leading "/"
272
276
  "/trials/predict": "",
@@ -745,7 +749,7 @@ def data(
745
749
  return None
746
750
  return data
747
751
  except Exception as err:
748
- verbose_mode.vprint("An error occurred, check dictaionries for 'data/name':'None':", err)
752
+ verbose_mode.vprint("An error occurred, check dictionaries for 'data/name':'None':", err)
749
753
  return data
750
754
  if res.status_code == 404:
751
755
  msg = res.json()
@@ -3,9 +3,11 @@ from sovai.api_config import ApiConfig
3
3
  import requests
4
4
  import pickle
5
5
  import base64
6
- from pyarrow.fs import S3FileSystem
6
+ from pyarrow.fs import S3FileSystem as S3File
7
+ import s3fs
7
8
 
8
- def get_s3_filesystem_pickle(storage_provider: str, verbose: bool = False):
9
+
10
+ def get_s3fs_filesystem_pickle(storage_provider: str, verbose: bool = False):
9
11
  """
10
12
  Retrieve the S3FileSystem for the specified storage provider using pickle.
11
13
 
@@ -38,6 +40,56 @@ def get_s3_filesystem_pickle(storage_provider: str, verbose: bool = False):
38
40
  print(f"Failed to retrieve S3FileSystem for {storage_provider}: {e}")
39
41
  return None
40
42
 
43
+
44
+
45
+ def get_s3fs_filesystem_json(storage_provider: str, verbose: bool = False):
46
+ """
47
+ Retrieve the S3FileSystem for the specified storage provider using JSON.
48
+
49
+ :param storage_provider: Either 'wasabi' or 'digitalocean'
50
+ :param verbose: If True, print additional information about the request
51
+ :return: S3FileSystem object, or None if the request fails
52
+ """
53
+ if storage_provider.lower() not in ['wasabi', 'digitalocean']:
54
+ raise ValueError("storage_provider must be either 'wasabi' or 'digitalocean'")
55
+
56
+ url = f"{ApiConfig.base_url}/credentials/get_s3_filesystem_json"
57
+ headers = {
58
+ "Authorization": f"Bearer {ApiConfig.token}",
59
+ "Content-Type": "application/json"
60
+ }
61
+ params = {"storage_provider": storage_provider.lower()}
62
+
63
+ try:
64
+ response = requests.get(url, headers=headers, params=params)
65
+ response.raise_for_status()
66
+
67
+ cred = response.json()
68
+
69
+ if verbose:
70
+ print(f"Successfully retrieved S3 credentials for {storage_provider}")
71
+
72
+ s3fsa = s3fs.S3FileSystem(
73
+ access_key=cred['access_key'],
74
+ secret_key=cred['secret_key'],
75
+ client_kwargs={'endpoint_url': cred['endpoint']}
76
+ )
77
+
78
+ try:
79
+ s3fsa.ls('/')
80
+ if verbose:
81
+ print(f"Successfully verified S3FileSystem for {storage_provider}")
82
+ return s3fsa
83
+ except Exception as e:
84
+ if verbose:
85
+ print(f"Failed to verify S3FileSystem: {str(e)}")
86
+ return None
87
+
88
+ except requests.RequestException as e:
89
+ if verbose:
90
+ print(f"Failed to retrieve S3 credentials for {storage_provider}: {e}")
91
+ return None
92
+
41
93
  def get_s3_filesystem_json(storage_provider: str, verbose: bool = False):
42
94
  """
43
95
  Retrieve the S3FileSystem for the specified storage provider using JSON.
@@ -65,17 +117,17 @@ def get_s3_filesystem_json(storage_provider: str, verbose: bool = False):
65
117
  if verbose:
66
118
  print(f"Successfully retrieved S3 credentials for {storage_provider}")
67
119
 
68
- s3fs = S3FileSystem(
120
+ s3fsa = S3File(
69
121
  access_key=cred['access_key'],
70
122
  secret_key=cred['secret_key'],
71
123
  endpoint_override=cred['endpoint']
72
124
  )
73
125
 
74
126
  try:
75
- s3fs.ls('/')
127
+ s3fsa.ls('/')
76
128
  if verbose:
77
129
  print(f"Successfully verified S3FileSystem for {storage_provider}")
78
- return s3fs
130
+ return s3fsa
79
131
  except Exception as e:
80
132
  if verbose:
81
133
  print(f"Failed to verify S3FileSystem: {str(e)}")
@@ -0,0 +1,206 @@
1
+ import pyarrow.dataset as ds
2
+ from pyarrow.fs import S3FileSystem
3
+ import pyarrow as pa
4
+ import pandas as pd
5
+ from functools import lru_cache
6
+ from concurrent.futures import ThreadPoolExecutor, as_completed
7
+ from sovai.tools.authentication import authentication
8
+
9
+
10
+ # Try to import CustomDataFrame, use regular DataFrame if not available
11
+ try:
12
+ from sovai.extensions.pandas_extensions import CustomDataFrame
13
+ HAS_CUSTOM_DATAFRAME = True
14
+ except ImportError:
15
+ HAS_CUSTOM_DATAFRAME = False
16
+ CustomDataFrame = pd.DataFrame # Fallback to regular DataFrame
17
+
18
+
19
+ @lru_cache(maxsize=2)
20
+ def get_cached_s3_filesystem(storage_provider):
21
+ return authentication.get_s3_filesystem_pickle(storage_provider, verbose=True)
22
+
23
+ def process_partition(storage_provider, base_path, identifier_column, identifier=None, columns=None, filters=None):
24
+ s3 = get_cached_s3_filesystem(storage_provider)
25
+
26
+ if identifier:
27
+ base_path += f"/{identifier_column}={identifier}"
28
+
29
+ dataset = ds.dataset(base_path, filesystem=s3, format='parquet')
30
+
31
+ if filters:
32
+ operator_map = {
33
+ '==': lambda a, b: a == b,
34
+ '!=': lambda a, b: a != b,
35
+ '<': lambda a, b: a < b,
36
+ '<=': lambda a, b: a <= b,
37
+ '>': lambda a, b: a > b,
38
+ '>=': lambda a, b: a >= b,
39
+ 'in': lambda a, b: a.isin(b),
40
+ 'not in': lambda a, b: ~a.isin(b),
41
+ 'like': lambda a, b: a.match_substring(b),
42
+ }
43
+ schema = dataset.schema
44
+ filter_expr = None
45
+ for col, op, val in filters:
46
+ if op not in operator_map:
47
+ raise ValueError(f"Unsupported operator '{op}' in filters.")
48
+ field = ds.field(col)
49
+ field_type = schema.field(col).type
50
+ if pa.types.is_timestamp(field_type) or pa.types.is_date(field_type):
51
+ val = pd.to_datetime(val)
52
+ elif pa.types.is_integer(field_type):
53
+ val = int(val)
54
+ elif pa.types.is_floating(field_type):
55
+ val = float(val)
56
+ condition = operator_map[op](field, val)
57
+ filter_expr = condition if filter_expr is None else filter_expr & condition
58
+ else:
59
+ filter_expr = None
60
+
61
+ table = dataset.to_table(columns=columns, filter=filter_expr, use_threads=True)
62
+ df = table.to_pandas(use_threads=True)
63
+
64
+ if identifier:
65
+ df[identifier_column] = identifier
66
+
67
+ df = df[[identifier_column] + [col for col in df.columns if col != identifier_column]]
68
+
69
+
70
+ return df
71
+
72
+ import numpy as np
73
+
74
+ def client_side_s3_frame(config, identifiers, columns, start_date, end_date):
75
+ storage_provider = "digitalocean" # Default to DigitalOcean
76
+ base_path = config["storage_provider"][storage_provider]
77
+ identifier_column = config.get("identifier_column")
78
+
79
+ filters = []
80
+ if start_date:
81
+ filters.append(('date', '>=', start_date))
82
+ if end_date:
83
+ filters.append(('date', '<=', end_date))
84
+
85
+ if not identifiers:
86
+ # Load the entire database
87
+ return process_partition(storage_provider, base_path, identifier_column, columns=columns, filters=filters)
88
+ else:
89
+ identifiers = map_identifier(identifiers, input_identifier='ticker', output_identifier=identifier_column)
90
+
91
+ # Use numpy.isscalar to check if identifiers is a single value
92
+ if np.isscalar(identifiers):
93
+ # Single identifier
94
+ identifier = identifiers
95
+ return process_partition(storage_provider, base_path, identifier_column, identifier=identifier, columns=columns, filters=filters)
96
+
97
+ # Multiple identifiers
98
+ with ThreadPoolExecutor() as executor:
99
+ futures = []
100
+ for identifier in identifiers:
101
+ futures.append(executor.submit(process_partition, storage_provider, base_path, identifier_column, identifier, columns, filters))
102
+
103
+ results = []
104
+ for future in as_completed(futures):
105
+ results.append(future.result())
106
+
107
+ df = pd.concat(results, ignore_index=True)
108
+ return df
109
+
110
+ # if 'filing_date' in df.columns:
111
+ # df['date'] = pd.to_datetime(df['filing_date'])
112
+ # elif 'date' not in df.columns:
113
+ # raise ValueError("Neither 'filing_date' nor 'date' column found in the data")
114
+
115
+ # df.set_index([identifier_column, 'date'], inplace=True)
116
+ # df.sort_index(inplace=True)
117
+
118
+ return df
119
+
120
+ import pandas as pd
121
+ import numpy as np
122
+
123
+ def map_identifier(input_values, input_identifier='ticker', output_identifier='cik', trailing_zero_removal=True):
124
+ """
125
+ Map from one identifier to another using the df_codes DataFrame.
126
+ Handles string, single-item list, and multiple-item lists as input.
127
+ Uses vectorization for improved performance.
128
+
129
+ :param input_values: The input identifier value(s) to map from (string, list, or array-like)
130
+ :param input_identifier: The type of input identifier (default: 'ticker')
131
+ :param output_identifier: The type of output identifier (default: 'cik')
132
+ :param trailing_zero_removal: If True, convert CIK to int (default: True)
133
+ :return: Mapped identifier value(s), same type as input
134
+ """
135
+ df_codes = pd.read_parquet("data/codes.parq")
136
+
137
+ # Check if the identifier columns exist in df_codes
138
+ if input_identifier not in df_codes.columns or output_identifier not in df_codes.columns:
139
+ raise ValueError(f"Identifier '{input_identifier}' or '{output_identifier}' not found in the DataFrame")
140
+
141
+ # Convert input to numpy array for consistent handling
142
+ if isinstance(input_values, str):
143
+ input_array = np.array([input_values])
144
+ input_is_string = True
145
+ else:
146
+ input_array = np.array(input_values)
147
+ input_is_string = False
148
+
149
+ # Ensure all input values are strings
150
+ input_array = np.char.strip(input_array.astype(str))
151
+
152
+ # Create a dictionary for fast lookup
153
+ mapping_dict = dict(zip(df_codes[input_identifier], df_codes[output_identifier]))
154
+
155
+ # Vectorized mapping
156
+ result = np.vectorize(mapping_dict.get)(input_array)
157
+
158
+ # Convert to int if trailing_zero_removal is True and output is CIK
159
+ if trailing_zero_removal and output_identifier.lower() == 'cik':
160
+ result = np.where(result == None, 0, result) # Replace None with 0
161
+ result = result.astype(np.int32) # Convert to int64
162
+
163
+ # Return result in the same format as input
164
+ if input_is_string:
165
+ return result[0]
166
+ elif len(input_array) == 1:
167
+ return result[0]
168
+ else:
169
+ return result.tolist()
170
+
171
+
172
+ def load_frame_s3(endpoint, tickers=None, columns=None, start_date=None, end_date=None):
173
+
174
+ endpoint_config = {
175
+
176
+ "patents/applications": {
177
+ "storage_provider": {
178
+ "digitalocean": "sovai/sovai-patents-export/applications",
179
+ "wasabi": "sovai-patents-export/applications"
180
+ },
181
+ "identifier_columns": ["date_partitioned", "ticker_partitioned"],
182
+ "partitioned": True,
183
+ },
184
+
185
+ }
186
+
187
+ if endpoint not in endpoint_config:
188
+ raise ValueError(f"Invalid endpoint: {endpoint}")
189
+
190
+ config = endpoint_config[endpoint]
191
+
192
+
193
+ df_frame = client_side_s3_frame(
194
+ config,
195
+ tickers,
196
+ columns,
197
+ start_date,
198
+ end_date
199
+ )
200
+
201
+
202
+ if HAS_CUSTOM_DATAFRAME:
203
+ return CustomDataFrame(df_frame)
204
+ else:
205
+ return df_frame # Returns a regular pandas DataFrame if CustomDataFrame is not available
206
+
@@ -182,6 +182,14 @@ def load_frame_s3(endpoint, tickers=None, columns=None, start_date=None, end_dat
182
182
  "partitioned": True,
183
183
 
184
184
  },
185
+ "patents/applications": {
186
+ "storage_provider": {
187
+ "digitalocean": "sovai/sovai-patents-export/applications",
188
+ "wasabi": "sovai-patents-export/applications"
189
+ },
190
+ "identifier_columns": ["date_partitioned", "ticker_partitioned"],
191
+ "partitioned": True,
192
+ },
185
193
  "trials/predict": {
186
194
  "storage_provider": {
187
195
  "digitalocean": "sovai/sovai-clinical-trials-export/prediction_public",
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
File without changes