refactor train/valid data

This commit is contained in:
Jamie
2021-05-06 21:06:12 -04:00
parent 51f4e9a695
commit e92d844f92
3 changed files with 153 additions and 198 deletions

View File

@@ -105,10 +105,10 @@ def k_nearest_neighbors(other_args: List[str], s_ticker: str, df_stock: pd.DataF
parser.add_argument(
"-t",
"--test_size",
default = .2,
default=0.2,
dest="test_size",
type = float,
help = "Percentage of data to validate in sample"
type=float,
help="Percentage of data to validate in sample",
)
try:

View File

@@ -29,6 +29,7 @@ from gamestonk_terminal.prediction_techniques.pred_helper import (
print_pretty_prediction_nn,
price_prediction_backtesting_color,
print_prediction_kpis,
prepare_scale_train_valid_test,
)
from gamestonk_terminal import feature_flags as gtff
@@ -143,7 +144,7 @@ def _parse_args(prog: str, description: str, other_args: List[str]):
action="store",
dest="n_epochs",
type=check_positive,
default=200,
default=50,
help="number of training epochs.",
)
parser.add_argument(
@@ -251,6 +252,14 @@ def _parse_args(prog: str, description: str, other_args: List[str]):
default=1,
help="number of loops to iterate and train models",
)
parser.add_argument(
"-v",
"--valid",
type=float,
dest="valid_split",
default=0.1,
help="Validation data split fraction",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
@@ -1016,59 +1025,80 @@ def lstm(other_args: List[str], s_ticker: str, df_stock: pd.DataFrame):
return
# Setup backtesting
df_stock, df_future = _setup_backtesting(df_stock, ns_parser)
# df_stock, df_future = _setup_backtesting(df_stock, ns_parser)
# Pre-process data
scaler, stock_train_data, stock_x, stock_y = _preprocess_split(
df_stock, ns_parser
)
stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1))
stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1))
# scaler, stock_train_data, stock_x, stock_y = _preprocess_split(
# df_stock, ns_parser
# )
# stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1))
# stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1))
(
X_train,
X_test,
y_train,
y_test,
X_dates_train,
X_dates_test,
y_dates_train,
y_dates_test,
test_data,
dates_test,
scaler,
) = prepare_scale_train_valid_test(df_stock, ns_parser)
# Build Neural Network model
model = build_neural_network_model(
cfg_nn_models.Long_Short_Term_Memory, ns_parser.n_inputs, ns_parser.n_days
)
model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss)
for idx_loop in range(ns_parser.n_loops):
# Train our model
model.fit(
stock_x,
stock_y,
epochs=ns_parser.n_epochs,
batch_size=ns_parser.n_batch_size,
verbose=1,
)
print("")
print(model.summary())
print("")
# Prediction
yhat = model.predict(
stock_train_data[-ns_parser.n_inputs :].reshape(
1, ns_parser.n_inputs, 1
),
verbose=0,
)
if idx_loop == 0:
# Re-scale the data back, plot, and print the results
df_pred = _rescale_data(
df_stock, ns_parser, scaler, yhat, idx_loop
).to_frame()
else:
df_pred = df_pred.join(
_rescale_data(
df_stock, ns_parser, scaler, yhat, idx_loop
).to_frame()
)
_plot_and_print_results(
df_stock, ns_parser, df_future, df_pred, "LSTM", s_ticker
print(X_train.shape, X_test.shape)
model.fit(
X_train.reshape(X_train.shape[0], X_train.shape[1], 1),
y_train,
epochs=ns_parser.n_epochs,
verbose=True,
validation_data=(X_test, y_test),
)
# for idx_loop in range(ns_parser.n_loops):
# Train our model
# model.fit(
# stock_x,
# stock_y,
# epochs=ns_parser.n_epochs,
# batch_size=ns_parser.n_batch_size,
# verbose=1,
# )
# print("")
# print(model.summary())
# print("")
# # Prediction
# yhat = model.predict(
# stock_train_data[-ns_parser.n_inputs :].reshape(
# 1, ns_parser.n_inputs, 1
# ),
# verbose=0,
# )
# if idx_loop == 0:
# Re-scale the data back, plot, and print the results
# df_pred = _rescale_data(
# df_stock, ns_parser, scaler, yhat, idx_loop
# ).to_frame()
# else:
# df_pred = df_pred.join(
# _rescale_data(
# df_stock, ns_parser, scaler, yhat, idx_loop
# ).to_frame()
# )
# _plot_and_print_results(
# df_stock, ns_parser, df_future, df_pred, "LSTM", s_ticker
# )
except Exception as e:
print(e)
traceback.print_exc()

View File

@@ -1,8 +1,9 @@
""" Prediction helper functions """
__docformat__ = "numpy"
import argparse
from typing import Tuple
from datetime import datetime
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
from pandas.plotting import register_matplotlib_converters
@@ -14,7 +15,7 @@ from sklearn.metrics import (
mean_squared_error,
)
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler, Normalizer
from gamestonk_terminal.helper_funcs import (
get_next_stock_market_days,
patch_pandas_text_adjustment,
@@ -26,26 +27,72 @@ from gamestonk_terminal.config_plot import PLOT_DPI
register_matplotlib_converters()
def prepare_train_valid_test(
df_stock, parsed_end_date, n_input_days, n_predict_days, test_size
def prepare_scale_train_valid_test(
df_stock: pd.DataFrame, ns_parser: argparse.Namespace
):
"""
Prepare and scale train, validate and test data.
Parameters
----------
df_stock: pd.DataFrame
Dataframe of stock prices
ns_parser: argparse.Namespace
Parsed arguments
Returns
-------
X_train: np.ndarray
Array of training data. Shape (# samples, n_inputs, 1)
X_test: np.ndarray
Array of validation data. Shape (#samples, n_inputs, 1)
y_train: np.ndarray
Array of training outputs. Shape (#samples, n_days)
y_test: np.ndarray
Array of validation outputs. Shape (#samples, n_days)
X_dates_train: np.ndarray
Array of dates for X_train
X_dates_test: np.ndarray
Array of dates for X_test
y_dates_train: np.ndarray
Array of dates for y_train
y_dates_test: np.ndarray
Array of dates for y)test
test_data: np.ndarray
Array of prices after the specified end date
dates_test: np.ndarray
Array of dates after specified end date
scaler:
Fitted preprocesser
"""
parsed_end_date = ns_parser.s_end_date or df_stock.index[-1]-timedelta(days=3)
n_input_days = ns_parser.n_inputs
n_predict_days = ns_parser.n_days
test_size = ns_parser.valid_split
df_test = df_stock[df_stock.index >= parsed_end_date]
df_stock = df_stock[df_stock.index < parsed_end_date]
dates = df_stock.index
prices = df_stock["5. adjusted close"].values
# Pre-process data
if ns_parser.s_preprocessing == "standardization":
scaler = StandardScaler()
elif ns_parser.s_preprocessing == "minmax":
scaler = MinMaxScaler()
elif ns_parser.s_preprocessing == "normalization":
scaler = Normalizer()
test_data = df_stock[df_stock.index > parsed_end_date]
train_data = df_stock[df_stock.index < parsed_end_date]
dates = train_data.index
dates_test = test_data.index
scaler = scaler
train_data = scaler.fit_transform(train_data.values.reshape(-1, 1))
test_data = scaler.transform(test_data.values.reshape(-1, 1))
prices = train_data
input_dates = []
input_prices = []
next_n_day_prices = []
next_n_day_dates = []
test_days = []
test_inputs = []
test_next_n_days = []
for idx in range(len(prices) - n_input_days - n_predict_days):
input_prices.append(prices[idx : idx + n_input_days])
input_dates.append(dates[idx : idx + n_input_days])
next_n_day_prices.append(
@@ -55,20 +102,20 @@ def prepare_train_valid_test(
dates[idx + n_input_days : idx + n_input_days + n_predict_days]
)
input_dates = np.asarray(input_dates)
input_prices = np.asarray(input_prices)
next_n_day_prices = np.asarray(next_n_day_prices)
next_n_day_dates = np.asarray(next_n_day_dates)
input_dates = np.array(input_dates)
input_prices = np.array(input_prices)
next_n_day_prices = np.array(next_n_day_prices)
next_n_day_dates = np.array(next_n_day_dates)
(
X_train,
X_valid,
X_test,
y_train,
y_valid,
y_test,
X_dates_train,
X_dates_valid,
X_dates_test,
y_dates_train,
y_dates_valid,
y_dates_test,
) = train_test_split(
input_prices,
next_n_day_prices,
@@ -76,15 +123,19 @@ def prepare_train_valid_test(
next_n_day_dates,
test_size=test_size,
)
return (
X_train,
X_valid,
X_test,
y_train,
y_valid,
y_test,
X_dates_train,
X_dates_valid,
X_dates_test,
y_dates_train,
y_dates_valid,
y_dates_test,
test_data,
dates_test,
scaler,
)
@@ -144,132 +195,6 @@ def get_backtesting_data(
return df_future, df_stock, True
def plot_pred(
df_stock: pd.DataFrame,
df_future: pd.DataFrame,
df_pred: pd.DataFrame,
title: str,
bt_flag: bool,
):
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
plt.title(title)
plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1])
plt.xlabel("Time")
plt.ylabel("Share Price ($)")
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
df_ma = df_stock["5. adjusted close"].rolling(window=ns_parser.n_length).mean()
plt.plot(df_ma.index, df_ma, lw=2, linestyle="--", c="tab:orange")
plt.plot(
[df_stock.index[-1], df_pred.index[0]],
[df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
lw=1,
c="tab:green",
linestyle="--",
)
plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
plt.axvspan(
df_stock.index[-1], df_pred.index[-1], facecolor="tab:orange", alpha=0.2
)
_, _, ymin, ymax = plt.axis()
plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle="--", color="k")
if bt_flag:
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
plt.subplot(211)
plt.plot(
df_future.index,
df_future["5. adjusted close"],
lw=2,
c="tab:blue",
ls="--",
)
plt.plot(df_pred.index, df_pred, lw=2, c="green")
plt.scatter(df_future.index, df_future["5. adjusted close"], c="tab:blue", lw=3)
plt.plot(
[df_stock.index[-1], df_future.index[0]],
[
df_stock["5. adjusted close"].values[-1],
df_future["5. adjusted close"].values[0],
],
lw=2,
c="tab:blue",
ls="--",
)
plt.scatter(df_pred.index, df_pred, c="green", lw=3)
plt.plot(
[df_stock.index[-1], df_pred.index[0]],
[df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
lw=2,
c="green",
ls="--",
)
plt.title("BACKTESTING: Real data price versus Prediction")
plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
plt.xticks(
[df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
visible=True,
)
plt.ylabel("Share Price ($)")
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
plt.legend(["Real data", "Prediction data"])
plt.xticks([])
plt.subplot(212)
plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
plt.plot(
df_future.index,
100
* (df_pred.values - df_future["5. adjusted close"].values)
/ df_future["5. adjusted close"].values,
lw=2,
c="red",
)
plt.scatter(
df_future.index,
100
* (df_pred.values - df_future["5. adjusted close"].values)
/ df_future["5. adjusted close"].values,
c="red",
lw=5,
)
plt.title("BACKTESTING: Error between Real data and Prediction [%]")
plt.plot(
[df_stock.index[-1], df_future.index[0]],
[
0,
100
* (df_pred.values[0] - df_future["5. adjusted close"].values[0])
/ df_future["5. adjusted close"].values[0],
],
lw=2,
ls="--",
c="red",
)
plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
plt.xticks(
[df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
visible=True,
)
plt.xlabel("Time")
plt.ylabel("Prediction Error (%)")
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
plt.legend(["Real data", "Prediction data"])
if gtff.USE_ION:
plt.ion()
plt.show()
pass
def price_prediction_color(val: float, last_val: float) -> str:
"""Set prediction to be a colored string"""
if float(val) > last_val: