Spaces:
Paused
Paused
Tonic commited on
fix covariate and model training issues
Browse files
app.py
CHANGED
|
@@ -3722,24 +3722,62 @@ def create_enhanced_ensemble_model(df: pd.DataFrame, covariate_data: Dict,
|
|
| 3722 |
# Add covariate data
|
| 3723 |
if 'market_indices' in covariate_data:
|
| 3724 |
for col in covariate_data['market_indices'].columns:
|
| 3725 |
-
|
| 3726 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3727 |
|
| 3728 |
if 'economic_indicators' in covariate_data:
|
| 3729 |
for col in covariate_data['economic_indicators'].columns:
|
| 3730 |
-
|
| 3731 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3732 |
|
| 3733 |
# Create feature matrix
|
| 3734 |
X = np.column_stack(features)
|
| 3735 |
y = target
|
| 3736 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3737 |
# Remove any NaN values
|
| 3738 |
mask = ~np.isnan(X).any(axis=1) & ~np.isnan(y)
|
| 3739 |
X = X[mask]
|
| 3740 |
y = y[mask]
|
| 3741 |
|
|
|
|
|
|
|
| 3742 |
if len(X) < 50: # Need sufficient data
|
|
|
|
| 3743 |
return np.array([]), np.array([])
|
| 3744 |
|
| 3745 |
# Initialize models
|
|
@@ -3776,8 +3814,27 @@ def create_enhanced_ensemble_model(df: pd.DataFrame, covariate_data: Dict,
|
|
| 3776 |
pred = model.predict(X[-prediction_days:])
|
| 3777 |
uncertainty = np.std(y) * np.ones(prediction_days)
|
| 3778 |
|
| 3779 |
-
|
| 3780 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3781 |
|
| 3782 |
except Exception as e:
|
| 3783 |
print(f"Error training {name}: {str(e)}")
|
|
@@ -3786,6 +3843,11 @@ def create_enhanced_ensemble_model(df: pd.DataFrame, covariate_data: Dict,
|
|
| 3786 |
if not predictions:
|
| 3787 |
return np.array([]), np.array([])
|
| 3788 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3789 |
# Combine predictions using weighted average
|
| 3790 |
weights = {}
|
| 3791 |
for name in predictions.keys():
|
|
@@ -3807,14 +3869,64 @@ def create_enhanced_ensemble_model(df: pd.DataFrame, covariate_data: Dict,
|
|
| 3807 |
|
| 3808 |
for name, pred in predictions.items():
|
| 3809 |
if name in weights:
|
| 3810 |
-
|
| 3811 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3812 |
|
| 3813 |
return ensemble_pred, ensemble_uncertainty
|
| 3814 |
|
| 3815 |
except Exception as e:
|
| 3816 |
print(f"Enhanced ensemble model error: {str(e)}")
|
| 3817 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3818 |
|
| 3819 |
def calculate_volume_prediction_enhanced(df: pd.DataFrame, price_prediction: np.ndarray,
|
| 3820 |
covariate_data: Dict = None) -> Tuple[np.ndarray, np.ndarray]:
|
|
|
|
| 3722 |
# Add covariate data
|
| 3723 |
if 'market_indices' in covariate_data:
|
| 3724 |
for col in covariate_data['market_indices'].columns:
|
| 3725 |
+
covariate_series = covariate_data['market_indices'][col]
|
| 3726 |
+
# Align covariate data to target length
|
| 3727 |
+
if len(covariate_series) == len(target):
|
| 3728 |
+
features.append(covariate_series.values)
|
| 3729 |
+
elif len(covariate_series) > len(target):
|
| 3730 |
+
# Truncate to target length
|
| 3731 |
+
features.append(covariate_series.tail(len(target)).values)
|
| 3732 |
+
else:
|
| 3733 |
+
# Pad with last value
|
| 3734 |
+
padded_values = np.pad(covariate_series.values,
|
| 3735 |
+
(len(target) - len(covariate_series), 0),
|
| 3736 |
+
mode='edge')
|
| 3737 |
+
features.append(padded_values)
|
| 3738 |
|
| 3739 |
if 'economic_indicators' in covariate_data:
|
| 3740 |
for col in covariate_data['economic_indicators'].columns:
|
| 3741 |
+
covariate_series = covariate_data['economic_indicators'][col]
|
| 3742 |
+
# Align covariate data to target length
|
| 3743 |
+
if len(covariate_series) == len(target):
|
| 3744 |
+
features.append(covariate_series.values)
|
| 3745 |
+
elif len(covariate_series) > len(target):
|
| 3746 |
+
# Truncate to target length
|
| 3747 |
+
features.append(covariate_series.tail(len(target)).values)
|
| 3748 |
+
else:
|
| 3749 |
+
# Pad with last value
|
| 3750 |
+
padded_values = np.pad(covariate_series.values,
|
| 3751 |
+
(len(target) - len(covariate_series), 0),
|
| 3752 |
+
mode='edge')
|
| 3753 |
+
features.append(padded_values)
|
| 3754 |
|
| 3755 |
# Create feature matrix
|
| 3756 |
X = np.column_stack(features)
|
| 3757 |
y = target
|
| 3758 |
|
| 3759 |
+
# Validate feature matrix
|
| 3760 |
+
print(f"Feature matrix shape: {X.shape}, Target shape: {y.shape}")
|
| 3761 |
+
|
| 3762 |
+
# Ensure all features have the same length
|
| 3763 |
+
feature_lengths = [len(feature) for feature in features]
|
| 3764 |
+
if len(set(feature_lengths)) > 1:
|
| 3765 |
+
print(f"Warning: Feature lengths are inconsistent: {feature_lengths}")
|
| 3766 |
+
# Find the minimum length and truncate all features
|
| 3767 |
+
min_length = min(feature_lengths)
|
| 3768 |
+
X = X[:min_length]
|
| 3769 |
+
y = y[:min_length]
|
| 3770 |
+
print(f"Truncated to minimum length: {min_length}")
|
| 3771 |
+
|
| 3772 |
# Remove any NaN values
|
| 3773 |
mask = ~np.isnan(X).any(axis=1) & ~np.isnan(y)
|
| 3774 |
X = X[mask]
|
| 3775 |
y = y[mask]
|
| 3776 |
|
| 3777 |
+
print(f"After NaN removal - X shape: {X.shape}, y shape: {y.shape}")
|
| 3778 |
+
|
| 3779 |
if len(X) < 50: # Need sufficient data
|
| 3780 |
+
print(f"Insufficient data after preprocessing: {len(X)} samples")
|
| 3781 |
return np.array([]), np.array([])
|
| 3782 |
|
| 3783 |
# Initialize models
|
|
|
|
| 3814 |
pred = model.predict(X[-prediction_days:])
|
| 3815 |
uncertainty = np.std(y) * np.ones(prediction_days)
|
| 3816 |
|
| 3817 |
+
# Ensure prediction is the right length
|
| 3818 |
+
if len(pred) != prediction_days:
|
| 3819 |
+
print(f"Warning: {name} produced {len(pred)} predictions, expected {prediction_days}")
|
| 3820 |
+
if len(pred) > prediction_days:
|
| 3821 |
+
pred = pred[:prediction_days]
|
| 3822 |
+
uncertainty = uncertainty[:prediction_days]
|
| 3823 |
+
else:
|
| 3824 |
+
# Extend with last value
|
| 3825 |
+
last_val = pred[-1] if len(pred) > 0 else y[-1]
|
| 3826 |
+
pred = np.pad(pred, (0, prediction_days - len(pred)),
|
| 3827 |
+
mode='constant', constant_values=last_val)
|
| 3828 |
+
uncertainty = np.pad(uncertainty, (0, prediction_days - len(uncertainty)),
|
| 3829 |
+
mode='constant', constant_values=uncertainty[-1] if len(uncertainty) > 0 else np.std(y))
|
| 3830 |
+
|
| 3831 |
+
# Validate prediction
|
| 3832 |
+
if len(pred) == prediction_days and len(uncertainty) == prediction_days:
|
| 3833 |
+
predictions[name] = pred
|
| 3834 |
+
uncertainties[name] = uncertainty
|
| 3835 |
+
else:
|
| 3836 |
+
print(f"Warning: {name} prediction validation failed. Skipping.")
|
| 3837 |
+
continue
|
| 3838 |
|
| 3839 |
except Exception as e:
|
| 3840 |
print(f"Error training {name}: {str(e)}")
|
|
|
|
| 3843 |
if not predictions:
|
| 3844 |
return np.array([]), np.array([])
|
| 3845 |
|
| 3846 |
+
# Debug: Print prediction lengths
|
| 3847 |
+
print(f"Ensemble model debugging - Expected prediction_days: {prediction_days}")
|
| 3848 |
+
for name, pred in predictions.items():
|
| 3849 |
+
print(f" {name}: prediction length = {len(pred)}, uncertainty length = {len(uncertainties.get(name, []))}")
|
| 3850 |
+
|
| 3851 |
# Combine predictions using weighted average
|
| 3852 |
weights = {}
|
| 3853 |
for name in predictions.keys():
|
|
|
|
| 3869 |
|
| 3870 |
for name, pred in predictions.items():
|
| 3871 |
if name in weights:
|
| 3872 |
+
# Ensure prediction is the right length
|
| 3873 |
+
pred_array = np.array(pred)
|
| 3874 |
+
uncertainty_array = np.array(uncertainties[name])
|
| 3875 |
+
|
| 3876 |
+
# Handle different prediction lengths
|
| 3877 |
+
if len(pred_array) >= prediction_days:
|
| 3878 |
+
# Truncate to prediction_days
|
| 3879 |
+
pred_array = pred_array[:prediction_days]
|
| 3880 |
+
uncertainty_array = uncertainty_array[:prediction_days]
|
| 3881 |
+
elif len(pred_array) < prediction_days:
|
| 3882 |
+
# Extend with the last value
|
| 3883 |
+
last_pred = pred_array[-1] if len(pred_array) > 0 else 0
|
| 3884 |
+
last_uncertainty = uncertainty_array[-1] if len(uncertainty_array) > 0 else 1.0
|
| 3885 |
+
|
| 3886 |
+
# Pad with last values
|
| 3887 |
+
pred_array = np.pad(pred_array, (0, prediction_days - len(pred_array)),
|
| 3888 |
+
mode='constant', constant_values=last_pred)
|
| 3889 |
+
uncertainty_array = np.pad(uncertainty_array, (0, prediction_days - len(uncertainty_array)),
|
| 3890 |
+
mode='constant', constant_values=last_uncertainty)
|
| 3891 |
+
|
| 3892 |
+
# Ensure arrays are the correct shape
|
| 3893 |
+
if len(pred_array) != prediction_days:
|
| 3894 |
+
print(f"Warning: {name} prediction length mismatch. Expected {prediction_days}, got {len(pred_array)}")
|
| 3895 |
+
continue
|
| 3896 |
+
|
| 3897 |
+
if len(uncertainty_array) != prediction_days:
|
| 3898 |
+
print(f"Warning: {name} uncertainty length mismatch. Expected {prediction_days}, got {len(uncertainty_array)}")
|
| 3899 |
+
continue
|
| 3900 |
+
|
| 3901 |
+
# Add weighted contribution
|
| 3902 |
+
ensemble_pred += weights[name] * pred_array
|
| 3903 |
+
ensemble_uncertainty += weights[name] * uncertainty_array
|
| 3904 |
|
| 3905 |
return ensemble_pred, ensemble_uncertainty
|
| 3906 |
|
| 3907 |
except Exception as e:
|
| 3908 |
print(f"Enhanced ensemble model error: {str(e)}")
|
| 3909 |
+
print("Falling back to simple ensemble prediction...")
|
| 3910 |
+
|
| 3911 |
+
# Fallback: Simple ensemble using basic models
|
| 3912 |
+
try:
|
| 3913 |
+
# Use simple linear regression as fallback
|
| 3914 |
+
X = np.arange(len(df)).reshape(-1, 1)
|
| 3915 |
+
y = df['Close'].values
|
| 3916 |
+
|
| 3917 |
+
# Simple linear trend
|
| 3918 |
+
slope = np.polyfit(X.flatten(), y, 1)[0]
|
| 3919 |
+
last_price = y[-1]
|
| 3920 |
+
|
| 3921 |
+
# Generate simple predictions
|
| 3922 |
+
ensemble_pred = np.array([last_price + slope * i for i in range(1, prediction_days + 1)])
|
| 3923 |
+
ensemble_uncertainty = np.std(y) * np.ones(prediction_days)
|
| 3924 |
+
|
| 3925 |
+
return ensemble_pred, ensemble_uncertainty
|
| 3926 |
+
|
| 3927 |
+
except Exception as fallback_error:
|
| 3928 |
+
print(f"Fallback ensemble also failed: {str(fallback_error)}")
|
| 3929 |
+
return np.array([]), np.array([])
|
| 3930 |
|
| 3931 |
def calculate_volume_prediction_enhanced(df: pd.DataFrame, price_prediction: np.ndarray,
|
| 3932 |
covariate_data: Dict = None) -> Tuple[np.ndarray, np.ndarray]:
|