Spaces:
Running
on
Zero
Running
on
Zero
improve smoothing and attempt to solve discontinuity
Browse files
app.py
CHANGED
@@ -400,9 +400,13 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
400 |
# Prepare data for Chronos
|
401 |
prices = df['Close'].values
|
402 |
window_size = 64 # Chronos context window size
|
|
|
|
|
403 |
context_window = prices[-window_size:]
|
404 |
scaler = MinMaxScaler(feature_range=(-1, 1))
|
405 |
-
|
|
|
|
|
406 |
|
407 |
# Ensure we have enough data points
|
408 |
min_data_points = window_size
|
@@ -635,11 +639,24 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
635 |
# Calculate standard deviation from quantiles
|
636 |
std_pred = (upper_bound - lower_bound) / (2 * 1.645)
|
637 |
|
638 |
-
# Check for discontinuity
|
639 |
last_actual = prices[-1]
|
640 |
first_pred = mean_pred[0]
|
641 |
-
if abs(first_pred - last_actual) > max(1e-6, 0.
|
642 |
print(f"Warning: Discontinuity detected between last actual ({last_actual}) and first prediction ({first_pred})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
643 |
|
644 |
# If we had to limit the prediction length, extend the prediction recursively
|
645 |
if actual_prediction_length < trim_length:
|
@@ -711,9 +728,12 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
711 |
if len(volume_data) >= 64:
|
712 |
# Normalize volume data
|
713 |
window_size = 64
|
|
|
714 |
context_window = volume_data[-window_size:]
|
715 |
volume_scaler = MinMaxScaler(feature_range=(-1, 1))
|
716 |
-
|
|
|
|
|
717 |
if len(normalized_volume) < window_size:
|
718 |
padding = np.full(window_size - len(normalized_volume), normalized_volume[-1])
|
719 |
normalized_volume = np.concatenate([padding, normalized_volume])
|
@@ -736,9 +756,21 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
736 |
std_pred_vol = (upper_bound - lower_bound) / (2 * 1.645)
|
737 |
last_actual = volume_data[-1]
|
738 |
first_pred = volume_pred[0]
|
739 |
-
if abs(first_pred - last_actual) > max(1e-6, 0.
|
740 |
print(f"Warning: Discontinuity detected between last actual volume ({last_actual}) and first prediction ({first_pred})")
|
741 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
742 |
# Extend volume predictions if needed
|
743 |
if actual_prediction_length < trim_length:
|
744 |
extended_mean_pred = volume_pred.copy()
|
@@ -802,9 +834,12 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
802 |
if len(rsi_data) >= 64 and not np.any(np.isnan(rsi_data)):
|
803 |
# RSI is already normalized (0-100), but we'll scale it to (-1, 1)
|
804 |
window_size = 64
|
|
|
805 |
context_window = rsi_data[-window_size:]
|
806 |
rsi_scaler = MinMaxScaler(feature_range=(-1, 1))
|
807 |
-
|
|
|
|
|
808 |
if len(normalized_rsi) < window_size:
|
809 |
padding = np.full(window_size - len(normalized_rsi), normalized_rsi[-1])
|
810 |
normalized_rsi = np.concatenate([padding, normalized_rsi])
|
@@ -830,8 +865,14 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
830 |
rsi_pred = np.clip(rsi_pred, 0, 100)
|
831 |
last_actual = rsi_data[-1]
|
832 |
first_pred = rsi_pred[0]
|
833 |
-
if abs(first_pred - last_actual) > max(1e-6, 0.
|
834 |
print(f"Warning: Discontinuity detected between last actual RSI ({last_actual}) and first prediction ({first_pred})")
|
|
|
|
|
|
|
|
|
|
|
|
|
835 |
# Extend RSI predictions if needed
|
836 |
if actual_prediction_length < trim_length:
|
837 |
extended_mean_pred = rsi_pred.copy()
|
@@ -873,7 +914,7 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
873 |
next_upper = rsi_scaler.inverse_transform(next_quantiles[0, :, 2].reshape(-1, 1)).flatten()
|
874 |
next_std_pred = (next_upper - next_lower) / (2 * 1.645)
|
875 |
next_mean_pred = np.clip(next_mean_pred, 0, 100)
|
876 |
-
if abs(next_mean_pred[0] - extended_mean_pred[-1]) > max(1e-6, 0.
|
877 |
print(f"Warning: Discontinuity detected between last RSI prediction ({extended_mean_pred[-1]}) and next prediction ({next_mean_pred[0]})")
|
878 |
extended_mean_pred = np.concatenate([extended_mean_pred, next_mean_pred])
|
879 |
extended_std_pred = np.concatenate([extended_std_pred, next_std_pred])
|
@@ -895,9 +936,12 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
895 |
if len(macd_data) >= 64 and not np.any(np.isnan(macd_data)):
|
896 |
# Normalize MACD data
|
897 |
window_size = 64
|
|
|
898 |
context_window = macd_data[-window_size:]
|
899 |
macd_scaler = MinMaxScaler(feature_range=(-1, 1))
|
900 |
-
|
|
|
|
|
901 |
if len(normalized_macd) < window_size:
|
902 |
padding = np.full(window_size - len(normalized_macd), normalized_macd[-1])
|
903 |
normalized_macd = np.concatenate([padding, normalized_macd])
|
@@ -923,8 +967,21 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
923 |
first_pred = macd_pred[0]
|
924 |
|
925 |
# Extend MACD predictions if needed
|
926 |
-
if abs(first_pred - last_actual) > max(1e-6, 0.
|
927 |
print(f"Warning: Discontinuity detected between last actual MACD ({last_actual}) and first prediction ({first_pred})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
928 |
if actual_prediction_length < trim_length:
|
929 |
extended_mean_pred = macd_pred.copy()
|
930 |
extended_std_pred = std_pred_macd.copy()
|
|
|
400 |
# Prepare data for Chronos
|
401 |
prices = df['Close'].values
|
402 |
window_size = 64 # Chronos context window size
|
403 |
+
# Use a larger range for scaler fitting to get better normalization
|
404 |
+
scaler_range = min(len(prices), window_size * 2) # Use up to 128 points for scaler
|
405 |
context_window = prices[-window_size:]
|
406 |
scaler = MinMaxScaler(feature_range=(-1, 1))
|
407 |
+
# Fit scaler on a larger range for better normalization
|
408 |
+
scaler.fit(prices[-scaler_range:].reshape(-1, 1))
|
409 |
+
normalized_prices = scaler.transform(context_window.reshape(-1, 1)).flatten()
|
410 |
|
411 |
# Ensure we have enough data points
|
412 |
min_data_points = window_size
|
|
|
639 |
# Calculate standard deviation from quantiles
|
640 |
std_pred = (upper_bound - lower_bound) / (2 * 1.645)
|
641 |
|
642 |
+
# Check for discontinuity and apply continuity correction
|
643 |
last_actual = prices[-1]
|
644 |
first_pred = mean_pred[0]
|
645 |
+
if abs(first_pred - last_actual) > max(1e-6, 0.005 * abs(last_actual)): # Further reduced threshold
|
646 |
print(f"Warning: Discontinuity detected between last actual ({last_actual}) and first prediction ({first_pred})")
|
647 |
+
# Apply continuity correction to first prediction
|
648 |
+
mean_pred[0] = last_actual
|
649 |
+
# Adjust subsequent predictions to maintain trend with smoothing
|
650 |
+
if len(mean_pred) > 1:
|
651 |
+
# Calculate the trend from the original prediction
|
652 |
+
original_trend = mean_pred[1] - first_pred
|
653 |
+
# Apply the same trend but starting from the last actual value
|
654 |
+
for i in range(1, len(mean_pred)):
|
655 |
+
mean_pred[i] = last_actual + original_trend * i
|
656 |
+
# Add small smoothing to prevent drift
|
657 |
+
if i > 1:
|
658 |
+
smoothing_factor = 0.95
|
659 |
+
mean_pred[i] = smoothing_factor * mean_pred[i] + (1 - smoothing_factor) * mean_pred[i-1]
|
660 |
|
661 |
# If we had to limit the prediction length, extend the prediction recursively
|
662 |
if actual_prediction_length < trim_length:
|
|
|
728 |
if len(volume_data) >= 64:
|
729 |
# Normalize volume data
|
730 |
window_size = 64
|
731 |
+
scaler_range = min(len(volume_data), window_size * 2)
|
732 |
context_window = volume_data[-window_size:]
|
733 |
volume_scaler = MinMaxScaler(feature_range=(-1, 1))
|
734 |
+
# Fit scaler on a larger range for better normalization
|
735 |
+
volume_scaler.fit(volume_data[-scaler_range:].reshape(-1, 1))
|
736 |
+
normalized_volume = volume_scaler.transform(context_window.reshape(-1, 1)).flatten()
|
737 |
if len(normalized_volume) < window_size:
|
738 |
padding = np.full(window_size - len(normalized_volume), normalized_volume[-1])
|
739 |
normalized_volume = np.concatenate([padding, normalized_volume])
|
|
|
756 |
std_pred_vol = (upper_bound - lower_bound) / (2 * 1.645)
|
757 |
last_actual = volume_data[-1]
|
758 |
first_pred = volume_pred[0]
|
759 |
+
if abs(first_pred - last_actual) > max(1e-6, 0.005 * abs(last_actual)): # Further reduced threshold
|
760 |
print(f"Warning: Discontinuity detected between last actual volume ({last_actual}) and first prediction ({first_pred})")
|
761 |
+
# Apply continuity correction
|
762 |
+
volume_pred[0] = last_actual
|
763 |
+
# Adjust subsequent predictions to maintain trend with smoothing
|
764 |
+
if len(volume_pred) > 1:
|
765 |
+
# Calculate the trend from the original prediction
|
766 |
+
original_trend = volume_pred[1] - first_pred
|
767 |
+
# Apply the same trend but starting from the last actual value
|
768 |
+
for i in range(1, len(volume_pred)):
|
769 |
+
volume_pred[i] = last_actual + original_trend * i
|
770 |
+
# Add small smoothing to prevent drift
|
771 |
+
if i > 1:
|
772 |
+
smoothing_factor = 0.95
|
773 |
+
volume_pred[i] = smoothing_factor * volume_pred[i] + (1 - smoothing_factor) * volume_pred[i-1]
|
774 |
# Extend volume predictions if needed
|
775 |
if actual_prediction_length < trim_length:
|
776 |
extended_mean_pred = volume_pred.copy()
|
|
|
834 |
if len(rsi_data) >= 64 and not np.any(np.isnan(rsi_data)):
|
835 |
# RSI is already normalized (0-100), but we'll scale it to (-1, 1)
|
836 |
window_size = 64
|
837 |
+
scaler_range = min(len(rsi_data), window_size * 2)
|
838 |
context_window = rsi_data[-window_size:]
|
839 |
rsi_scaler = MinMaxScaler(feature_range=(-1, 1))
|
840 |
+
# Fit scaler on a larger range for better normalization
|
841 |
+
rsi_scaler.fit(rsi_data[-scaler_range:].reshape(-1, 1))
|
842 |
+
normalized_rsi = rsi_scaler.transform(context_window.reshape(-1, 1)).flatten()
|
843 |
if len(normalized_rsi) < window_size:
|
844 |
padding = np.full(window_size - len(normalized_rsi), normalized_rsi[-1])
|
845 |
normalized_rsi = np.concatenate([padding, normalized_rsi])
|
|
|
865 |
rsi_pred = np.clip(rsi_pred, 0, 100)
|
866 |
last_actual = rsi_data[-1]
|
867 |
first_pred = rsi_pred[0]
|
868 |
+
if abs(first_pred - last_actual) > max(1e-6, 0.005 * abs(last_actual)): # Further reduced threshold
|
869 |
print(f"Warning: Discontinuity detected between last actual RSI ({last_actual}) and first prediction ({first_pred})")
|
870 |
+
# Apply continuity correction
|
871 |
+
rsi_pred[0] = last_actual
|
872 |
+
if len(rsi_pred) > 1:
|
873 |
+
trend = rsi_pred[1] - first_pred
|
874 |
+
rsi_pred[1:] = rsi_pred[1:] - first_pred + last_actual
|
875 |
+
rsi_pred = np.clip(rsi_pred, 0, 100) # Re-clip after adjustment
|
876 |
# Extend RSI predictions if needed
|
877 |
if actual_prediction_length < trim_length:
|
878 |
extended_mean_pred = rsi_pred.copy()
|
|
|
914 |
next_upper = rsi_scaler.inverse_transform(next_quantiles[0, :, 2].reshape(-1, 1)).flatten()
|
915 |
next_std_pred = (next_upper - next_lower) / (2 * 1.645)
|
916 |
next_mean_pred = np.clip(next_mean_pred, 0, 100)
|
917 |
+
if abs(next_mean_pred[0] - extended_mean_pred[-1]) > max(1e-6, 0.005 * abs(extended_mean_pred[-1])):
|
918 |
print(f"Warning: Discontinuity detected between last RSI prediction ({extended_mean_pred[-1]}) and next prediction ({next_mean_pred[0]})")
|
919 |
extended_mean_pred = np.concatenate([extended_mean_pred, next_mean_pred])
|
920 |
extended_std_pred = np.concatenate([extended_std_pred, next_std_pred])
|
|
|
936 |
if len(macd_data) >= 64 and not np.any(np.isnan(macd_data)):
|
937 |
# Normalize MACD data
|
938 |
window_size = 64
|
939 |
+
scaler_range = min(len(macd_data), window_size * 2)
|
940 |
context_window = macd_data[-window_size:]
|
941 |
macd_scaler = MinMaxScaler(feature_range=(-1, 1))
|
942 |
+
# Fit scaler on a larger range for better normalization
|
943 |
+
macd_scaler.fit(macd_data[-scaler_range:].reshape(-1, 1))
|
944 |
+
normalized_macd = macd_scaler.transform(context_window.reshape(-1, 1)).flatten()
|
945 |
if len(normalized_macd) < window_size:
|
946 |
padding = np.full(window_size - len(normalized_macd), normalized_macd[-1])
|
947 |
normalized_macd = np.concatenate([padding, normalized_macd])
|
|
|
967 |
first_pred = macd_pred[0]
|
968 |
|
969 |
# Extend MACD predictions if needed
|
970 |
+
if abs(first_pred - last_actual) > max(1e-6, 0.005 * abs(last_actual)): # Further reduced threshold
|
971 |
print(f"Warning: Discontinuity detected between last actual MACD ({last_actual}) and first prediction ({first_pred})")
|
972 |
+
# Apply continuity correction
|
973 |
+
macd_pred[0] = last_actual
|
974 |
+
# Adjust subsequent predictions to maintain trend with smoothing
|
975 |
+
if len(macd_pred) > 1:
|
976 |
+
# Calculate the trend from the original prediction
|
977 |
+
original_trend = macd_pred[1] - first_pred
|
978 |
+
# Apply the same trend but starting from the last actual value
|
979 |
+
for i in range(1, len(macd_pred)):
|
980 |
+
macd_pred[i] = last_actual + original_trend * i
|
981 |
+
# Add small smoothing to prevent drift
|
982 |
+
if i > 1:
|
983 |
+
smoothing_factor = 0.95
|
984 |
+
macd_pred[i] = smoothing_factor * macd_pred[i] + (1 - smoothing_factor) * macd_pred[i-1]
|
985 |
if actual_prediction_length < trim_length:
|
986 |
extended_mean_pred = macd_pred.copy()
|
987 |
extended_std_pred = std_pred_macd.copy()
|