text: 
  # https://blog.csdn.net/a19990412/article/details/85139058
  # LSTM实现股票预测--pytorch版本【120+行代码】
  '''
  模型假设
  
  我这里认为每天的沪深300的最高价格，是依赖于当天的前n天的沪深300的最高价。
  然后用RNN的LSTM模型来估计（捕捉到时序信息）。
  让模型学会用前n天的最高价，来判断当天的最高价。
  '''
  # depends
  
  import pandas as pd
  import matplotlib.pyplot as plt
  import datetime
  import torch
  import torch.nn as nn
  import numpy as np
  from torch.utils.data import Dataset, DataLoader
  
  ## load data
  
  def generate_df_affect_by_n_days(series, n, index=False):
      if len(series) <= n:
          raise Exception("The Length of series is %d, while affect by (n=%d)." % (len(series), n))
      df = pd.DataFrame()
      for i in range(n):
          df['c%d' % i] = series.tolist()[i:-(n - i)]
      df['y'] = series.tolist()[n:]
      if index:
          df.index = series.index[n:]
      return df
  
  
  def readData(column='high', n=30, all_too=True, index=False, train_end=-300):
      df = pd.read_csv("sh.csv", index_col=0)
      df.index = list(map(lambda x: datetime.datetime.strptime(x, "%Y-%m-%d"), df.index))
      df_column = df[column].copy()
      df_column_train, df_column_test = df_column[:train_end], df_column[train_end - n:]
      df_generate_from_df_column_train = generate_df_affect_by_n_days(df_column_train, n, index=index)
      if all_too:
          return df_generate_from_df_column_train, df_column, df.index.tolist()
      return df_generate_from_df_column_train
      
  ## params
  
  n = 30
  LR = 0.0001
  EPOCH = 100
  train_end = -500
  
  ## build
  
  df, df_all, df_index = readData('high', n=n, train_end=train_end)
  
  df_all = np.array(df_all.tolist())
  plt.plot(df_index, df_all, label='real-data')
  
  df_numpy = np.array(df)
  
  df_numpy_mean = np.mean(df_numpy)
  df_numpy_std = np.std(df_numpy)
  
  df_numpy = (df_numpy - df_numpy_mean) / df_numpy_std
  df_tensor = torch.Tensor(df_numpy)
  
  trainset = TrainSet(df_tensor)
  trainloader = DataLoader(trainset, batch_size=10, shuffle=True)
  
  ## train
  
  rnn = RNN(n)
  optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)  # optimize all cnn parameters
  loss_func = nn.MSELoss()
  
  for step in range(EPOCH):
      for tx, ty in trainloader:
          output = rnn(torch.unsqueeze(tx, dim=0))
          loss = loss_func(torch.squeeze(output), ty)
          optimizer.zero_grad()  # clear gradients for this training step
          loss.backward()  # back propagation, compute gradients
          optimizer.step()
      print(step, loss)
      if step % 10:
          torch.save(rnn, 'rnn.pkl')
  torch.save(rnn, 'rnn.pkl')
  
  
  ## output paint
  
  generate_data_train = []
  generate_data_test = []
  
  test_index = len(df_all) + train_end
  
  df_all_normal = (df_all - df_numpy_mean) / df_numpy_std
  df_all_normal_tensor = torch.Tensor(df_all_normal)
  for i in range(n, len(df_all)):
      x = df_all_normal_tensor[i - n:i]
      x = torch.unsqueeze(torch.unsqueeze(x, dim=0), dim=0)
      y = rnn(x)
      if i < test_index:
          generate_data_train.append(torch.squeeze(y).detach().numpy() * df_numpy_std + df_numpy_mean)
      else:
          generate_data_test.append(torch.squeeze(y).detach().numpy() * df_numpy_std + df_numpy_mean)
  plt.plot(df_index[n:train_end], generate_data_train, label='generate_train')
  plt.plot(df_index[train_end:], generate_data_test, label='generate_test')
  plt.legend()
  plt.show()
  