Spaces:
Paused
Paused
Tonic commited on
Commit ·
65bf228
1
Parent(s): a65d91d
attempt to predict technicals and volume
Browse files
app.py
CHANGED
|
@@ -620,6 +620,128 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
| 620 |
mean_pred = extended_mean_pred[:prediction_days * 96]
|
| 621 |
std_pred = extended_std_pred[:prediction_days * 96]
|
| 622 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 623 |
except Exception as e:
|
| 624 |
print(f"Chronos prediction error: {str(e)}")
|
| 625 |
print(f"Error type: {type(e)}")
|
|
@@ -701,6 +823,21 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
| 701 |
row=2, col=1
|
| 702 |
)
|
| 703 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 704 |
# Add volume
|
| 705 |
fig.add_trace(
|
| 706 |
go.Bar(x=df.index, y=df['Volume'], name='Volume',
|
|
@@ -708,6 +845,14 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
| 708 |
row=3, col=1
|
| 709 |
)
|
| 710 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
# Update layout with timeframe-specific settings
|
| 712 |
fig.update_layout(
|
| 713 |
title=f'{symbol} {timeframe} Analysis and Prediction',
|
|
@@ -730,6 +875,14 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
| 730 |
"strategy_used": strategy
|
| 731 |
})
|
| 732 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 733 |
return signals, fig
|
| 734 |
|
| 735 |
except Exception as e:
|
|
|
|
| 620 |
mean_pred = extended_mean_pred[:prediction_days * 96]
|
| 621 |
std_pred = extended_std_pred[:prediction_days * 96]
|
| 622 |
|
| 623 |
+
# Extend Chronos forecasting to volume and technical indicators
|
| 624 |
+
volume_pred = None
|
| 625 |
+
rsi_pred = None
|
| 626 |
+
macd_pred = None
|
| 627 |
+
|
| 628 |
+
try:
|
| 629 |
+
# Prepare volume data for Chronos
|
| 630 |
+
volume_data = df['Volume'].values
|
| 631 |
+
if len(volume_data) >= 64:
|
| 632 |
+
# Normalize volume data
|
| 633 |
+
volume_scaler = MinMaxScaler(feature_range=(-1, 1))
|
| 634 |
+
normalized_volume = volume_scaler.fit_transform(volume_data.reshape(-1, 1)).flatten()
|
| 635 |
+
|
| 636 |
+
# Use last 64 points for volume prediction
|
| 637 |
+
volume_context = normalized_volume[-64:]
|
| 638 |
+
volume_context_tensor = torch.tensor(volume_context, dtype=dtype, device=device)
|
| 639 |
+
if len(volume_context_tensor.shape) == 1:
|
| 640 |
+
volume_context_tensor = volume_context_tensor.unsqueeze(0)
|
| 641 |
+
|
| 642 |
+
# Predict volume
|
| 643 |
+
with torch.amp.autocast('cuda'):
|
| 644 |
+
volume_quantiles, volume_mean = pipe.predict_quantiles(
|
| 645 |
+
context=volume_context_tensor,
|
| 646 |
+
prediction_length=min(actual_prediction_length, 64),
|
| 647 |
+
quantile_levels=[0.1, 0.5, 0.9]
|
| 648 |
+
)
|
| 649 |
+
|
| 650 |
+
# Convert and denormalize volume predictions
|
| 651 |
+
volume_mean = volume_mean.detach().cpu().numpy()
|
| 652 |
+
volume_pred = volume_scaler.inverse_transform(volume_mean.reshape(-1, 1)).flatten()
|
| 653 |
+
|
| 654 |
+
# Extend volume predictions if needed
|
| 655 |
+
if len(volume_pred) < len(mean_pred):
|
| 656 |
+
last_volume = volume_pred[-1]
|
| 657 |
+
extension_length = len(mean_pred) - len(volume_pred)
|
| 658 |
+
volume_extension = np.full(extension_length, last_volume)
|
| 659 |
+
volume_pred = np.concatenate([volume_pred, volume_extension])
|
| 660 |
+
except Exception as e:
|
| 661 |
+
print(f"Volume prediction error: {str(e)}")
|
| 662 |
+
# Fallback: use historical average
|
| 663 |
+
avg_volume = df['Volume'].mean()
|
| 664 |
+
volume_pred = np.full(len(mean_pred), avg_volume)
|
| 665 |
+
|
| 666 |
+
try:
|
| 667 |
+
# Prepare RSI data for Chronos
|
| 668 |
+
rsi_data = df['RSI'].values
|
| 669 |
+
if len(rsi_data) >= 64 and not np.any(np.isnan(rsi_data)):
|
| 670 |
+
# RSI is already normalized (0-100), but we'll scale it to (-1, 1)
|
| 671 |
+
rsi_scaler = MinMaxScaler(feature_range=(-1, 1))
|
| 672 |
+
normalized_rsi = rsi_scaler.fit_transform(rsi_data.reshape(-1, 1)).flatten()
|
| 673 |
+
|
| 674 |
+
# Use last 64 points for RSI prediction
|
| 675 |
+
rsi_context = normalized_rsi[-64:]
|
| 676 |
+
rsi_context_tensor = torch.tensor(rsi_context, dtype=dtype, device=device)
|
| 677 |
+
if len(rsi_context_tensor.shape) == 1:
|
| 678 |
+
rsi_context_tensor = rsi_context_tensor.unsqueeze(0)
|
| 679 |
+
|
| 680 |
+
# Predict RSI
|
| 681 |
+
with torch.amp.autocast('cuda'):
|
| 682 |
+
rsi_quantiles, rsi_mean = pipe.predict_quantiles(
|
| 683 |
+
context=rsi_context_tensor,
|
| 684 |
+
prediction_length=min(actual_prediction_length, 64),
|
| 685 |
+
quantile_levels=[0.1, 0.5, 0.9]
|
| 686 |
+
)
|
| 687 |
+
|
| 688 |
+
# Convert and denormalize RSI predictions
|
| 689 |
+
rsi_mean = rsi_mean.detach().cpu().numpy()
|
| 690 |
+
rsi_pred = rsi_scaler.inverse_transform(rsi_mean.reshape(-1, 1)).flatten()
|
| 691 |
+
|
| 692 |
+
# Clamp RSI to valid range (0-100)
|
| 693 |
+
rsi_pred = np.clip(rsi_pred, 0, 100)
|
| 694 |
+
|
| 695 |
+
# Extend RSI predictions if needed
|
| 696 |
+
if len(rsi_pred) < len(mean_pred):
|
| 697 |
+
last_rsi = rsi_pred[-1]
|
| 698 |
+
extension_length = len(mean_pred) - len(rsi_pred)
|
| 699 |
+
rsi_extension = np.full(extension_length, last_rsi)
|
| 700 |
+
rsi_pred = np.concatenate([rsi_pred, rsi_extension])
|
| 701 |
+
except Exception as e:
|
| 702 |
+
print(f"RSI prediction error: {str(e)}")
|
| 703 |
+
# Fallback: use last known RSI value
|
| 704 |
+
last_rsi = df['RSI'].iloc[-1]
|
| 705 |
+
rsi_pred = np.full(len(mean_pred), last_rsi)
|
| 706 |
+
|
| 707 |
+
try:
|
| 708 |
+
# Prepare MACD data for Chronos
|
| 709 |
+
macd_data = df['MACD'].values
|
| 710 |
+
if len(macd_data) >= 64 and not np.any(np.isnan(macd_data)):
|
| 711 |
+
# Normalize MACD data
|
| 712 |
+
macd_scaler = MinMaxScaler(feature_range=(-1, 1))
|
| 713 |
+
normalized_macd = macd_scaler.fit_transform(macd_data.reshape(-1, 1)).flatten()
|
| 714 |
+
|
| 715 |
+
# Use last 64 points for MACD prediction
|
| 716 |
+
macd_context = normalized_macd[-64:]
|
| 717 |
+
macd_context_tensor = torch.tensor(macd_context, dtype=dtype, device=device)
|
| 718 |
+
if len(macd_context_tensor.shape) == 1:
|
| 719 |
+
macd_context_tensor = macd_context_tensor.unsqueeze(0)
|
| 720 |
+
|
| 721 |
+
# Predict MACD
|
| 722 |
+
with torch.amp.autocast('cuda'):
|
| 723 |
+
macd_quantiles, macd_mean = pipe.predict_quantiles(
|
| 724 |
+
context=macd_context_tensor,
|
| 725 |
+
prediction_length=min(actual_prediction_length, 64),
|
| 726 |
+
quantile_levels=[0.1, 0.5, 0.9]
|
| 727 |
+
)
|
| 728 |
+
|
| 729 |
+
# Convert and denormalize MACD predictions
|
| 730 |
+
macd_mean = macd_mean.detach().cpu().numpy()
|
| 731 |
+
macd_pred = macd_scaler.inverse_transform(macd_mean.reshape(-1, 1)).flatten()
|
| 732 |
+
|
| 733 |
+
# Extend MACD predictions if needed
|
| 734 |
+
if len(macd_pred) < len(mean_pred):
|
| 735 |
+
last_macd = macd_pred[-1]
|
| 736 |
+
extension_length = len(mean_pred) - len(macd_pred)
|
| 737 |
+
macd_extension = np.full(extension_length, last_macd)
|
| 738 |
+
macd_pred = np.concatenate([macd_pred, macd_extension])
|
| 739 |
+
except Exception as e:
|
| 740 |
+
print(f"MACD prediction error: {str(e)}")
|
| 741 |
+
# Fallback: use last known MACD value
|
| 742 |
+
last_macd = df['MACD'].iloc[-1]
|
| 743 |
+
macd_pred = np.full(len(mean_pred), last_macd)
|
| 744 |
+
|
| 745 |
except Exception as e:
|
| 746 |
print(f"Chronos prediction error: {str(e)}")
|
| 747 |
print(f"Error type: {type(e)}")
|
|
|
|
| 823 |
row=2, col=1
|
| 824 |
)
|
| 825 |
|
| 826 |
+
# Add predicted technical indicators if available
|
| 827 |
+
if rsi_pred is not None:
|
| 828 |
+
fig.add_trace(
|
| 829 |
+
go.Scatter(x=pred_dates, y=rsi_pred, name='Predicted RSI',
|
| 830 |
+
line=dict(color='purple', dash='dash')),
|
| 831 |
+
row=2, col=1
|
| 832 |
+
)
|
| 833 |
+
|
| 834 |
+
if macd_pred is not None:
|
| 835 |
+
fig.add_trace(
|
| 836 |
+
go.Scatter(x=pred_dates, y=macd_pred, name='Predicted MACD',
|
| 837 |
+
line=dict(color='orange', dash='dash')),
|
| 838 |
+
row=2, col=1
|
| 839 |
+
)
|
| 840 |
+
|
| 841 |
# Add volume
|
| 842 |
fig.add_trace(
|
| 843 |
go.Bar(x=df.index, y=df['Volume'], name='Volume',
|
|
|
|
| 845 |
row=3, col=1
|
| 846 |
)
|
| 847 |
|
| 848 |
+
# Add predicted volume if available
|
| 849 |
+
if volume_pred is not None:
|
| 850 |
+
fig.add_trace(
|
| 851 |
+
go.Bar(x=pred_dates, y=volume_pred, name='Predicted Volume',
|
| 852 |
+
marker_color='red', opacity=0.7),
|
| 853 |
+
row=3, col=1
|
| 854 |
+
)
|
| 855 |
+
|
| 856 |
# Update layout with timeframe-specific settings
|
| 857 |
fig.update_layout(
|
| 858 |
title=f'{symbol} {timeframe} Analysis and Prediction',
|
|
|
|
| 875 |
"strategy_used": strategy
|
| 876 |
})
|
| 877 |
|
| 878 |
+
# Add predicted indicators to signals if available
|
| 879 |
+
if volume_pred is not None:
|
| 880 |
+
signals["predicted_volume"] = volume_pred.tolist()
|
| 881 |
+
if rsi_pred is not None:
|
| 882 |
+
signals["predicted_rsi"] = rsi_pred.tolist()
|
| 883 |
+
if macd_pred is not None:
|
| 884 |
+
signals["predicted_macd"] = macd_pred.tolist()
|
| 885 |
+
|
| 886 |
return signals, fig
|
| 887 |
|
| 888 |
except Exception as e:
|