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 keras.layers.core import Dense, 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
from sklearn.svm import SVR,NuSVR
import csv

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
    X2 = df2[['Rpos', 'Rsize']].values
    y = df2[['Close']].values
    X1_train,X2_train,y_train=X1[0:train_size],X2[0:train_size],y[0:train_size]
    X1_test,X2_test,y_test=X1[train_size:],X2[train_size:],y[train_size:]
    return [X1_train,X2_train,y_train,X1_test,X2_test,y_test,train_size,test_size,y]

def ErrorSVR(regressor2,X1_train, X2_train,y_train,seq_len):
    X1_train2, y_train2 = [], []
    for i in range(seq_len, X1_train.shape[0]):
        X1_train2.append(X1_train[i - seq_len:i, :])
        y_train2.append(y_train[i, 0])
    X1_train2, y_train2 = np.array(X1_train2), np.array(y_train2)
    # print(X1_train2.shape)
    # print(y_train2.shape)
    y_train2_pred_lstm1=regressor2.predict(X1_train2)
    a = y_train2.reshape(-1, 1)
    error = a - y_train2_pred_lstm1  # 固有的预测误差
    # scaler = MinMaxScaler(feature_range=(0, 1))
    # error = scaler.fit_transform(error)
    # print(error.shape)
    X2_train2=X2_train[seq_len:,]          #选择因子

    # 根据误差和模糊输出，建立SVR模型
    regressor2 = NuSVR(nu=0.1,kernel='rbf', gamma=0.001)
    #regr=SVR(kernel='rbf',gamma='auto')
    regressor2.fit(X2_train2, error)
    return regressor2

def LSTM_model2(layers,X1_train, y_train,seq_len):  #100%历史数据
    X_train3, y_train3 = [], []
    for i in range(seq_len, X1_train.shape[0]):
        X_train3.append(X1_train[i - seq_len:i, :])
        y_train3.append(y_train[i, 0])
    X_train3, y_train3 = np.array(X_train3), np.array(y_train3)
    # Stack LSTM1
    regressor3 = Sequential()
    # Adding the first LSTM layer and some Dropout regularisation
    regressor3.add(LSTM(units=layers[0], input_shape=(X_train3.shape[1], X_train3.shape[2]), kernel_initializer='zeros',
                        return_sequences=False))  # ,activation='tanh' ,kernel_initializer='zeros',
    regressor3.add(Dropout(0.2))
    regressor3.add(Dense(units=layers[1]))
    regressor3.add(Activation("linear"))
    # Compiling the RNN
    regressor3.compile(optimizer='adam', loss='mean_squared_error')
    # es =EarlyStopping(monitor="val_loss", mode="min", patience=20, verbose=1,min_delta=0.0001)
    print(regressor3.summary())
    # Fitting the RNN to the Training set
    regressor3.fit(X_train3, y_train3, batch_size=32, epochs=100, validation_split=0.2, verbose=0)#,callbacks=[es]
    return regressor3

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,X2_train,y_train,X1_test,X2_test,y_test,train_size,test_size,y= data_split(df)
    scaler = MinMaxScaler(feature_range=(0, 1))
    X1_train = scaler.fit_transform(X1_train)
    X2_train = scaler.fit_transform(X2_train)
    a=scaler.fit(y_train)
    y_train = scaler.fit_transform(y_train)
    X1_test = scaler.fit_transform(X1_test)
    X2_test = scaler.fit_transform(X2_test)
    b=scaler.fit(y_test)
    y_test = scaler.fit_transform(y_test)
    regressor3 = LSTM_model2([38, 1], X1_train, y_train, seq_len)
    plt.plot(regressor3.history.history['loss'], label='train')
    plt.plot(regressor3.history.history['val_loss'], label='val')
    plt.legend()
    plt.show()
    regressor2=ErrorSVR(regressor3,X1_train, X2_train,y_train,seq_len)


    #结果比较
    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)

    #训练集
    y_train_pred_lstm2 = regressor3.predict(X1_train)
    error1= regressor2.predict(X2_train)
    print('Score: %.2f' % regressor2.score(X2_train, error1))
    error1 = error1.reshape(-1, 1)
    y_train_pred = y_train_pred_lstm2+error1[seq_len:]
    #测试集
    y_test_pred_lstm2 = regressor3.predict(X1_test)
    error2 = regressor2.predict(X2_test)
    print('Score: %.2f' % regressor2.score(X2_test, error2))
    error2 = error2.reshape(-1, 1)
    y_test_pred = y_test_pred_lstm2 + error2[seq_len:]
    # plt.plot(regressor2.history.history['loss'], label='train')
    # plt.plot(regressor2.history.history['val_loss'], label='val')
    # plt.legend()
    # plt.show()
    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=(5, 3))
    plt.plot(y_train, color='red')
    plt.plot(y_train_pred, color='blue',
             label='Predicted Price By LSTM+Svr(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=(5, 3))
    # plt.plot(y_test, color='red')
    # plt.plot(y_test_pred, color='blue',
    #          label='Predicted Price By LSTM+Svr(inverse_scale)On Test dataset')
    # plt.xlabel('Time')
    # plt.ylabel('Price')
    # plt.legend()
    # plt.show()

    # 设置输出的图片大小
    figsize = 6, 4
    figure, ax = plt.subplots(figsize=figsize)

    # 在同一幅图片上画两条折线
    A, = plt.plot(y_test, 'r', label='actual value', linewidth=1.0)
    B, = plt.plot(y_test_pred, 'b', label='predicted value', linewidth=1.0)

    # 设置图例并且设置图例的字体及大小
    font1 = {'family': 'Times New Roman',
             'weight': 'normal',
             'size': 10,
             }
    legend = plt.legend(handles=[A, B], prop=font1)

    # 设置坐标刻度值的大小以及刻度值的字体
    plt.tick_params(labelsize=11)
    labels = ax.get_xticklabels() + ax.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]

    # 设置横纵坐标的名称以及对应字体格式
    font2 = {'family': 'Times New Roman',
             'weight': 'normal',
             'size': 10,
             }
    plt.xlabel('Time', font2)
    plt.ylabel('Price', font2)

    # 将文件保存至文件中并且画出图
    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-vSVR.csv', 'w', encoding='utf-8')
    # 2. 基于文件对象构建 csv写入对象
    csv_writer = csv.writer(f)
    # 3. 构建列表头
    csv_writer.writerow(['y_test','GLSTM-vSVR'])
    # 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()