@@ -22,12 +22,14 @@ std::string address(std::string ticker){
22
22
return url;
23
23
}
24
24
25
+ // Takes part in decrypting bytes to be transferred into a string result
25
26
size_t WriteCallback (void * contents, size_t size, size_t nmemb, std::string* response) {
26
27
size_t totalSize = size * nmemb;
27
28
response->append ((char *)contents, totalSize);
28
29
return totalSize;
29
30
}
30
31
32
+ // Sends a rest request to polygon to fetch the stock data
31
33
std::string RequestData (const std::string& url) {
32
34
CURL* curl;
33
35
CURLcode res;
@@ -55,16 +57,21 @@ std::string RequestData(const std::string& url) {
55
57
return response; // Return the response
56
58
}
57
59
60
+ // Sleep timer
58
61
void Sleep (int wait_time){
59
62
std::this_thread::sleep_for (std::chrono::seconds (wait_time));
60
63
}
61
64
65
+ // Imports historical stock price data from Polygon.io and sorts them into a map with the key being the stock ticker
66
+ // and the value being the vector of close prices
62
67
std::map<std::string, std::vector<double >> ImportHistoricalData (std::vector<std::string> tickers, int wait_time){
63
68
std::map<std::string, std::vector<double >> result;
64
69
std::cout << " Stock data is loading" << std::endl;
65
70
for (auto & stock : tickers){
66
71
Sleep (wait_time);
67
72
std::cout << stock << " is imported" << std::endl;
73
+
74
+ // Fetch stock price data and parse string result as JSON with Boost
68
75
std::string response = RequestData (address (stock));
69
76
ptree data;
70
77
std::stringstream ss (response);
@@ -74,6 +81,7 @@ std::map<std::string, std::vector<double>> ImportHistoricalData(std::vector<std:
74
81
for (ptree::const_iterator jt = it->second .begin (); jt != it->second .end (); ++jt){
75
82
for (ptree::const_iterator kt = jt->second .begin (); kt != jt->second .end (); ++kt){
76
83
if (kt->first == " l" ){
84
+ // Pull close prices for the stock into the map
77
85
result[stock].push_back (atof (kt->second .get_value <std::string>().c_str ()));
78
86
}
79
87
}
@@ -85,7 +93,10 @@ std::map<std::string, std::vector<double>> ImportHistoricalData(std::vector<std:
85
93
return result;
86
94
}
87
95
96
+ // Calculates the distribution charts per ticker and stores the results in the modify map
88
97
void ComputeData (std::vector<double > close, std::string ticker, std::map<std::string, std::map<std::string, std::vector<double >>> & modify){
98
+
99
+ // Computes the average of a given vector of values
89
100
auto average = [](std::vector<double > x){
90
101
double total = 0 ;
91
102
for (auto & i : x){
@@ -95,6 +106,7 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
95
106
return total;
96
107
};
97
108
109
+ // Computes the standard deviation of a given vector of values
98
110
auto volatility = [&](std::vector<double > x){
99
111
double mu = average (x);
100
112
double total = 0 ;
@@ -105,23 +117,30 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
105
117
return pow (total, 0.5 );
106
118
};
107
119
120
+ // Stochastic parameter in Geometric Brownian Motion which returns a value between -10 to 10 percent
108
121
auto dWT = [](){
109
122
int num = 10 ;
110
123
double dw = (rand () % (2 *num + 1 )) - num;
111
124
return dw/100.0 ;
112
125
};
113
126
127
+ // Takes in the stock returns and the number of bins and generates a histogram
114
128
auto histogram = [](std::vector<double > returns, int bins){
115
129
std::map<std::string, std::vector<double >> res;
130
+
131
+ // Sort the returns and set the bounds of the histogram
116
132
std::sort (returns.begin (), returns.end ());
117
133
double m0 = returns[0 ];
118
134
double m1 = returns[returns.size () - 1 ];
119
135
double dm = (m1 - m0)/((double ) bins);
136
+
137
+ // Count the frequency of each return group occuring, return group is between 'a' and 'b'
120
138
for (int i = 0 ; i < bins; ++i){
121
139
double a = m0 + i*dm;
122
140
double b = m0 + (i+1 )*dm;
123
141
int count = 0 ;
124
142
for (auto & r : returns){
143
+ // Counts the frequency
125
144
if (i == bins - 1 ){
126
145
if (r >= a && r <= b){
127
146
count += 1 ;
@@ -132,17 +151,22 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
132
151
}
133
152
}
134
153
}
154
+ // Pushes x and y parameters in histogram map
135
155
double mid = 0.5 *(a + b);
136
156
res[" x" ].push_back (mid);
137
157
res[" y" ].push_back (count);
138
158
}
139
159
return res;
140
160
};
141
-
161
+
142
162
std::vector<double > ror, ror_predict, stock_paths;
163
+
164
+ // Calculates the rate of return of the current selected stock
143
165
for (int i = 1 ; i < close.size (); ++i){
144
166
ror.push_back (close[i]/close[i-1 ] - 1.0 );
145
167
}
168
+
169
+ // Sets the parameters for the Geometric Brownian Motion equation
146
170
double S = close[close.size () - 1 ];
147
171
double mu = average (ror);
148
172
double t = 1.0 /12.0 ;
@@ -151,9 +175,12 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
151
175
int P = 100 ;
152
176
double dt = t / (double ) N;
153
177
154
- // mu*S*dt + v*S*dWT()
178
+ // Formula = mu*S*dt + v*S*dWT()
179
+
180
+ // Makes sure each run is random
155
181
srand (time (NULL ));
156
182
183
+ // Running the GBM simulation
157
184
for (int p = 0 ; p < P; ++p){
158
185
double S0 = S;
159
186
for (int t = 0 ; t < N; ++t){
@@ -162,13 +189,18 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
162
189
stock_paths.push_back (S0);
163
190
}
164
191
192
+ // Computing the rate of return from the predicted stock paths
165
193
for (int i = 1 ; i < stock_paths.size (); ++i){
166
194
ror_predict.push_back (stock_paths[i]/stock_paths[i-1 ] - 1.0 );
167
195
}
168
196
197
+ // Generating the histogram with 30 bins for both groups (historical and predicted)
169
198
std::map<std::string, std::vector<double >> RHist = histogram (ror, 30 );
170
199
std::map<std::string, std::vector<double >> RPred = histogram (ror_predict, 30 );
171
200
201
+ // Storing everything in the modify result map which has the first key being a stock ticker
202
+ // and the second key being x,y hist/pred
203
+
172
204
modify[ticker][" xhist" ] = RHist[" x" ];
173
205
modify[ticker][" yhist" ] = RHist[" y" ];
174
206
modify[ticker][" xpred" ] = RPred[" x" ];
@@ -179,27 +211,35 @@ void ComputeData(std::vector<double> close, std::string ticker, std::map<std::st
179
211
180
212
int main ()
181
213
{
214
+ // Selected stocks to be examined
182
215
std::vector<std::string> tickers = {" MSFT" ," AAPL" ," NVDA" ," AMZN" ," IBM" ," ORCL" };
216
+
217
+ // Building the plot grid for the histograms
183
218
std::vector<PyObject*> plots;
184
219
std::vector<int > pnum = {231 , 232 , 233 , 234 , 235 , 236 };
185
220
for (auto & number : pnum){
186
221
plots.push_back (plt::chart2D (number));
187
222
}
188
223
224
+ // Set sleep time
189
225
int sleep_for_time = 10 ;
190
226
227
+ // Import the historical data and declare storage map
191
228
std::map<std::string, std::vector<double >> close = ImportHistoricalData (tickers, sleep_for_time);
192
229
std::map<std::string, std::map<std::string, std::vector<double >>> modify;
193
-
230
+
231
+ // Build a vector of threads to calculate all inputted stocks simulations at the same time
194
232
std::vector<std::thread> items;
195
233
for (auto & ticker : tickers){
196
234
items.emplace_back (ComputeData, close[ticker], ticker, std::ref (modify));
197
235
}
198
236
237
+ // Join the threads upon completion to end each thread
199
238
for (auto & plane : items){
200
239
plane.join ();
201
240
}
202
241
242
+ // Plot the distributions
203
243
for (int i = 0 ; i < plots.size (); ++i){
204
244
PyObject * ax = plots[i];
205
245
std::string tick = tickers[i];
@@ -211,4 +251,4 @@ int main()
211
251
plt::show ();
212
252
213
253
return 0 ;
214
- }
254
+ }
0 commit comments