import math
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM,Dense,Dropout
import random
import torch
from torch import nn
from torch.autograd import Variable
pd.options.mode.chained_assignment = None
plt.style.use('fivethirtyeight') # or seaborn
Using TensorFlow backend.
Stock Prediction¶
Get the stock data from yfinance
# Get the stock data
df = yf.download('AMZN',
start='2018-01-01',
end='2022-08-28')
print(df.shape)
df.head()
[*********************100%***********************] 1 of 1 completed (1172, 6)
| Open | High | Low | Close | Adj Close | Volume | |
|---|---|---|---|---|---|---|
| Date | ||||||
| 2018-01-02 | 58.599998 | 59.500000 | 58.525501 | 59.450500 | 59.450500 | 53890000 |
| 2018-01-03 | 59.415001 | 60.274502 | 59.415001 | 60.209999 | 60.209999 | 62176000 |
| 2018-01-04 | 60.250000 | 60.793499 | 60.233002 | 60.479500 | 60.479500 | 60442000 |
| 2018-01-05 | 60.875500 | 61.457001 | 60.500000 | 61.457001 | 61.457001 | 70894000 |
| 2018-01-08 | 61.799999 | 62.653999 | 61.601501 | 62.343498 | 62.343498 | 85590000 |
We plot the dataset!
plt.figure(figsize=(16,8))
plt.plot(df.Close)
plt.ylabel('Closing price', fontsize=18)
plt.xlabel('Date', fontsize=18)
plt.show()
#plt.style.use('ggplot')
plt.style.use('fivethirtyeight')
df['Volume'].plot(label='CLOSE', title='Amazon')
<AxesSubplot:title={'center':'Amazon'}, xlabel='Date'>
Predicting the following day, based on the previous 60 days¶
We first create our dataframe
# Create new dataframe with only close column
data = df.filter(['Close'])
# Save it as a numpy array
dataset = np.array(data)
# Get the number of rows to train the model
train_data_len = math.ceil(len(dataset) * 0.8) # we multiply by 0.8 to get a 80-20 train-test model
print(train_data_len)
938
We then have to normalize the data
# Scale/normalize the data, since neuron takes only values between [0,1]
scaler = MinMaxScaler(feature_range=(0,1))
scaled_data = scaler.fit_transform(dataset)
scaled_data
array([[0. ],
[0.00597466],
[0.00809471],
...,
[0.58487654],
[0.61225221],
[0.56088343]])
Now our implementation with
Keras:¶
We create the training dataset:
# Create the training dataset
train_data = scaled_data[0:train_data_len, :] # Splitting the 80% training data, with all the column 'Close'
# Split the training data into x_train and y_train
x_train = []
y_train = []
for i in range(60,len(train_data)): # We're using the past 60 days to preditct the stock price
x_train.append(train_data[i-60:i,0])
y_train.append(train_data[i,0])
if i <= 62:
print(x_train)
print(y_train)
print('\n')
x_train, y_train = np.array(x_train), np.array(y_train)
[array([0. , 0.00597466, 0.00809471, 0.0157843 , 0.02275801,
0.02505112, 0.02569225, 0.03448316, 0.04570093, 0.04556715,
0.04168895, 0.04102816, 0.04152373, 0.05439743, 0.0682544 ,
0.06627599, 0.0743156 , 0.08379485, 0.08994259, 0.09786421,
0.10300505, 0.07905522, 0.0947687 , 0.07905522, 0.09983872,
0.08958855, 0.06351873, 0.05923146, 0.07757238, 0.08869574,
0.10306795, 0.1072805 , 0.10213972, 0.10987259, 0.1156034 ,
0.11655521, 0.12232143, 0.13095503, 0.1270335 , 0.12721836,
0.11974513, 0.12241974, 0.1316079 , 0.13712637, 0.14002124,
0.1427195 , 0.1533512 , 0.1610211 , 0.15700517, 0.15811441,
0.15470026, 0.15051526, 0.13999369, 0.15634834, 0.15451937,
0.13998979, 0.12057505, 0.14429279, 0.12116112, 0.09534691])]
[0.10160869078816598]
[array([0. , 0.00597466, 0.00809471, 0.0157843 , 0.02275801,
0.02505112, 0.02569225, 0.03448316, 0.04570093, 0.04556715,
0.04168895, 0.04102816, 0.04152373, 0.05439743, 0.0682544 ,
0.06627599, 0.0743156 , 0.08379485, 0.08994259, 0.09786421,
0.10300505, 0.07905522, 0.0947687 , 0.07905522, 0.09983872,
0.08958855, 0.06351873, 0.05923146, 0.07757238, 0.08869574,
0.10306795, 0.1072805 , 0.10213972, 0.10987259, 0.1156034 ,
0.11655521, 0.12232143, 0.13095503, 0.1270335 , 0.12721836,
0.11974513, 0.12241974, 0.1316079 , 0.13712637, 0.14002124,
0.1427195 , 0.1533512 , 0.1610211 , 0.15700517, 0.15811441,
0.15470026, 0.15051526, 0.13999369, 0.15634834, 0.15451937,
0.13998979, 0.12057505, 0.14429279, 0.12116112, 0.09534691]), array([0.00597466, 0.00809471, 0.0157843 , 0.02275801, 0.02505112,
0.02569225, 0.03448316, 0.04570093, 0.04556715, 0.04168895,
0.04102816, 0.04152373, 0.05439743, 0.0682544 , 0.06627599,
0.0743156 , 0.08379485, 0.08994259, 0.09786421, 0.10300505,
0.07905522, 0.0947687 , 0.07905522, 0.09983872, 0.08958855,
0.06351873, 0.05923146, 0.07757238, 0.08869574, 0.10306795,
0.1072805 , 0.10213972, 0.10987259, 0.1156034 , 0.11655521,
0.12232143, 0.13095503, 0.1270335 , 0.12721836, 0.11974513,
0.12241974, 0.1316079 , 0.13712637, 0.14002124, 0.1427195 ,
0.1533512 , 0.1610211 , 0.15700517, 0.15811441, 0.15470026,
0.15051526, 0.13999369, 0.15634834, 0.15451937, 0.13998979,
0.12057505, 0.14429279, 0.12116112, 0.09534691, 0.10160869])]
[0.10160869078816598, 0.07197138472795855]
[array([0. , 0.00597466, 0.00809471, 0.0157843 , 0.02275801,
0.02505112, 0.02569225, 0.03448316, 0.04570093, 0.04556715,
0.04168895, 0.04102816, 0.04152373, 0.05439743, 0.0682544 ,
0.06627599, 0.0743156 , 0.08379485, 0.08994259, 0.09786421,
0.10300505, 0.07905522, 0.0947687 , 0.07905522, 0.09983872,
0.08958855, 0.06351873, 0.05923146, 0.07757238, 0.08869574,
0.10306795, 0.1072805 , 0.10213972, 0.10987259, 0.1156034 ,
0.11655521, 0.12232143, 0.13095503, 0.1270335 , 0.12721836,
0.11974513, 0.12241974, 0.1316079 , 0.13712637, 0.14002124,
0.1427195 , 0.1533512 , 0.1610211 , 0.15700517, 0.15811441,
0.15470026, 0.15051526, 0.13999369, 0.15634834, 0.15451937,
0.13998979, 0.12057505, 0.14429279, 0.12116112, 0.09534691]), array([0.00597466, 0.00809471, 0.0157843 , 0.02275801, 0.02505112,
0.02569225, 0.03448316, 0.04570093, 0.04556715, 0.04168895,
0.04102816, 0.04152373, 0.05439743, 0.0682544 , 0.06627599,
0.0743156 , 0.08379485, 0.08994259, 0.09786421, 0.10300505,
0.07905522, 0.0947687 , 0.07905522, 0.09983872, 0.08958855,
0.06351873, 0.05923146, 0.07757238, 0.08869574, 0.10306795,
0.1072805 , 0.10213972, 0.10987259, 0.1156034 , 0.11655521,
0.12232143, 0.13095503, 0.1270335 , 0.12721836, 0.11974513,
0.12241974, 0.1316079 , 0.13712637, 0.14002124, 0.1427195 ,
0.1533512 , 0.1610211 , 0.15700517, 0.15811441, 0.15470026,
0.15051526, 0.13999369, 0.15634834, 0.15451937, 0.13998979,
0.12057505, 0.14429279, 0.12116112, 0.09534691, 0.10160869]), array([0.00809471, 0.0157843 , 0.02275801, 0.02505112, 0.02569225,
0.03448316, 0.04570093, 0.04556715, 0.04168895, 0.04102816,
0.04152373, 0.05439743, 0.0682544 , 0.06627599, 0.0743156 ,
0.08379485, 0.08994259, 0.09786421, 0.10300505, 0.07905522,
0.0947687 , 0.07905522, 0.09983872, 0.08958855, 0.06351873,
0.05923146, 0.07757238, 0.08869574, 0.10306795, 0.1072805 ,
0.10213972, 0.10987259, 0.1156034 , 0.11655521, 0.12232143,
0.13095503, 0.1270335 , 0.12721836, 0.11974513, 0.12241974,
0.1316079 , 0.13712637, 0.14002124, 0.1427195 , 0.1533512 ,
0.1610211 , 0.15700517, 0.15811441, 0.15470026, 0.15051526,
0.13999369, 0.15634834, 0.15451937, 0.13998979, 0.12057505,
0.14429279, 0.12116112, 0.09534691, 0.10160869, 0.07197138])]
[0.10160869078816598, 0.07197138472795855, 0.07986155457201921]
Data Reshaping
# Reshape the data, since LSTM takes 3 dimensional array
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_train.shape
(878, 60, 1)
We can now build our LSTM Model
# Build the LSTM model
model = Sequential()
model.add(LSTM(50, input_shape=(x_train.shape[1],1),
return_sequences=True))
model.add(LSTM(50), return_sequences=True)
#model.add(Dense(25))
model.add(LSTM(50))
model.add(Dense(1))
# Compile model
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])
model.summary()
Model Training
# Train the model
model.fit(x_train, y_train, batch_size=64, epochs=10)
# save the model
model.save('best_model/model')
# load the model
from tensorflow import keras
model = keras.models.load_model('best_model/model')
We now test our Keras model¶
We first create our testing dataset
# Testing dataset --- Create a new arrray containing scaled values from index 1543 to 2003
test_data = scaled_data[train_data_len-60: ,:]
x_test = []
y_test = dataset[train_data_len: ,:]
for i in range(60, len(test_data)):
x_test.append(test_data[i-60:i, 0])
x_test = np.array(x_test)
Some reshape...¶
# Reshape the data
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
We then test our model¶
# Get the models predicted values
predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)
...and compute the error
# Get the root mean squared error (RSME)
rmse = np.sqrt( np.mean( predictions - y_test)**2 )
print(rmse)
0.12970665173652846
We plot our results and predictions of the Keras model
# Plot the data
train = data[:train_data_len]
valid = data[train_data_len:]
valid['Predictions'] = predictions
plt.figure(figsize=(16,8))
plt.title(('AMZN stock prediction, RSME =',rmse),fontsize=18)
plt.ylabel('Closing price', fontsize=18)
plt.xlabel('Date', fontsize=18)
plt.plot(train['Close'])
plt.plot(valid[['Close','Predictions']])
plt.legend(['Train','Validation','Predictions'], loc='upper left')
plt.show()
We can now show our implementation with PyTorch:¶
We split together train and test data
# Create the training and testing dataset
train_data = scaled_data[0:train_data_len, :] # Splitting the 80% training data, with all the column 'Close'
test_data = scaled_data[train_data_len-60: ,:] # Size = 294. We take the 20% left, including days needed to test the first 60 days, they are also part of train_data. So we get the increase in size, from 234 to 294.
# Split the training data into x_train and y_train
x_train = []
y_train = scaled_data[60:train_data_len,:]
x_test = []
y_test = dataset[train_data_len:, :] # not scaled, we will inverse-transform the predictions later
for i in range(60,len(train_data)): # We're using the past 60 days to preditct the stock price
x_train.append(train_data[i-60:i,0])
for i in range(60, len(test_data)): # We start adding where we left in x_train, so the fisrt 60-sequence-long follows the same trend,
x_test.append(test_data[i-60:i, 0]) # and almost overlap with the last one in x_train: we start from the next index respect to the one
# we started on the last iteration on x_train.
# Including the previous 60 days in the creation of test_data allows us to test the predictions on all
# the 234 (y_test size) labels/days in y_test. #see following print
x_train, y_train = np.array(x_train), np.array(y_train)
x_test = np.array(x_test)
print(f'x_train shape: {x_train.shape}') # == (878, 60): we have 878 sequences (of length 60 days) out of 938 = train_data_length. The first 60 days are not usable since there is not enough days/data to train, hence 878 = 938 - 60.
print(f'y_train shape: {y_train.shape}') # labels
print(f'x_test shape: {x_test.shape}')
print(f'y_test shape: {y_test.shape}')
print(f'We overlap the previous 60 days in test_data: {len(y_test)}(labels) = {len(test_data)}(test_data size) - 60(days added)')
x_train shape: (878, 60) y_train shape: (878, 1) x_test shape: (234, 60) y_test shape: (234, 1) We overlap the previous 60 days in test_data: 234(labels) = 294(test_data size) - 60(days added)
We can show this overlap of train_data and test_data that permits us to test all the 234 labels.
#a = pd.DataFrame(a); #b = pd.DataFrame(b)
a,b = x_train[-1], x_test[0] # We take the last sequence in train and the first in test
i = random.randint(0,51) # Random generate an index in this range
a = a[i+1:i+10] # To visualize it better we only take a slice of the two sequences
b = b[i:i+9]
print(" Train:", a, "\n\n", "Test:", b, "\n\n", a==b)
Train: [1. 0.99525251 0.99494186 0.97874056 0.98043977 0.9605845 0.93794059 0.92848499 0.9377675 ] Test: [1. 0.99525251 0.99494186 0.97874056 0.98043977 0.9605845 0.93794059 0.92848499 0.9377675 ] [ True True True True True True True True True]
We then convert arrays to tensors
X_train_tensors = Variable(torch.Tensor(x_train))
X_test_tensors = Variable(torch.Tensor(x_test))
y_train_tensors = Variable(torch.Tensor(y_train))
y_test_tensors = Variable(torch.Tensor(y_test))
We need then to convert the tensors to 3-D shape as LSTM takes sequential data, and so timestamp information.
(We will simply use increasing indexes as timestamp info)
#reshaping to rows, timestamps, features
X_train_tensors_final = torch.reshape(X_train_tensors, (X_train_tensors.shape[0], 1, X_train_tensors.shape[1]))
X_test_tensors_final = torch.reshape(X_test_tensors, (X_test_tensors.shape[0], 1, X_test_tensors.shape[1]))
print("Training Shape", X_train_tensors_final.shape, y_train_tensors.shape)
print("Testing Shape", X_test_tensors_final.shape, y_test_tensors.shape)
Training Shape torch.Size([878, 1, 60]) torch.Size([878, 1]) Testing Shape torch.Size([234, 1, 60]) torch.Size([234, 1])
Now we can create our LSTM:
class myLSTM(nn.Module):
def __init__(self, num_classes, input_size, hidden_size, num_layers, seq_length):
super(myLSTM, self).__init__()
self.num_classes = num_classes #number of classes
self.num_layers = num_layers #number of layers
self.input_size = input_size #input size
self.hidden_size = hidden_size #hidden state
self.seq_length = seq_length #sequence length
self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size,
num_layers=num_layers, batch_first=True) #lstm
# Our dense layer
self.fc = nn.Linear(hidden_size, num_classes)
self.relu = nn.ReLU()
def forward(self,x):
h_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) #hidden state
c_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) #internal state
# Propagate input through LSTM
output, (hn, cn) = self.lstm(x, (h_0, c_0)) #lstm with input, hidden, and internal state
hn = hn.view(-1, self.hidden_size) #reshaping the data for Dense layer next. Il -1 in pytorch assume la dimensionalità basandosi su la shape e l'altro moltiplicatore, in questo caso hidden_size
out = self.relu(hn)
out = self.fc(out)
return out
We define some Global variables...
num_epochs = 1500 #1000 epochs. More than 1500 and it overfits!!!
learning_rate = 0.001 #0.001 lr
input_size = 60 #number of features
hidden_size = 50 #number of features in hidden state
num_layers = 1 #number of stacked lstm layers
num_classes = 1 #number of output classes
... and instanciate our model
lstm = myLSTM(num_classes, input_size, hidden_size, num_layers, X_train_tensors_final.shape[1]) #our lstm class
We define our loss function and our optimizer
loss_fn = torch.nn.MSELoss() # mean-squared error for regression
optimizer = torch.optim.Adam(lstm1.parameters(), lr=learning_rate)
We now train our model!
for epoch in range(num_epochs):
outputs = lstm.forward(X_train_tensors_final) #forward pass
optimizer.zero_grad() #calculate the gradient, manually setting to 0
# Il modello con keras ha come metrica anche l'accuracy, ho provato a calcolarla anche qua confrontando ouput e labels, ma è un errore. Leggi sotto cosa ho scritto:
#train_acc = torch.sum(Variable(torch.Tensor(y_train == outputs.detach().numpy()))) # Can't get accuracy in regression models, we just want to see how close the prediction is, useless to know when it predicts the exact value --> overfit!
# obtain the loss function
loss = loss_fn(outputs, y_train_tensors)
loss.backward() #calculates the loss of the loss function
optimizer.step() #improve from loss, i.e backprop
if epoch % 100 == 0:
print(f"Epoch: {epoch}, loss: {loss.item()}")
Epoch: 0, loss: 0.3505839705467224 Epoch: 100, loss: 0.003500645514577627 Epoch: 200, loss: 0.002669299952685833 Epoch: 300, loss: 0.0019216921646147966 Epoch: 400, loss: 0.001370133482851088 Epoch: 500, loss: 0.0010127387940883636 Epoch: 600, loss: 0.0007733474485576153 Epoch: 700, loss: 0.0006454678368754685 Epoch: 800, loss: 0.0005669034435413778 Epoch: 900, loss: 0.0005129565251991153 Epoch: 1000, loss: 0.00047219780390150845 Epoch: 1100, loss: 0.00043925177305936813 Epoch: 1200, loss: 0.00042482034768909216 Epoch: 1300, loss: 0.0003953732957597822 Epoch: 1400, loss: 0.0003776254307013005
We now predict
predictions = lstm.forward(X_test_tensors_final)
pred = predictions.detach().numpy() # or can be used: predictions.data.numpy()
predictions = scaler.inverse_transform(pred) # inverse tranform on numpy array like converted from tensor
predictions.shape # check the shape!
(234, 1)
Actually quite high RMSE compared to the Keras model!
# Get the root mean squared error (RSME)
rmse = np.sqrt(np.mean(predictions - y_test)**2)
print(rmse)
1.4330431294237447
And we show the results of the pytorch implementation...
# Plot the data
train = data[:train_data_len]
valid = data[train_data_len:]
valid['Predictions'] = predictions
plt.figure(figsize=(16,8))
plt.title(('AMZN stock prediction, RSME =',rmse),fontsize=18)
plt.ylabel('Closing price', fontsize=18)
plt.xlabel('Date', fontsize=18)
plt.plot(train['Close'])
plt.plot(valid[['Close','Predictions']])
plt.legend(['Train','Validation','Predictions'], loc='upper left')
plt.show()
Predicting the next day¶
# Predict the next day
stock_aapl = yf.download('AAPL',
start='2018-01-01',
end='2022-08-28')
# Create new data frame
new_df = stock_aapl.filter(['Close'])
# Get the last 60 days closing price
last_60_days = new_df[-60:].values
# Scale the data
last_60_days_scaled = scaler.transform(last_60_days)
# Append data to a list
new_x_test = []
new_x_test.append(last_60_days_scaled)
new_x_test = np.array(new_x_test)
# Reshape the date
new_x_test = np.reshape(new_x_test,(new_x_test.shape[0],new_x_test.shape[1],1))
# Get the predicted price
price_pred = model.predict(new_x_test)
price_pred = scaler.inverse_transform(price_pred)
print(price_pred)
[*********************100%***********************] 1 of 1 completed [[54.147667]]
We split the dataset
df_sample = data
df_sample[:train_data_len] = data[:train_data_len]
df_sample[train_data_len:] = predictions
We have choosen to calculate the simple moving averages
#Create the 30 day simple moving average
SMA30 = df_sample.rolling(window=30).mean()
SMA30
| Close | |
|---|---|
| Date | |
| 2018-01-02 | NaN |
| 2018-01-03 | NaN |
| 2018-01-04 | NaN |
| 2018-01-05 | NaN |
| 2018-01-08 | NaN |
| ... | ... |
| 2022-08-22 | 128.366192 |
| 2022-08-23 | 129.115955 |
| 2022-08-24 | 129.956921 |
| 2022-08-25 | 130.779187 |
| 2022-08-26 | 131.690558 |
1172 rows × 1 columns
#Create the 100 day simple moving average
SMA100 = df_sample.rolling(window=100).mean()
SMA100
| Close | |
|---|---|
| Date | |
| 2018-01-02 | NaN |
| 2018-01-03 | NaN |
| 2018-01-04 | NaN |
| 2018-01-05 | NaN |
| 2018-01-08 | NaN |
| ... | ... |
| 2022-08-22 | 126.798824 |
| 2022-08-23 | 126.452762 |
| 2022-08-24 | 126.140010 |
| 2022-08-25 | 125.855358 |
| 2022-08-26 | 125.589627 |
1172 rows × 1 columns
# Visually Show The Stock and The Moving Averages
# Create the title
title = 'Adj. Close Price History Simple Moving Averages '
#Create and plot the graph
plt.figure(figsize=(16,8))
plt.plot( df_sample[-150:], label='AMZN')#plt.plot( X-Axis , Y-Axis, line_width, alpha_for_blending, label)
plt.plot( SMA30[-150:], label='SMA30')
plt.plot( SMA100[-150:], label='SMA100')
plt.title(title)
plt.xlabel('Oct. 02, 2006 - Dec. 30, 2011 ',fontsize=18)
plt.ylabel('Adj. Price USD ($)',fontsize=18)
plt.legend( loc='upper left')
plt.show()
We then try to automate the process¶
#Create a function to signal when to buy and sell an asset
def buy_sell(signal):
sigPriceBuy = []
sigPriceSell = []
flag = -1
for i in range(0,len(signal)):
#if sma30 > sma100 then buy else sell
if signal['SMA30'][i] > signal['SMA100'][i]:
if flag != 1:
sigPriceBuy.append(signal['Close'][i])
sigPriceSell.append(np.nan)
flag = 1
else:
sigPriceBuy.append(np.nan)
sigPriceSell.append(np.nan)
#print('Buy')
elif signal['SMA30'][i] < signal['SMA100'][i]:
if flag != 0:
sigPriceSell.append(signal['Close'][i])
sigPriceBuy.append(np.nan)
flag = 0
else:
sigPriceBuy.append(np.nan)
sigPriceSell.append(np.nan)
#print('sell')
else: #Handling nan values
sigPriceBuy.append(np.nan)
sigPriceSell.append(np.nan)
return (sigPriceBuy, sigPriceSell)
#Create a new dataframe
signal = pd.DataFrame(index=df_sample['Close'].index)
signal['Close'] = df_sample['Close']
signal['SMA30'] = SMA30['Close']
signal['SMA100'] = SMA100['Close']
signal
| Close | SMA30 | SMA100 | |
|---|---|---|---|
| Date | |||
| 2018-01-02 | 59.450500 | NaN | NaN |
| 2018-01-03 | 60.209999 | NaN | NaN |
| 2018-01-04 | 60.479500 | NaN | NaN |
| 2018-01-05 | 61.457001 | NaN | NaN |
| 2018-01-08 | 62.343498 | NaN | NaN |
| ... | ... | ... | ... |
| 2022-08-22 | 138.406097 | 128.366192 | 126.798824 |
| 2022-08-23 | 133.884415 | 129.115955 | 126.452762 |
| 2022-08-24 | 134.242996 | 129.956921 | 126.140010 |
| 2022-08-25 | 134.358337 | 130.779187 | 125.855358 |
| 2022-08-26 | 137.381302 | 131.690558 | 125.589627 |
1172 rows × 3 columns
x = buy_sell(signal)
signal['Buy_Signal_Price'] = x[0]
signal['Sell_Signal_Price'] = x[1]
signal
| Close | SMA30 | SMA100 | Buy_Signal_Price | Sell_Signal_Price | |
|---|---|---|---|---|---|
| Date | |||||
| 2018-01-02 | 59.450500 | NaN | NaN | NaN | NaN |
| 2018-01-03 | 60.209999 | NaN | NaN | NaN | NaN |
| 2018-01-04 | 60.479500 | NaN | NaN | NaN | NaN |
| 2018-01-05 | 61.457001 | NaN | NaN | NaN | NaN |
| 2018-01-08 | 62.343498 | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... |
| 2022-08-22 | 138.406097 | 128.366192 | 126.798824 | NaN | NaN |
| 2022-08-23 | 133.884415 | 129.115955 | 126.452762 | NaN | NaN |
| 2022-08-24 | 134.242996 | 129.956921 | 126.140010 | NaN | NaN |
| 2022-08-25 | 134.358337 | 130.779187 | 125.855358 | NaN | NaN |
| 2022-08-26 | 137.381302 | 131.690558 | 125.589627 | NaN | NaN |
1172 rows × 5 columns
# Visually Show The Stock buy and sell signals
# Create the title
title = 'Adj. Close Price History Buy / Sell Signals '
#Get the stocks
my_stocks = signal
ticker = 'Close'
#Create and plot the graph
plt.figure(figsize=(16,8)) #width = 12.2in, height = 4.5
plt.scatter(my_stocks.index, my_stocks['Buy_Signal_Price'], color = 'green', label='Buy Signal', marker = '^', alpha = 1)
plt.scatter(my_stocks.index, my_stocks['Sell_Signal_Price'], color = 'red', label='Sell Signal', marker = 'v', alpha = 1)
plt.plot( my_stocks[ticker], label=ticker, alpha = 0.35)#plt.plot( X-Axis , Y-Axis, line_width, alpha_for_blending, label)
plt.plot( my_stocks['SMA30'], label='SMA30', alpha = 0.35)
plt.plot( my_stocks['SMA100'], label='SMA100', alpha = 0.35)
plt.title(title)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Close Price USD ($)',fontsize=18)
plt.legend( loc='upper left')
plt.show()