sovai 0.2.60__tar.gz → 0.2.62__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.
- {sovai-0.2.60 → sovai-0.2.62}/PKG-INFO +1 -1
- {sovai-0.2.60 → sovai-0.2.62}/pyproject.toml +1 -1
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/pandas_extensions.py +96 -72
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/time_decomposition.py +3 -1
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/news/news_econometric_analysis.py +9 -2
- sovai-0.2.62/sovai/token_auth.py +25 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/client_side.py +20 -14
- sovai-0.2.60/sovai/token_auth.py +0 -15
- {sovai-0.2.60 → sovai-0.2.62}/LICENSE +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/README.md +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/data/codes.parq +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/data/tickers.parq +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/.DS_Store +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/api_config.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/assets/dropdown.css +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/assets/features_mapping.parq +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/basic_auth.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/computations/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/computations/functions.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/errors/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/errors/sovai_errors.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/anomalies.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/ask_df_llm.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/change_point_generator.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/clustering.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/core_kshape.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/cum_sum_torch.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/cusum.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/dimensionality_reduction.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/feature_extraction.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/feature_importance.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/feature_neutralizer.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/filter_df.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/fractional_differencing.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/nowcasting.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/pairwise.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/parallel_functions.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/pfa_feature_selector.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/regime_change.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/regime_change_pca.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/shapley_global_importance.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/shapley_importance.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/signal_evaluation.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/technical_indicators.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/extensions/weight_optimization.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_compute.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_data copy.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_data.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_reports.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/get_tools.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/accounting/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/accounting/accounting_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/allocation/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/allocation/allocation_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/bankruptcy/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/bankruptcy/bankruptcy_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/breakout/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/breakout/breakout_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/corp_risk/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/corp_risk/corp_risk_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/earnings_surprise/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/earnings_surprise/earnings_surprise_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/insider/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/insider/insider_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/institutional/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/institutional/institutional_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/news/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/news/news_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/ratios/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/plots/ratios/ratios_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/accounting/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/accounting/accounting_balance_sheet.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/bankruptcy/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/bankruptcy/bankruptcy_monthly_top.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/general/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/general/general_plots.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/reports/news/__inti__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/studies/nowcasting.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/authentication/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/authentication/authentication.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/sec/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/sec/graphs.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/sec/llm_code_generator.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/sec/sec_10_k_8_k_filings.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/tools/sec/sec_edgar_search.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/__init__.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/client_side_s3.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/client_side_s3_part_high copy 2.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/client_side_s3_part_high copy.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/client_side_s3_part_high.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/converter.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/datetime_formats.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/file_management.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/get_tickers.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/helpers.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/pandas_extensions copy.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/plot.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/port_manager.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/stream.py +0 -0
- {sovai-0.2.60 → sovai-0.2.62}/sovai/utils/verbose_utils.py +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
import numpy as np
|
|
3
|
-
|
|
4
|
-
from numpy.linalg import norm
|
|
3
|
+
|
|
5
4
|
|
|
6
5
|
# from extensions.pfa_feature_selector import PFA ## # ## ###
|
|
7
6
|
|
|
@@ -11,72 +10,6 @@ pd.options.display.float_format = "{:.3f}".format
|
|
|
11
10
|
|
|
12
11
|
# from sovai.extensions.shapley_importance import run_simulations_frame
|
|
13
12
|
|
|
14
|
-
from sovai.extensions.feature_neutralizer import (
|
|
15
|
-
neutralize_features_function,
|
|
16
|
-
orthogonalize_features_function,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
from sovai.extensions.fractional_differencing import fractional_diff
|
|
20
|
-
|
|
21
|
-
from sovai.extensions.anomalies import (
|
|
22
|
-
anomaly_scores,
|
|
23
|
-
anomaly_global,
|
|
24
|
-
anomaly_local,
|
|
25
|
-
anomaly_cluster,
|
|
26
|
-
anomaly_reconstruction,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
from sovai.extensions.pairwise import distance_calc, relative_distance_calc
|
|
30
|
-
|
|
31
|
-
from sovai.extensions.clustering import (
|
|
32
|
-
cluster,
|
|
33
|
-
cluster_summary,
|
|
34
|
-
feature_cent,
|
|
35
|
-
vizualisation_cluster,
|
|
36
|
-
vizualisation_scatter,
|
|
37
|
-
vizualisation_animation,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
from sovai.extensions.nowcasting import nowcast_data_source, nowcast_plot_source
|
|
41
|
-
|
|
42
|
-
from sovai.extensions.change_point_generator import (
|
|
43
|
-
perform_cusum_analysis,
|
|
44
|
-
run_cusum_dashboard,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
from sovai.extensions.regime_change import (
|
|
48
|
-
perform_regime_change_analysis,
|
|
49
|
-
run_regime_change_dashboard,
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
from sovai.extensions.regime_change_pca import (
|
|
53
|
-
perform_pca_regime_change_analysis,
|
|
54
|
-
run_pca_regime_change_dashboard,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
from sovai.extensions.time_decomposition import (
|
|
58
|
-
perform_comprehensive_analysis,
|
|
59
|
-
run_comprehensive_analysis_dashboard,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
from sovai.extensions.feature_extraction import feature_extractor
|
|
63
|
-
|
|
64
|
-
from sovai.extensions.dimensionality_reduction import dimensionality_reduction
|
|
65
|
-
|
|
66
|
-
from sovai.extensions.feature_importance import (
|
|
67
|
-
random_projection_importance,
|
|
68
|
-
fast_nonlinear_diverse_selector,
|
|
69
|
-
fast_ica_selector,
|
|
70
|
-
truncated_svd_selector,
|
|
71
|
-
sparse_random_projection_selector,
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
from sovai.extensions.weight_optimization import WeightOptimization
|
|
75
|
-
|
|
76
|
-
from sovai.extensions.signal_evaluation import SignalEvaluator
|
|
77
|
-
|
|
78
|
-
from sovai.extensions.technical_indicators import techn_indicators
|
|
79
|
-
|
|
80
13
|
|
|
81
14
|
import warnings
|
|
82
15
|
|
|
@@ -98,8 +31,8 @@ import pandas as pd
|
|
|
98
31
|
|
|
99
32
|
import pandas as pd
|
|
100
33
|
from typing import Union, List
|
|
101
|
-
from sovai.extensions.ask_df_llm import Ask
|
|
102
|
-
|
|
34
|
+
# from sovai.extensions.ask_df_llm import Ask
|
|
35
|
+
|
|
103
36
|
import pandas as pd
|
|
104
37
|
from functools import lru_cache
|
|
105
38
|
import re
|
|
@@ -124,6 +57,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
124
57
|
:param verbose: If True, print detailed information about the filtering process.
|
|
125
58
|
:return: A filtered CustomDataFrame.
|
|
126
59
|
"""
|
|
60
|
+
|
|
61
|
+
from sovai.extensions.filter_df import Filter
|
|
62
|
+
|
|
127
63
|
filtered_df = Filter.filter(conditions, df_multi=self, verbose=verbose)
|
|
128
64
|
return CustomDataFrame(filtered_df)
|
|
129
65
|
|
|
@@ -230,6 +166,7 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
230
166
|
return CustomDataFrame(latest_data)
|
|
231
167
|
|
|
232
168
|
def plot_line(self, column=None, tickers=None, n=50):
|
|
169
|
+
import plotly.express as px
|
|
233
170
|
# Your plot_line implementation
|
|
234
171
|
if isinstance(self.index, pd.MultiIndex):
|
|
235
172
|
df = self.reset_index()
|
|
@@ -308,6 +245,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
308
245
|
metric="pearson",
|
|
309
246
|
calculations=["mean"],
|
|
310
247
|
):
|
|
248
|
+
|
|
249
|
+
from sovai.extensions.pairwise import distance_calc
|
|
250
|
+
|
|
311
251
|
result = distance_calc(
|
|
312
252
|
self,
|
|
313
253
|
orient=orient,
|
|
@@ -326,6 +266,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
326
266
|
metric="pearson",
|
|
327
267
|
calculations=["mean"],
|
|
328
268
|
):
|
|
269
|
+
|
|
270
|
+
from sovai.extensions.pairwise import distance_calc, relative_distance_calc
|
|
271
|
+
|
|
329
272
|
result = relative_distance_calc(
|
|
330
273
|
self,
|
|
331
274
|
orient=orient,
|
|
@@ -337,6 +280,15 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
337
280
|
return CustomDataFrame(result)
|
|
338
281
|
|
|
339
282
|
def cluster(self, orient="cluster", features=None):
|
|
283
|
+
|
|
284
|
+
from sovai.extensions.clustering import (
|
|
285
|
+
cluster,
|
|
286
|
+
cluster_summary,
|
|
287
|
+
feature_cent,
|
|
288
|
+
vizualisation_cluster,
|
|
289
|
+
vizualisation_scatter,
|
|
290
|
+
vizualisation_animation,
|
|
291
|
+
)
|
|
340
292
|
if orient == "cluster":
|
|
341
293
|
result = cluster(self, features)
|
|
342
294
|
elif orient == "summary":
|
|
@@ -358,10 +310,10 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
358
310
|
|
|
359
311
|
import numpy as np
|
|
360
312
|
import pandas as pd
|
|
361
|
-
from numpy.linalg import norm
|
|
362
313
|
|
|
363
314
|
|
|
364
315
|
def cointegration(self, on="ticker", shift=12):
|
|
316
|
+
|
|
365
317
|
"""
|
|
366
318
|
Calculate an approximate cointegration proxy using shifted cosine similarity.
|
|
367
319
|
|
|
@@ -370,6 +322,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
370
322
|
:param shift: The number of periods to shift for lagged comparison (default 1 month).
|
|
371
323
|
:return: DataFrame of shifted cosine similarities.
|
|
372
324
|
"""
|
|
325
|
+
|
|
326
|
+
from numpy.linalg import norm
|
|
327
|
+
|
|
373
328
|
# Shift the DataFrame by the specified lag
|
|
374
329
|
shifted_df = self.groupby(level=on).shift(-shift)
|
|
375
330
|
|
|
@@ -462,6 +417,8 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
462
417
|
# return CustomDataFrame(avg_shap_values)
|
|
463
418
|
|
|
464
419
|
def orthogonalize_features(self, method="gram_schmidt"):
|
|
420
|
+
from sovai.extensions.feature_neutralizer import orthogonalize_features_function
|
|
421
|
+
|
|
465
422
|
return CustomDataFrame(orthogonalize_features_function(self, method))
|
|
466
423
|
|
|
467
424
|
def importance_reorder(self):
|
|
@@ -469,6 +426,7 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
469
426
|
|
|
470
427
|
|
|
471
428
|
def neutralize_features(self, method="pca"):
|
|
429
|
+
from sovai.extensions.feature_neutralizer import neutralize_features_function
|
|
472
430
|
return CustomDataFrame(neutralize_features_function(self, method))
|
|
473
431
|
|
|
474
432
|
def ticker(self, ticker="AAPL"):
|
|
@@ -710,6 +668,8 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
710
668
|
return CustomDataFrame(df_merge)
|
|
711
669
|
|
|
712
670
|
def fractional_difference(self, d=0.845, m=100, groupby_column="ticker"):
|
|
671
|
+
from sovai.extensions.fractional_differencing import fractional_diff
|
|
672
|
+
|
|
713
673
|
"""
|
|
714
674
|
Apply fractional differencing to each group for all columns, or to the entire DataFrame if groupby_column is not present.
|
|
715
675
|
:param d: Differencing parameter.
|
|
@@ -740,6 +700,14 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
740
700
|
|
|
741
701
|
def anomalies(self, method="scores", ticker=None):
|
|
742
702
|
|
|
703
|
+
from sovai.extensions.anomalies import (
|
|
704
|
+
anomaly_scores,
|
|
705
|
+
anomaly_global,
|
|
706
|
+
anomaly_local,
|
|
707
|
+
anomaly_cluster,
|
|
708
|
+
anomaly_reconstruction,
|
|
709
|
+
)
|
|
710
|
+
|
|
743
711
|
if method == "scores":
|
|
744
712
|
return CustomDataFrame(anomaly_scores(self, ticker=ticker))
|
|
745
713
|
elif method == "global":
|
|
@@ -759,6 +727,15 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
759
727
|
|
|
760
728
|
from sovai.extensions.shapley_global_importance import run_simulations_global_importance
|
|
761
729
|
|
|
730
|
+
from sovai.extensions.feature_importance import (
|
|
731
|
+
random_projection_importance,
|
|
732
|
+
fast_nonlinear_diverse_selector,
|
|
733
|
+
fast_ica_selector,
|
|
734
|
+
truncated_svd_selector,
|
|
735
|
+
sparse_random_projection_selector,
|
|
736
|
+
)
|
|
737
|
+
|
|
738
|
+
|
|
762
739
|
if method == "random_projection":
|
|
763
740
|
return random_projection_importance(self)
|
|
764
741
|
elif method == "fourier":
|
|
@@ -781,15 +758,26 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
781
758
|
|
|
782
759
|
def nowcast_data(self, feature=None):
|
|
783
760
|
|
|
761
|
+
from sovai.extensions.nowcasting import nowcast_data_source
|
|
762
|
+
|
|
763
|
+
|
|
784
764
|
return CustomDataFrame(nowcast_data_source(self, selected_feature=feature))
|
|
785
765
|
|
|
786
766
|
|
|
787
767
|
def nowcast_plot(self, feature=None):
|
|
788
768
|
|
|
769
|
+
from sovai.extensions.nowcasting import nowcast_plot_source
|
|
770
|
+
|
|
789
771
|
return nowcast_plot_source(self, feature=feature)
|
|
790
772
|
|
|
791
773
|
|
|
792
774
|
def change_point(self, method="data", ticker=None, feature=None):
|
|
775
|
+
|
|
776
|
+
from sovai.extensions.change_point_generator import (
|
|
777
|
+
perform_cusum_analysis,
|
|
778
|
+
run_cusum_dashboard,
|
|
779
|
+
)
|
|
780
|
+
|
|
793
781
|
if ticker is None or feature is None:
|
|
794
782
|
print("Ticker and/or feature not provided. We will choose on your behalf.")
|
|
795
783
|
if ticker is None:
|
|
@@ -819,15 +807,26 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
819
807
|
print(f"Selected feature: {feature}")
|
|
820
808
|
|
|
821
809
|
if method == "data":
|
|
810
|
+
|
|
811
|
+
from sovai.extensions.regime_change import perform_regime_change_analysis
|
|
812
|
+
|
|
822
813
|
analysis_df = perform_regime_change_analysis(self, ticker, feature)
|
|
823
814
|
result = CustomDataFrame(analysis_df)
|
|
824
815
|
return result
|
|
825
816
|
elif method == "plot":
|
|
817
|
+
|
|
818
|
+
from sovai.extensions.regime_change import run_regime_change_dashboard
|
|
826
819
|
return run_regime_change_dashboard(self, ticker=ticker, feature=feature)
|
|
827
820
|
else:
|
|
828
821
|
raise ValueError("Invalid method. Choose from 'data', 'plot'")
|
|
829
822
|
|
|
830
823
|
def pca_regime_change(self, method="data", ticker=None):
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
from sovai.extensions.regime_change_pca import (
|
|
827
|
+
perform_pca_regime_change_analysis,
|
|
828
|
+
run_pca_regime_change_dashboard,
|
|
829
|
+
)
|
|
831
830
|
if ticker is None:
|
|
832
831
|
print("Ticker not provided. We will choose on your behalf.")
|
|
833
832
|
ticker = self.index.get_level_values("ticker").unique()[0]
|
|
@@ -841,6 +840,13 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
841
840
|
raise ValueError("Invalid method. Choose from 'data', 'plot'")
|
|
842
841
|
|
|
843
842
|
def time_decomposition(self, method="data", ticker=None, feature=None):
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
from sovai.extensions.time_decomposition import (
|
|
846
|
+
perform_comprehensive_analysis,
|
|
847
|
+
run_comprehensive_analysis_dashboard,
|
|
848
|
+
)
|
|
849
|
+
|
|
844
850
|
if ticker is None or feature is None:
|
|
845
851
|
print("Ticker and/or feature not provided. We will choose on your behalf.")
|
|
846
852
|
if ticker is None:
|
|
@@ -873,6 +879,8 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
873
879
|
"""
|
|
874
880
|
Extracts features from the CustomDataFrame and returns a new CustomDataFrame with the extracted features.
|
|
875
881
|
"""
|
|
882
|
+
from sovai.extensions.feature_extraction import feature_extractor
|
|
883
|
+
|
|
876
884
|
result_pd = feature_extractor(
|
|
877
885
|
self, entity_col, date_col, lookback, features, every, verbose
|
|
878
886
|
)
|
|
@@ -894,6 +902,12 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
894
902
|
CustomDataFrame: Reduced data in panel format
|
|
895
903
|
"""
|
|
896
904
|
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
from sovai.extensions.dimensionality_reduction import dimensionality_reduction
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
|
|
897
911
|
def print_status(message):
|
|
898
912
|
if verbose:
|
|
899
913
|
print(message)
|
|
@@ -929,6 +943,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
929
943
|
import pandas as pd
|
|
930
944
|
import numpy as np
|
|
931
945
|
|
|
946
|
+
|
|
947
|
+
from sovai.extensions.weight_optimization import WeightOptimization
|
|
948
|
+
|
|
932
949
|
# Check if self is a pandas DataFrame
|
|
933
950
|
if not isinstance(self, pd.DataFrame):
|
|
934
951
|
raise TypeError("Input must be a pandas DataFrame.")
|
|
@@ -974,6 +991,8 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
974
991
|
import pandas as pd
|
|
975
992
|
import numpy as np
|
|
976
993
|
|
|
994
|
+
from sovai.extensions.signal_evaluation import SignalEvaluator
|
|
995
|
+
|
|
977
996
|
# Check if self.df_factor is a pandas DataFrame
|
|
978
997
|
if not isinstance(self, pd.DataFrame):
|
|
979
998
|
raise TypeError("Input must be a pandas DataFrame.")
|
|
@@ -1024,6 +1043,9 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
1024
1043
|
return CustomDataFrame(avg_shap_values)
|
|
1025
1044
|
|
|
1026
1045
|
def technical_indicators(self):
|
|
1046
|
+
|
|
1047
|
+
from sovai.extensions.technical_indicators import techn_indicators
|
|
1048
|
+
|
|
1027
1049
|
"""
|
|
1028
1050
|
Computes feature importance using SHAP values based on multiple simulations.
|
|
1029
1051
|
|
|
@@ -1049,10 +1071,12 @@ class CustomDataFrame(pd.DataFrame):
|
|
|
1049
1071
|
import polars as pl
|
|
1050
1072
|
import pandas as pd
|
|
1051
1073
|
import numpy as np
|
|
1052
|
-
from numpy.linalg import norm
|
|
1053
1074
|
|
|
1054
1075
|
|
|
1055
1076
|
def distance_pl(pandas_df, on="ticker"):
|
|
1077
|
+
|
|
1078
|
+
from numpy.linalg import norm
|
|
1079
|
+
|
|
1056
1080
|
pl_df = pl.from_pandas(
|
|
1057
1081
|
pandas_df.reset_index()
|
|
1058
1082
|
if isinstance(pandas_df.index, pd.MultiIndex)
|
|
@@ -3,7 +3,7 @@ import pandas as pd
|
|
|
3
3
|
import plotly.graph_objects as go
|
|
4
4
|
from plotly.subplots import make_subplots
|
|
5
5
|
from scipy import stats
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
import dash
|
|
8
8
|
from dash import dcc, html
|
|
9
9
|
from dash.dependencies import Input, Output
|
|
@@ -31,6 +31,8 @@ def categorize_trend(
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def perform_comprehensive_analysis(df_accounting, ticker, feature):
|
|
34
|
+
from statsforecast.models import MSTL
|
|
35
|
+
|
|
34
36
|
df_signal = (
|
|
35
37
|
df_accounting.query(f"ticker == '{ticker}'")
|
|
36
38
|
.reset_index()
|
|
@@ -6,8 +6,6 @@ import logging
|
|
|
6
6
|
import ipywidgets as widgets
|
|
7
7
|
import pandas as pd
|
|
8
8
|
import numpy as np
|
|
9
|
-
from statsmodels.tsa.stattools import adfuller, coint, grangercausalitytests
|
|
10
|
-
from statsmodels.tsa.vector_ar.vecm import VECM
|
|
11
9
|
from IPython.display import display, HTML
|
|
12
10
|
from scipy import stats
|
|
13
11
|
import warnings
|
|
@@ -48,6 +46,8 @@ def prepare_data(ticker, variables):
|
|
|
48
46
|
|
|
49
47
|
|
|
50
48
|
def adf_test(series):
|
|
49
|
+
from statsmodels.tsa.stattools import adfuller
|
|
50
|
+
|
|
51
51
|
"""Perform Augmented Dickey-Fuller test for stationarity."""
|
|
52
52
|
result = adfuller(series)
|
|
53
53
|
return pd.Series({
|
|
@@ -59,6 +59,9 @@ def adf_test(series):
|
|
|
59
59
|
})
|
|
60
60
|
|
|
61
61
|
def cointegration_test(series1, series2):
|
|
62
|
+
|
|
63
|
+
from statsmodels.tsa.stattools import coint
|
|
64
|
+
|
|
62
65
|
"""Perform cointegration test between two series."""
|
|
63
66
|
_, p_value, _ = coint(series1, series2)
|
|
64
67
|
return p_value
|
|
@@ -100,6 +103,8 @@ def interpret_vecm_coefficient(coef, p_value):
|
|
|
100
103
|
return f"{strength.capitalize()} {direction} impact"
|
|
101
104
|
|
|
102
105
|
def granger_causality(data, variables, max_lags=5):
|
|
106
|
+
from statsmodels.tsa.stattools import grangercausalitytests
|
|
107
|
+
|
|
103
108
|
results = {}
|
|
104
109
|
for v1 in variables:
|
|
105
110
|
for v2 in variables:
|
|
@@ -189,6 +194,8 @@ def generate_dynamic_report(df_merged, ticker, variables):
|
|
|
189
194
|
report.append("<p>VECM combines short-term dynamics with long-term equilibrium relationships. It's particularly useful when variables are cointegrated, as it can model both short-term adjustments and long-term convergence to equilibrium.</p>")
|
|
190
195
|
|
|
191
196
|
try:
|
|
197
|
+
from statsmodels.tsa.vector_ar.vecm import VECM
|
|
198
|
+
|
|
192
199
|
max_lags = 10 # Increase the number of lags considered
|
|
193
200
|
logger.info(f"Fitting VECM model with {max_lags} lags")
|
|
194
201
|
model = VECM(df_merged[all_variables], deterministic='co', k_ar_diff=max_lags)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from sovai.api_config import ApiConfig, save_key
|
|
2
|
+
# Removed verify_token import from top level
|
|
3
|
+
from sovai.errors.sovai_errors import InvalidCredentialsError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def token_auth(token: str):
|
|
7
|
+
"""Authenticates using a token, saves it, and verifies it."""
|
|
8
|
+
|
|
9
|
+
# Lazy load verify_token here, just before use
|
|
10
|
+
from sovai.utils.client_side import verify_token
|
|
11
|
+
|
|
12
|
+
ApiConfig.token = token
|
|
13
|
+
ApiConfig.token_type = "Bearer"
|
|
14
|
+
save_key() # Assumes save_key doesn't trigger heavy imports
|
|
15
|
+
|
|
16
|
+
# Now call the imported function
|
|
17
|
+
is_valid, user_id = verify_token(verbose=False) # Uses lazy-loaded verify_token
|
|
18
|
+
|
|
19
|
+
if not is_valid:
|
|
20
|
+
# print('invalid') # Keep commented or use logging
|
|
21
|
+
raise InvalidCredentialsError("Invalid or expired token. Please authenticate.")
|
|
22
|
+
|
|
23
|
+
# Optionally, you could return something useful, like the validity or user_id
|
|
24
|
+
# print(f"Token verified successfully for user ID: {user_id}") # Or use logging
|
|
25
|
+
# return is_valid, user_id
|
|
@@ -7,13 +7,7 @@ from sovai.errors.sovai_errors import InvalidCredentialsError
|
|
|
7
7
|
import requests
|
|
8
8
|
from sovai.api_config import ApiConfig
|
|
9
9
|
|
|
10
|
-
|
|
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
|
|
10
|
+
|
|
17
11
|
|
|
18
12
|
|
|
19
13
|
## might do the same thing as token_auth, you might have recreated it.
|
|
@@ -224,15 +218,27 @@ def client_side_frame(endpoint, tickers, columns, start_date, end_date):
|
|
|
224
218
|
name_file = config["name"]
|
|
225
219
|
partitioned = config["partitioned"]
|
|
226
220
|
|
|
227
|
-
# Load data
|
|
228
|
-
|
|
221
|
+
# Load data - receives a standard pandas DataFrame
|
|
222
|
+
df_result = load_data_for_tickers(
|
|
229
223
|
base_url, tickers, columns, start_date, end_date, name_file, partitioned
|
|
230
224
|
)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
225
|
+
|
|
226
|
+
# --- Lazy Load CustomDataFrame Wrapper ---
|
|
227
|
+
# Try to import and wrap only if the import succeeds
|
|
228
|
+
try:
|
|
229
|
+
from sovai.extensions.pandas_extensions import CustomDataFrame
|
|
230
|
+
# If import successful, wrap the result
|
|
231
|
+
print("Wrapping result in CustomDataFrame.") # Optional: for debugging
|
|
232
|
+
return CustomDataFrame(df_result)
|
|
233
|
+
except ImportError:
|
|
234
|
+
# If import fails (lean install), return the standard DataFrame
|
|
235
|
+
print("CustomDataFrame not available (lean install?). Returning standard pandas DataFrame.") # Optional: for debugging
|
|
236
|
+
return df_result
|
|
237
|
+
except Exception as e:
|
|
238
|
+
# Catch other potential errors during wrapping
|
|
239
|
+
print(f"Error wrapping result in CustomDataFrame: {e}. Returning standard pandas DataFrame.")
|
|
240
|
+
return df_result
|
|
241
|
+
|
|
236
242
|
|
|
237
243
|
|
|
238
244
|
# def client_side_frame(endpoint, tickers, columns, start_date, end_date):
|
sovai-0.2.60/sovai/token_auth.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from sovai.api_config import ApiConfig, save_key
|
|
2
|
-
from sovai.utils.client_side import verify_token
|
|
3
|
-
from sovai.errors.sovai_errors import InvalidCredentialsError
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def token_auth(token: str):
|
|
7
|
-
ApiConfig.token = token
|
|
8
|
-
ApiConfig.token_type = "Bearer"
|
|
9
|
-
save_key()
|
|
10
|
-
is_valid, user_id = verify_token(verbose=False)
|
|
11
|
-
|
|
12
|
-
if not is_valid:
|
|
13
|
-
# print('invalid')
|
|
14
|
-
raise InvalidCredentialsError("Invalid or expired token. Please authenticate.")
|
|
15
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|