-
-
Save anthonymorast/43038e9cd67a96f90b9d4719f38fa84b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include "matplotlib.h" // plotting | |
#include "yfapi.h" // data API | |
namespace plt = matplotlibcpp; | |
using namespace std; | |
/* | |
Transforms a primitve array into a std::vector of the | |
approriate type. | |
*/ | |
vector<float> array_to_vector(float* arr, size_t size) | |
{ | |
vector<float> vec; | |
for(int i = 0; i < size; i++) | |
{ | |
vec.push_back(arr[i]); | |
} | |
return vec; | |
} | |
/* | |
Makes the closing data indepent of the actual trading price | |
of the ETFs by squeezing the values between 0 and 1. | |
*/ | |
float** normalize_close(datatable::DataTable<float> data) | |
{ | |
float* cdata = data.get_column("Close"); | |
float min = MAXFLOAT, max = -MAXFLOAT; | |
for(int i = 0; i < data.nrows(); i++) | |
{ | |
min = cdata[i] < min ? cdata[i] : min; | |
max = cdata[i] > max ? cdata[i] : max; | |
} | |
delete cdata; | |
float** new_data = new float*[1]; | |
float* close = data.get_column("Close"); | |
for(int i = 0; i < data.nrows(); i++) | |
{ | |
close[i] = (close[i] - min) / (max - min); | |
} | |
new_data[0] = close; | |
return new_data; | |
} | |
/* | |
An easy way to retrieve the data from the API, normalize the close prices, and | |
reformat into a matplotlibcpp acceptable format. | |
*/ | |
vector<float> get_close_vector_for_ticker(string ticker, string start_date, string end_date, yfapi::YahooFinanceAPI api) | |
{ | |
datatable::DataTable<float> data = api.get_ticker_data(ticker, start_date, end_date); | |
float** normal_data = normalize_close(data); | |
vector<float> vec_data = array_to_vector(normal_data[0], data.nrows()); | |
delete[] normal_data; | |
return vec_data; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
yfapi::YahooFinanceAPI api; | |
int number_tickers = 4; | |
string start_date = "2021-01-01", end_date = "2021-12-31"; | |
string tickers[number_tickers] = { "XRT", "SOXX", "VDE", "VHT" }; | |
// get the baseline data: price data from the SPY ETF which tracks the S&P 500 | |
vector<float> spy = get_close_vector_for_ticker("spy", start_date, end_date, api); | |
int min = spy.size(); // used to determine how many points there are in common with the other ETFs | |
for(int i = 0; i < number_tickers; i++) | |
{ | |
cout << "Processing " << tickers[i] << endl; | |
// get the data for the ticker | |
vector<float> ticker_data = get_close_vector_for_ticker(tickers[i], start_date, end_date, api); | |
// divergence array will use all of the data that is available in both ETFs | |
min = min < ticker_data.size() ? min : ticker_data.size(); | |
// calculate divergence and fill up some plotting arrays | |
float* divergence = new float[min]; | |
vector<int> fillx, filly1, filly2, zero; | |
for(int j = 0; j < min; j++) | |
{ | |
divergence[j] = ticker_data[j] - spy[j]; | |
fillx.push_back(j); // used to plot; x-values | |
zero.push_back(0); // used to fill red and green areas | |
filly1.push_back(1); // used to fill green section (divergence < 0) | |
filly2.push_back(-1); // used to fill red section (divergence > 0) | |
} | |
// plot the current sector ETF | |
plt::plot(ticker_data, {{"label", tickers[i]}}); | |
plt::plot(spy, {{"label", "SPY"}}); // plot SPY | |
plt::plot(array_to_vector(divergence, min), {{"label", "Divergence"}}); // plot the divergence line | |
plt::axhline(0, 0, 1, {{"color", "black"}}); // draw the line at y = 0 | |
// matplotlibcpp's way of passing extra parameters to the plot | |
map<string, string> fill_parameters; | |
fill_parameters["color"] = "green"; | |
fill_parameters["alpha"] = "0.2"; | |
plt::fill_between(fillx, zero, filly1, fill_parameters); // green fill | |
fill_parameters["color"] = "red"; | |
plt::fill_between(fillx, zero, filly2, fill_parameters); // red fill | |
plt::xlabel("Days"); | |
plt::ylabel("Price"); | |
plt::legend(); | |
//plt::show(); | |
plt::save("plots/" + tickers[i] + ".png"); // save the plot | |
plt::clf(); // clear the plot | |
delete divergence; // don't leak memory | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment