Tonic commited on
Commit
737efc2
·
unverified ·
1 Parent(s): 9dc46d3

improve smoothing and attempt to solve discontinuity

Browse files
Files changed (1) hide show
  1. app.py +68 -11
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
- normalized_prices = scaler.fit_transform(context_window.reshape(-1, 1)).flatten()
 
 
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 between last actual and first prediction
639
  last_actual = prices[-1]
640
  first_pred = mean_pred[0]
641
- if abs(first_pred - last_actual) > max(1e-6, 0.05 * abs(last_actual)):
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
- normalized_volume = volume_scaler.fit_transform(context_window.reshape(-1, 1)).flatten()
 
 
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.05 * abs(last_actual)):
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
- normalized_rsi = rsi_scaler.fit_transform(context_window.reshape(-1, 1)).flatten()
 
 
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.05 * abs(last_actual)):
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.05 * abs(extended_mean_pred[-1])):
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
- normalized_macd = macd_scaler.fit_transform(context_window.reshape(-1, 1)).flatten()
 
 
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.05 * abs(last_actual)):
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()