# Import necessary libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_absolute_percentage_error
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.callbacks import EarlyStopping

# 1. Load and preprocess the data
file_path = r"C:\Users\jack8\OneDrive\stock cow ai\data\enhanced_stock_price_ma.csv"
data = pd.read_csv(file_path, parse_dates=['Date'])

# Display the first few rows and check for missing values
print(data.head())
print(data.isnull().sum())

# 2. Select features and target
# It's common to exclude the 'Date' column from features for modeling purposes
features = ['Opening Price', 'Highest Price', 'Lowest Price', 'Closing Price', 'MA_5', 'MA_20']
target = 'Closing Price'
data = data[features]

# Sort the data by date if not already sorted
# Assuming the original data is sorted; if not, uncomment the following line:
# data = data.sort_values('Date')

# Handle missing values if any (e.g., forward fill)
data.fillna(method='ffill', inplace=True)

# 3. Feature Scaling
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)

# 4. Create sequences for LSTM
def create_sequences(data, sequence_length):
    X = []
    y = []
    for i in range(sequence_length, len(data)):
        X.append(data[i-sequence_length:i])
        y.append(data[i][3])  # 'Closing Price' is the 4th feature (index 3)
    return np.array(X), np.array(y)

sequence_length = 70  # You can adjust this value
X, y = create_sequences(scaled_data, sequence_length)

# 5. Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, shuffle=False
)

# 6. Build the LSTM model
model = Sequential()
model.add(LSTM(units=100, return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(LSTM(units=100))
model.add(Dense(1))

# Compile the model
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_percentage_error'])

# 7. Implement Early Stopping
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)

# 8. Train the model
history = model.fit(
    X_train, y_train,
    epochs=100,
    batch_size=16,
    validation_split=0.1,
    callbacks=[early_stop],
    verbose=1
)

# 9. Make predictions
predictions = model.predict(X_test)

# Inverse transform the scaled data to get actual prices
# Since only 'Closing Price' was used as the target, we need to invert the scaling for that feature
# Create a scaler for the target
scaler_target = MinMaxScaler()
scaler_target.min_, scaler_target.scale_ = scaler.min_[3], scaler.scale_[3]

y_test_inverse = scaler_target.inverse_transform(y_test.reshape(-1, 1))
predictions_inverse = scaler_target.inverse_transform(predictions)

# 10. Calculate MAPE
mape = mean_absolute_percentage_error(y_test_inverse, predictions_inverse)
print(f"Mean Absolute Percentage Error (MAPE): {mape * 100:.2f}%")

# 11. Plot the results
plt.figure(figsize=(14, 7))
plt.plot(y_test_inverse, color='blue', label='Actual Closing Price')
plt.plot(predictions_inverse, color='red', label='Predicted Closing Price')
plt.title('Actual vs Predicted Closing Prices')
plt.xlabel('Time')
plt.ylabel('Closing Price')
plt.legend()
plt.show()

###幫我另外寫一個預測未來2周的股價