|
|
import pandas as pd |
|
|
import numpy as np |
|
|
from sklearn.preprocessing import MinMaxScaler |
|
|
from tensorflow.keras.models import Sequential |
|
|
from tensorflow.keras.layers import LSTM, Dense, Dropout |
|
|
|
|
|
|
|
|
def preprocess_data_for_deep_mql(df: pd.DataFrame, look_back: int = 60, features_cols=['Close', 'Volume'], target_col='Close'): |
|
|
""" |
|
|
Prepares data for a deep learning model (e.g., LSTM) for MQL-like tasks. |
|
|
- Scales features. |
|
|
- Creates sequences for time series forecasting. |
|
|
""" |
|
|
df_copy = df.copy() |
|
|
|
|
|
|
|
|
df_copy['returns'] = df_copy['Close'].pct_change() |
|
|
df_copy['ma10'] = df_copy['Close'].rolling(window=10).mean() |
|
|
df_copy['ma30'] = df_copy['Close'].rolling(window=30).mean() |
|
|
df_copy = df_copy.dropna() |
|
|
|
|
|
all_cols = list(set(features_cols + [target_col] + ['returns', 'ma10', 'ma30'])) |
|
|
data_to_scale = df_copy[all_cols].values |
|
|
|
|
|
scaler = MinMaxScaler(feature_range=(0, 1)) |
|
|
scaled_data = scaler.fit_transform(data_to_scale) |
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
scaled_df_cols = df_copy[all_cols].columns.tolist() |
|
|
target_idx_in_scaled = scaled_df_cols.index(target_col) |
|
|
except AttributeError: |
|
|
|
|
|
|
|
|
|
|
|
if target_col in features_cols: |
|
|
target_idx_in_scaled = features_cols.index(target_col) |
|
|
elif target_col == 'returns': |
|
|
target_idx_in_scaled = len(features_cols) |
|
|
elif target_col == 'ma10': |
|
|
target_idx_in_scaled = len(features_cols) + 1 |
|
|
elif target_col == 'ma30': |
|
|
target_idx_in_scaled = len(features_cols) + 2 |
|
|
else: |
|
|
print(f"Warning: Target column '{target_col}' not reliably found in scaled data. Defaulting to index 0.") |
|
|
target_idx_in_scaled = 0 |
|
|
|
|
|
|
|
|
X, y = [], [] |
|
|
for i in range(look_back, len(scaled_data)): |
|
|
X.append(scaled_data[i-look_back:i]) |
|
|
y.append(scaled_data[i, target_idx_in_scaled]) |
|
|
|
|
|
return np.array(X), np.array(y), scaler, df_copy[all_cols].columns.tolist() |
|
|
|
|
|
def create_deep_mql_model(input_shape): |
|
|
""" |
|
|
Creates a Deep Learning model (LSTM example) for MQL-like tasks. |
|
|
This is a basic example and can be significantly enhanced. |
|
|
""" |
|
|
model = Sequential([ |
|
|
LSTM(units=50, return_sequences=True, input_shape=input_shape), |
|
|
Dropout(0.2), |
|
|
LSTM(units=50, return_sequences=False), |
|
|
Dropout(0.2), |
|
|
Dense(units=25, activation='relu'), |
|
|
Dense(units=1) |
|
|
]) |
|
|
model.compile(optimizer='adam', loss='mean_squared_error') |
|
|
return model |
|
|
|
|
|
def generate_trading_signals(model, data_X, scaler, last_known_price, threshold=0.005): |
|
|
""" |
|
|
Generates trading signals based on model predictions. |
|
|
- Predicts next step. |
|
|
- Compares prediction with current price to generate signal. |
|
|
|
|
|
Signal: 1 (Buy), -1 (Sell), 0 (Hold) |
|
|
""" |
|
|
|
|
|
|
|
|
if data_X.ndim == 2: |
|
|
data_X = np.expand_dims(data_X, axis=0) |
|
|
|
|
|
predicted_scaled_value = model.predict(data_X) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
num_features = data_X.shape[2] |
|
|
dummy_array = np.zeros((len(predicted_scaled_value), num_features)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
target_column_index_in_scaler = 0 |
|
|
dummy_array[:, target_column_index_in_scaler] = predicted_scaled_value.ravel() |
|
|
|
|
|
try: |
|
|
predicted_value = scaler.inverse_transform(dummy_array)[:, target_column_index_in_scaler] |
|
|
except ValueError as e: |
|
|
print(f"Error during inverse_transform: {e}") |
|
|
print("Ensure dummy_array shape matches scaler's n_features_in_.") |
|
|
print(f"dummy_array shape: {dummy_array.shape}, scaler.n_features_in_: {scaler.n_features_in_}") |
|
|
|
|
|
return 0 |
|
|
|
|
|
|
|
|
signal = 0 |
|
|
if predicted_value > last_known_price * (1 + threshold): |
|
|
signal = 1 |
|
|
elif predicted_value < last_known_price * (1 - threshold): |
|
|
signal = -1 |
|
|
return signal, predicted_value[0] |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dates_mql = pd.date_range(start='2022-01-01', periods=500, freq='B') |
|
|
data_mql_np = np.random.rand(500, 5) * 150 + 50 |
|
|
raw_data_mql = pd.DataFrame(data_mql_np, index=dates_mql, columns=['Open', 'High', 'Low', 'Close', 'Volume']) |
|
|
raw_data_mql['Close'] = raw_data_mql['Close'] + np.sin(np.linspace(0, 20, 500)) * 20 |
|
|
|
|
|
if not raw_data_mql.empty: |
|
|
look_back_mql = 60 |
|
|
|
|
|
features_mql = ['Close', 'Volume', 'Open', 'High', 'Low'] |
|
|
target_mql = 'Close' |
|
|
|
|
|
X_mql, y_mql, scaler_mql, scaled_cols_mql = preprocess_data_for_deep_mql( |
|
|
raw_data_mql, |
|
|
look_back=look_back_mql, |
|
|
features_cols=features_mql, |
|
|
target_col=target_mql |
|
|
) |
|
|
|
|
|
if X_mql.shape[0] > 0: |
|
|
print(f"X_mql shape: {X_mql.shape}, y_mql shape: {y_mql.shape}") |
|
|
|
|
|
|
|
|
model_mql = create_deep_mql_model(input_shape=(X_mql.shape[1], X_mql.shape[2])) |
|
|
print("Training DeepMQL model (example)...") |
|
|
|
|
|
train_size = int(len(X_mql) * 0.8) |
|
|
X_train_mql, y_train_mql = X_mql[:train_size], y_mql[:train_size] |
|
|
|
|
|
|
|
|
if y_train_mql.ndim == 1: |
|
|
y_train_mql = y_train_mql.reshape(-1, 1) |
|
|
|
|
|
model_mql.fit(X_train_mql, y_train_mql, epochs=10, batch_size=32, verbose=1) |
|
|
print("DeepMQL model trained.") |
|
|
|
|
|
|
|
|
|
|
|
if len(X_mql) > train_size: |
|
|
last_sequence = X_mql[-1] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
original_close_series = raw_data_mql['Close'].iloc[len(raw_data_mql) - len(X_mql) + X_mql.shape[1] -1 - (len(X_mql) - (np.where(X_mql == last_sequence)[0][0])) : len(raw_data_mql) - (len(X_mql) - (np.where(X_mql == last_sequence)[0][0]))] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
last_actual_close_price = raw_data_mql[target_mql].iloc[-1] |
|
|
|
|
|
|
|
|
print(f"\nGenerating signal based on last sequence (shape: {last_sequence.shape})...") |
|
|
print(f"Last actual close price for reference: {last_actual_close_price}") |
|
|
|
|
|
signal, predicted_price = generate_trading_signals( |
|
|
model_mql, |
|
|
last_sequence, |
|
|
scaler_mql, |
|
|
last_actual_close_price, |
|
|
threshold=0.001 |
|
|
) |
|
|
print(f"Predicted Next '{target_mql}': {predicted_price:.2f}") |
|
|
if signal == 1: |
|
|
print("Signal: BUY") |
|
|
elif signal == -1: |
|
|
print("Signal: SELL") |
|
|
else: |
|
|
print("Signal: HOLD") |
|
|
else: |
|
|
print("Not enough data to generate a signal after training split.") |
|
|
else: |
|
|
print("X_mql is empty. Check preprocessing for DeepMQL.") |
|
|
else: |
|
|
print("Raw data for MQL is empty. Check data fetching.") |