1
+ import numpy as np
2
+
3
+ import matplotlib .pyplot as plt
4
+
5
+ from stock_prediction import create_model , load_data
6
+ from parameters import *
7
+
8
+
9
+ def plot_graph (test_df ,MY_LOOKUP_STEP ):
10
+ """
11
+ This function plots true close price along with predicted close price
12
+ with blue and red colors respectively
13
+ """
14
+ plt .plot (test_df [f'true_adjclose_{ MY_LOOKUP_STEP } ' ], c = 'k' )
15
+ plt .plot (test_df [f'adjclose_{ MY_LOOKUP_STEP } ' ], c = 'bo' )
16
+ plt .xlabel ("Days" )
17
+ plt .ylabel ("Price" )
18
+ plt .legend (["Actual Price" , "Predicted Price" ])
19
+ plt .show ()
20
+
21
+
22
+ def get_final_df (model , data , MY_LOOKUP_STEP ):
23
+ """
24
+ This function takes the `model` and `data` dict to
25
+ construct a final dataframe that includes the features along
26
+ with true and predicted prices of the testing dataset
27
+ """
28
+ # if predicted future price is higher than the current,
29
+ # then calculate the true future price minus the current price, to get the buy profit
30
+ buy_profit = lambda current , pred_future , true_future : true_future - current if pred_future > current else 0
31
+ # if the predicted future price is lower than the current price,
32
+ # then subtract the true future price from the current price
33
+ sell_profit = lambda current , pred_future , true_future : current - true_future if pred_future < current else 0
34
+ X_test = data ["X_test" ]
35
+ y_test = data ["y_test" ]
36
+ # perform prediction and get prices
37
+ y_pred = model .predict (X_test )
38
+ if SCALE :
39
+ y_test = np .squeeze (data ["column_scaler" ]["adjclose" ].inverse_transform (np .expand_dims (y_test , axis = 0 )))
40
+ y_pred = np .squeeze (data ["column_scaler" ]["adjclose" ].inverse_transform (y_pred ))
41
+ test_df = data ["test_df" ]
42
+ # add predicted future prices to the dataframe
43
+ test_df [f"adjclose_{ MY_LOOKUP_STEP } " ] = y_pred
44
+ # add true future prices to the dataframe
45
+ test_df [f"true_adjclose_{ MY_LOOKUP_STEP } " ] = y_test
46
+ # sort the dataframe by date
47
+ test_df .sort_index (inplace = True )
48
+ final_df = test_df
49
+ # add the buy profit column
50
+ final_df ["buy_profit" ] = list (map (buy_profit ,
51
+ final_df ["adjclose" ],
52
+ final_df [f"adjclose_{ MY_LOOKUP_STEP } " ],
53
+ final_df [f"true_adjclose_{ MY_LOOKUP_STEP } " ])
54
+ # since we don't have profit for last sequence, add 0's
55
+ )
56
+ # add the sell profit column
57
+ final_df ["sell_profit" ] = list (map (sell_profit ,
58
+ final_df ["adjclose" ],
59
+ final_df [f"adjclose_{ MY_LOOKUP_STEP } " ],
60
+ final_df [f"true_adjclose_{ MY_LOOKUP_STEP } " ])
61
+ # since we don't have profit for last sequence, add 0's
62
+ )
63
+ return final_df
64
+
65
+
66
+ def predict (model , data ):
67
+ # retrieve the last sequence from data
68
+ last_sequence = data ["last_sequence" ][- N_STEPS :]
69
+ # expand dimension
70
+ last_sequence = np .expand_dims (last_sequence , axis = 0 )
71
+ # get the prediction (scaled from 0 to 1)
72
+ prediction = model .predict (last_sequence )
73
+ # get the price (by inverting the scaling)
74
+ if SCALE :
75
+ predicted_price = data ["column_scaler" ]["adjclose" ].inverse_transform (prediction )[0 ][0 ]
76
+ else :
77
+ predicted_price = prediction [0 ][0 ]
78
+ return predicted_price
79
+
80
+ predictions = []
81
+ # predictions = np.array(float)
82
+ # predictions.resize(30)
83
+ for MY_LOOKUP_STEP in range (1 , 30 ):
84
+
85
+ # load the data
86
+ data = load_data (ticker , N_STEPS , scale = SCALE , split_by_date = SPLIT_BY_DATE ,
87
+ shuffle = SHUFFLE , lookup_step = MY_LOOKUP_STEP , test_size = TEST_SIZE ,
88
+ feature_columns = FEATURE_COLUMNS )
89
+
90
+ # construct the model
91
+ model = create_model (N_STEPS , len (FEATURE_COLUMNS ), loss = LOSS , units = UNITS , cell = CELL , n_layers = N_LAYERS ,
92
+ dropout = DROPOUT , optimizer = OPTIMIZER , bidirectional = BIDIRECTIONAL )
93
+
94
+ my_model_name = f"{ date_now } _{ ticker } -{ shuffle_str } -{ scale_str } -{ split_by_date_str } -\
95
+ { LOSS } -{ OPTIMIZER } -{ CELL .__name__ } -seq-{ N_STEPS } -step-{ MY_LOOKUP_STEP } -layers-{ N_LAYERS } -units-{ UNITS } "
96
+ if BIDIRECTIONAL :
97
+ my_model_name += "-b"
98
+
99
+ # load optimal model weights from results folder
100
+ model_path = os .path .join ("results" , my_model_name ) + ".h5"
101
+ model .load_weights (model_path )
102
+
103
+ # evaluate the model
104
+ loss , mae = model .evaluate (data ["X_test" ], data ["y_test" ], verbose = 0 )
105
+ # calculate the mean absolute error (inverse scaling)
106
+ if SCALE :
107
+ mean_absolute_error = data ["column_scaler" ]["adjclose" ].inverse_transform ([[mae ]])[0 ][0 ]
108
+ else :
109
+ mean_absolute_error = mae
110
+
111
+ # get the final dataframe for the testing set
112
+ final_df = get_final_df (model , data , MY_LOOKUP_STEP )
113
+ # predict the future price
114
+ future_price = predict (model , data )
115
+ # we calculate the accuracy by counting the number of positive profits
116
+ accuracy_score = (len (final_df [final_df ['sell_profit' ] > 0 ]) + len (final_df [final_df ['buy_profit' ] > 0 ])) / len (final_df )
117
+ # calculating total buy & sell profit
118
+ total_buy_profit = final_df ["buy_profit" ].sum ()
119
+ total_sell_profit = final_df ["sell_profit" ].sum ()
120
+ # total profit by adding sell & buy together
121
+ total_profit = total_buy_profit + total_sell_profit
122
+ # dividing total profit by number of testing samples (number of trades)
123
+ profit_per_trade = total_profit / len (final_df )
124
+ # Append new prediction to array
125
+ # predictions[MY_LOOKUP_STEP] = future_price
126
+ predictions .append (future_price )
127
+ # printing metrics
128
+ print (f"Future price after { MY_LOOKUP_STEP } days is { future_price :.2f} $" )
129
+ print (f"{ LOSS } loss:" , loss )
130
+ print ("Mean Absolute Error:" , mean_absolute_error )
131
+ print ("Accuracy score:" , accuracy_score )
132
+ print ("Total buy profit:" , total_buy_profit )
133
+ print ("Total sell profit:" , total_sell_profit )
134
+ print ("Total profit:" , total_profit )
135
+ print ("Profit per trade:" , profit_per_trade )
136
+ # plot true/pred prices graph
137
+ plot_graph (final_df ,MY_LOOKUP_STEP )
138
+ print (final_df .tail (10 ))
139
+ print (f"Future price after { MY_LOOKUP_STEP } days is { future_price :.2f} $" )
140
+ # save the final dataframe to csv-results folder
141
+ csv_results_folder = "csv-results"
142
+ if not os .path .isdir (csv_results_folder ):
143
+ os .mkdir (csv_results_folder )
144
+ csv_filename = os .path .join (csv_results_folder , my_model_name + ".csv" )
145
+ final_df .to_csv (csv_filename )
146
+ print (predictions )
147
+ predictions = np .array (predictions )
148
+ predictions .tofile (f"{ csv_results_folder } \evaluate30_{ date_now } _{ ticker } .csv" ,"," )
0 commit comments