import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers import Activation
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score
import csv
#import Fuzzification
#from keras.callbacks import EarlyStopping

def data_split(df):
    print(df.shape)
    column=['Close','Open', 'High', 'Low', 'Volume', 'Rpos', 'Rsize']
    df2=df[column].dropna()
    train_size=int(0.8*df.shape[0])
    test_size=int(df.shape[0]-train_size)
    X1 = df2[['Close']].values
    y = df2[['Close']].values
    X1_train,y_train=X1[0:train_size],y[0:train_size]
    X1_test,y_test=X1[train_size:],y[train_size:]
    return [X1_train,y_train,X1_test,y_test,train_size,test_size,y]


def LSTM_model(unit,X1_train, y_train,X1_test, y_test,batch_size,epochs):  #100%历史数据
    # Stack LSTM1
    regressor1 = Sequential()
    # Adding the first LSTM layer and some Dropout regularisation
    regressor1.add(LSTM(units=unit, input_shape=(X1_train.shape[1], X1_train.shape[2]), kernel_initializer='zeros',
                        return_sequences=False))  # ,activation='tanh' ,kernel_initializer='zeros',
    regressor1.add(Dropout(0.2))
    regressor1.add(Dense(units=1))
    regressor1.add(Activation("linear"))
    # Compiling the RNN
    regressor1.compile(optimizer='adam', loss='mean_squared_error')
    # es =EarlyStopping(monitor="val_loss", mode="min", patience=20, verbose=1,min_delta=0.0001)
    print(regressor1.summary())
    # Fitting the RNN to the Training set
    regressor1.fit(X1_train, y_train, batch_size, epochs, validation_split=0.2, verbose=0)#,callbacks=[es]
    return regressor1



def mape(y_true, y_pred):
    return np.mean(np.abs(( y_true- y_pred) / y_true)) * 100




if __name__ == '__main__':
    data1 = pd.read_csv('C:/Users/Big Data/Desktop/output/实验2/fuzzy2/IXIC.csv', parse_dates=['Date'], index_col=0,
                        encoding='utf-8')
    df = data1.reset_index()
    df = df.dropna()
    seq_len=11
    X1_train,y_train,X1_test,y_test,train_size,test_size,y= data_split(df)
    scaler = MinMaxScaler(feature_range=(0, 1))
    X1_train = scaler.fit_transform(X1_train)
    a = scaler.fit(y_train)
    y_train = scaler.fit_transform(y_train)
    X1_test = scaler.fit_transform(X1_test)
    b = scaler.fit(y_test)
    y_test = scaler.fit_transform(y_test)



    #结果比较
    X_train1, y = [], []
    for i in range(seq_len, X1_train.shape[0]):
        X_train1.append(X1_train[i - seq_len:i, :])
        y.append(y_train[i, 0])
    X1_train,  y_train = np.array(X_train1), np.array(y)

    X_test1,  y = [], []
    for i in range(seq_len, X1_test.shape[0]):
        X_test1.append(X1_test[i - seq_len:i, :])
        y.append(y_test[i, 0])
    X1_test,  y_test = np.array(X_test1),  np.array(y)
    regressor1 = LSTM_model(38, X1_train, y_train,X1_test,  y_test, 32, 100)
    plt.plot(regressor1.history.history['loss'], label='train')
    plt.plot(regressor1.history.history['val_loss'], label='val')
    plt.legend()
    plt.show()

    #训练集
    y_train_pred= regressor1.predict(X1_train)
    #测试集
    y_test_pred= regressor1.predict(X1_test)

    print('=============训练集===============')
    print("The R2 score on the Train set is:\t{:0.8f}".format(r2_score(y_train, y_train_pred)))
    print("The MSE on the Train set is:\t{:0.8f}".format(mean_squared_error(y_train, y_train_pred)))
    print("The MAE on the Train set is:\t{:0.8f}".format(mean_absolute_error(y_train, y_train_pred)))
    print('=============测试集===============')
    print("The R2 score on the Test set is:\t{:0.8f}".format(r2_score(y_test, y_test_pred)))
    print("The MSE on the Test set is:\t{:0.8f}".format(mean_squared_error(y_test, y_test_pred)))
    print("The MAE on the Test set is:\t{:0.8f}".format(mean_absolute_error(y_test, y_test_pred)))




    #逆标准化之后的结果
    y_train = y_train.reshape(-1, 1)
    y_train = a.inverse_transform(y_train)
    y_train_pred = a.inverse_transform(y_train_pred)
    # print(y_train.shape)
    # print(y_train_pred.shape)
    plt.figure(figsize=(10, 4))
    plt.plot(y_train, color='red')
    plt.plot(y_train_pred, color='blue',
             label='Predicted Price By LSTM(inverse_scale)On Train dataset')
    plt.xlabel('Time')
    plt.ylabel('Price')
    plt.legend()
    plt.show()
    rmse1 = np.sqrt(mean_squared_error(y_train, y_train_pred))
    mape1 = mape(y_train ,y_train_pred)
    print('=============训练集===============')
    print("The R2 score on the Train set is:\t{:0.8f}".format(r2_score(y_train, y_train_pred)))
    print("The MSE on the Train set is:\t{:0.8f}".format(mean_squared_error(y_train, y_train_pred)))
    print("The RMSE on the Train set is:\t{:0.8f}".format(rmse1))
    print("The MAPE on the Train set is:\t{:0.8f}".format(mape1))
    print("The MAE on the Train set is:\t{:0.8f}".format(mean_absolute_error(y_train, y_train_pred)))

    y_test = y_test.reshape(-1, 1)
    y_test = b.inverse_transform(y_test)
    y_test_pred = b.inverse_transform(y_test_pred)
    plt.figure(figsize=(10, 4))
    plt.plot(y_test, color='red')
    plt.plot(y_test_pred, color='blue',
             label='Predicted Price By LSTM(inverse_scale)On Test dataset')
    plt.xlabel('Time')
    plt.ylabel('Price')
    plt.legend()
    plt.show()
    rmse2 = np.sqrt(mean_squared_error(y_test, y_test_pred))
    mape2 = mape(y_test ,y_test_pred)
    print('=============测试集===============')
    print("The R2 score on the Test set is:\t{:0.8f}".format(r2_score(y_test, y_test_pred)))
    print("The MSE on the Test set is:\t{:0.8f}".format(mean_squared_error(y_test, y_test_pred)))
    print("The RMSE on the Test set is:\t{:0.8f}".format(rmse2))
    print("The MAPE on the Train set is:\t{:0.8f}".format(mape2))
    print("The MAE on the Test set is:\t{:0.8f}".format(mean_absolute_error(y_test, y_test_pred)))

    y_var_test = y_test[1:] - y_test[:len(y_test) - 1]
    y_var_predict = y_test_pred[1:] - y_test_pred[:len(y_test_pred) - 1]
    txt = np.zeros(len(y_var_test))
    for i in range(len(y_var_test - 1)):
        txt[i] = np.sign(y_var_test[i]) == np.sign(y_var_predict[i])
    result = sum(txt) / len(txt)
    print('预测涨跌正确:', result)

    print(r2_score(y_train, y_train_pred))
    print(mean_squared_error(y_train, y_train_pred))
    print(rmse1)
    print(mape1)
    print(mean_absolute_error(y_train, y_train_pred))
    print(' ')
    print(r2_score(y_test, y_test_pred))
    print(mean_squared_error(y_test, y_test_pred))
    print(rmse2)
    print(mape2)
    print(mean_absolute_error(y_test, y_test_pred))
    print(result)

    # 1. 创建文件对象
    f = open('C:/Users/Big Data/Desktop/GLSTM.csv', 'w', encoding='utf-8')
    # 2. 基于文件对象构建 csv写入对象
    csv_writer = csv.writer(f)
    # 3. 构建列表头
    csv_writer.writerow(['y_test', 'GLSTM'])
    # 4. 写入csv文件内容
    y_test_m = y_test.flatten().tolist()
    y_test_pred_m = y_test_pred.flatten().tolist()
    csv_writer.writerow([y_test_m, y_test_pred_m])
    # 5. 关闭文件
    f.close()