Spaces:
Runtime error
Runtime error
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()
|