text: # Copyright 2020 Jordi Corbilla. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  import os
  import secrets
  import pandas as pd
  from datetime import datetime
  
  from stock_prediction_class import StockPrediction
  from stock_prediction_lstm import LongShortTermMemory
  from stock_prediction_numpy import StockData
  from stock_prediction_plotter import Plotter
  from stock_prediction_readme_generator import ReadmeGenerator
  
  os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
  
  
  def train_LSTM_network(stock):
      data = StockData(stock)
      plotter = Plotter(True, stock.get_project_folder(), data.get_stock_short_name(), data.get_stock_currency(), stock.get_ticker())
      (x_train, y_train), (x_test, y_test), (training_data, test_data) = data.download_transform_to_numpy(TIME_STEPS, stock.get_project_folder())
      plotter.plot_histogram_data_split(training_data, test_data, stock.get_validation_date())
  
      lstm = LongShortTermMemory(stock.get_project_folder())
      model = lstm.create_model(x_train)
      model.compile(optimizer='adam', loss='mean_squared_error', metrics=lstm.get_defined_metrics())
      history = model.fit(x_train, y_train, epochs=EPOCHS, batch_size=BATCH_SIZE, validation_data=(x_test, y_test),
                          callbacks=[lstm.get_callback()])
      print("saving weights")
      model.save(os.path.join(stock.get_project_folder(), 'model_weights.h5'))
  
      plotter.plot_loss(history)
      plotter.plot_mse(history)
  
      print("display the content of the model")
      baseline_results = model.evaluate(x_test, y_test, verbose=2)
      for name, value in zip(model.metrics_names, baseline_results):
          print(name, ': ', value)
      print()
  
      print("plotting prediction results")
      test_predictions_baseline = model.predict(x_test)
      test_predictions_baseline = data.get_min_max().inverse_transform(test_predictions_baseline)
      test_predictions_baseline = pd.DataFrame(test_predictions_baseline)
      test_predictions_baseline.to_csv(os.path.join(stock.get_project_folder(), 'predictions.csv'))
  
      test_predictions_baseline.rename(columns={0: STOCK_TICKER + '_predicted'}, inplace=True)
      test_predictions_baseline = test_predictions_baseline.round(decimals=2)
      test_predictions_baseline.index = test_data.index
      plotter.project_plot_predictions(test_predictions_baseline, test_data)
  
      generator = ReadmeGenerator(TOKEN, data.get_stock_short_name())
      generator.write()
  
      print("prediction is finished")
  
  
  # The Main function requires 3 major variables
  # 1) Ticker => defines the short code of a stock
  # 2) Start date => Date when we want to start using the data for training, usually the first data point of the stock
  # 3) Validation date => Date when we want to start partitioning our data from training to validation
  if __name__ == '__main__':
      STOCK_TICKER = 'ETH-USD'
      STOCK_START_DATE = pd.to_datetime('2015-08-07')
      STOCK_VALIDATION_DATE = pd.to_datetime('2021-09-01')
      EPOCHS = 100
      BATCH_SIZE = 32
      TIME_STEPS = 3
      TODAY_RUN = datetime.today().strftime("%Y%m%d")
      TOKEN = STOCK_TICKER + '_' + TODAY_RUN + '_' + secrets.token_hex(16)
      print('Ticker: ' + STOCK_TICKER)
      print('Start Date: ' + STOCK_START_DATE.strftime("%Y-%m-%d"))
      print('Validation Date: ' + STOCK_START_DATE.strftime("%Y-%m-%d"))
      print('Test Run Folder: ' + TOKEN)
      # create project run folder
      PROJECT_FOLDER = os.path.join(os.getcwd(), TOKEN)
      if not os.path.exists(PROJECT_FOLDER):
          os.makedirs(PROJECT_FOLDER)
  
      stock_prediction = StockPrediction(STOCK_TICKER, STOCK_START_DATE, STOCK_VALIDATION_DATE, PROJECT_FOLDER)
      # Execute Deep Learning model
      train_LSTM_network(stock_prediction)
  