#include #include #include #include #include #include #include #include // libcurl hands the body over in pieces: append each one to a string static size_t append(char* data, size_t size, size_t n, void* body) { static_cast(body)->append(data, size * n); return size * n; } int main() { // Read both funds' files; each has the date of its own issuer's file std::vector> funds; for (std::string ticker : {"voo", "qqq"}) { std::string url = "https://tickerinside.com/api/v1/fund/" + ticker + ".json"; std::string body; CURL* curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_USERAGENT, "MyProject/1.0 (+https://example.com)"); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, append); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body); CURLcode rc = curl_easy_perform(curl); curl_easy_cleanup(curl); if (rc != CURLE_OK) { std::cerr << curl_easy_strerror(rc) << "\n"; return 1; } auto fund = nlohmann::json::parse(body); std::cout << fund["ticker"].get() << " holdings_as_of " << fund["holdings_as_of"].get() << "\n"; funds.emplace_back(ticker, fund); } // Overlap by weight, as the site computes it: for every ticker both // funds hold, add the smaller of its two weights auto& a = funds[0].second["holdings"]; auto& b = funds[1].second["holdings"]; double overlap = 0; int shared = 0; for (auto& [t, w] : a.items()) { if (b.contains(t)) { overlap += std::min(w.get(), b[t].get()); ++shared; } } std::cout << "overlap by weight " << std::fixed << std::setprecision(1) << overlap << "%, " << shared << " companies in both\n"; // The lines to print under the figure, one per fund file for (auto& [ticker, fund] : funds) { std::cout << fund["cite_as"].get() << "\n"; } }