<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Timeseries Forecasting
This notebook explains how to use tsfresh in time series foreacasting.
Make sure you also read through the documentation to learn more on this feature.
We will use the stock price of Apple for this.
In this notebook we will only showcase how to work with a single time series at a time (one stock).
There exist another notebook in the advanced folder, which treats several stocks at the same time.
Basically the same - but a bit more complex when it comes to pandas multi-indexing.
Step1:  Reading the data
We download the data from "stooq" and only store the High value.
Please note
Step2:  We want to make the time dependency a bit clearer and add an identifier to each of the stock values (in this notebook we only have Google though).
Step3:  Create training data sample
Forecasting typically involves the following steps
Step4:  The resulting dataframe now consists of these "windows" stamped out of the original dataframe.
For example all data with the id = (AAPL, 2020-07-14 00
Step5:  If you now group by the new id column, each of the groups will be a certain stock symbol until and including the data until a certain day (and including the last 20 days in the past).
Whereas we started with 1259 data samples
Step6:  we now have 1254 unique windows (identified by stock symbol and ending date)
Step7:  We "lost" 5 windows, as we required to have a minimum history of more than 5 days.
Step8:  The process is also shown in this image (please note that the window size is smaller for better visibility)
Step9:  We make the data a bit easier to work with by removing the tuple-index
Step10:  Our (AAPL, 2020-07-14 00
Step11:  Just to repeat
Step12:  Quick consistency test
Step13:  However, we need to be a bit careful here
Step14:  We can now train normal AdaBoostRegressors to predict the next time step .
Let's split the data into a training and testing sample (but make sure to keep temporal consistency).
We take everything until 2019 as train data an the rest as test
Step15:  and do feature selection before training
Step16:  Now lets check how good our prediction is
Step17:  The prediction is for the next day, so for drawing we need to shift 1 step back
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pylab as plt
from tsfresh import extract_features, select_features
from tsfresh.utilities.dataframe_functions import roll_time_series, make_forecasting_frame
from tsfresh.utilities.dataframe_functions import impute
try:
    import pandas_datareader.data as web
except ImportError:
    print("You need to install the pandas_datareader. Run pip install pandas_datareader.")
from sklearn.linear_model import LinearRegression
Explanation: Timeseries Forecasting
This notebook explains how to use tsfresh in time series foreacasting.
Make sure you also read through the documentation to learn more on this feature.
We will use the stock price of Apple for this.
In this notebook we will only showcase how to work with a single time series at a time (one stock).
There exist another notebook in the advanced folder, which treats several stocks at the same time.
Basically the same - but a bit more complex when it comes to pandas multi-indexing.
End of explanation
df = web.DataReader("AAPL", 'stooq')["High"]
df.head()
plt.figure(figsize=(15, 6))
df.plot(ax=plt.gca())
plt.show()
Explanation: Reading the data
We download the data from "stooq" and only store the High value.
Please note: this notebook is for showcasing tsfreshs feature extraction - not to predict stock market prices :-)
End of explanation
df_melted = pd.DataFrame({"high": df.copy()})
df_melted["date"] = df_melted.index
df_melted["Symbols"] = "AAPL"
df_melted.head()
Explanation: We want to make the time dependency a bit clearer and add an identifier to each of the stock values (in this notebook we only have Google though).
End of explanation
df_rolled = roll_time_series(df_melted, column_id="Symbols", column_sort="date",
                             max_timeshift=20, min_timeshift=5)
df_rolled.head()
Explanation: Create training data sample
Forecasting typically involves the following steps:
* take all data up to today
* do feature extraction (e.g. by running extract_features)
* run a prediction model (e.g. a regressor, see below)
* use the result as the forecast for tomorrow
In training however, we need multiple examples to train.
If we would only use the time series until today (and wait for the value of tomorrow to have a target), we would only have a single training example.
Therefore we use a trick: we replay the history.
Imagine you have a cut-out window sliding over your data.
At each time step $t$, you treat the data as it would be today. 
You extract the features with everything you know until today (which is all data until and including $t$).
The target for the features until time $t$ is the time value of time $t + 1$ (which you already know, because everything has already happened).
The process of window-sliding is implemented in the function roll_time_series.
Our window size will be 20 (we look at max 20 days in the past) and we disregard all windows which are shorter than 5 days.
End of explanation
df_rolled[df_rolled["id"] == ("AAPL", pd.to_datetime("2020-07-14"))]
df_melted[(df_melted["date"] <= pd.to_datetime("2020-07-14")) & 
          (df_melted["date"] >= pd.to_datetime("2020-06-15")) & 
          (df_melted["Symbols"] == "AAPL")]
Explanation: The resulting dataframe now consists of these "windows" stamped out of the original dataframe.
For example all data with the id = (AAPL, 2020-07-14 00:00:00) comes from the original data of stock AAPL including the last 20 days until 2020-07-14:
End of explanation
len(df_melted)
Explanation: If you now group by the new id column, each of the groups will be a certain stock symbol until and including the data until a certain day (and including the last 20 days in the past).
Whereas we started with 1259 data samples:
End of explanation
df_rolled["id"].nunique()
Explanation: we now have 1254 unique windows (identified by stock symbol and ending date):
End of explanation
df_rolled.groupby("id").size().agg([np.min, np.max])
Explanation: We "lost" 5 windows, as we required to have a minimum history of more than 5 days.
End of explanation
X = extract_features(df_rolled.drop("Symbols", axis=1), 
                     column_id="id", column_sort="date", column_value="high", 
                     impute_function=impute, show_warnings=False)
X.head()
Explanation: The process is also shown in this image (please note that the window size is smaller for better visibility):
<img src="./stocks.png"/>
Extract Features
The rolled (windowed) data sample is now in the correct format to use it for tsfreshs feature extraction.
As normal, features will be extracted using all data for a given id, which is in our case all data of a given window and a given id (one colored box in the graph above).
If the feature extraction returns a row with the index (AAPL, 2020-07-14 00:00:00), you know it has been calculated using the AAPL data up and including 2020-07-14 (and 20 days of history).
End of explanation
X = X.set_index(X.index.map(lambda x: x[1]), drop=True)
X.index.name = "last_date"
X.head()
Explanation: We make the data a bit easier to work with by removing the tuple-index
End of explanation
X.loc['2020-07-14']
Explanation: Our (AAPL, 2020-07-14 00:00:00) is also in the data again:
End of explanation
y = df_melted.set_index("date").sort_index().high.shift(-1)
Explanation: Just to repeat: the features in this row were only calculated using the time series values of AAPL up to and including 2015-07-14 and the last 20 days.
Prediction
We can now use the extracted features to train a regressor.
But what will be our targets?
The target for the row 2020-07-13 is the value on the next timestep (that would be 2020-07-14 in this case).
So all we need to do is go back to our original dataframe and take the stock value of tomorrow.
This is done with shift:
End of explanation
y["2020-07-13"], df["2020-07-14"].iloc[0]
Explanation: Quick consistency test:
End of explanation
y = y[y.index.isin(X.index)]
X = X[X.index.isin(y.index)]
Explanation: However, we need to be a bit careful here: X is missing the first 5 dates (as our minimum window size was 5) and y is missing the last date (as there is nothing to predict on today).
So lets make sure we have a consistent view on the data.
End of explanation
X[:"2018"]
X_train = X[:"2018"]
X_test = X["2019":]
y_train = y[:"2018"]
y_test = y["2019":]
Explanation: We can now train normal AdaBoostRegressors to predict the next time step .
Let's split the data into a training and testing sample (but make sure to keep temporal consistency).
We take everything until 2019 as train data an the rest as test:
End of explanation
X_train_selected = select_features(X_train, y_train)
ada = LinearRegression()
ada.fit(X_train_selected, y_train)
Explanation: and do feature selection before training
End of explanation
X_test_selected = X_test[X_train_selected.columns]
y_pred = pd.Series(ada.predict(X_test_selected), index=X_test_selected.index)
Explanation: Now lets check how good our prediction is:
End of explanation
plt.figure(figsize=(15, 6))
y.plot(ax=plt.gca())
y_pred.plot(ax=plt.gca(), legend=None, marker=".")
Explanation: The prediction is for the next day, so for drawing we need to shift 1 step back:
End of explanation
<END_TASK>