diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b134107 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,59 @@ +cmake_minimum_required(VERSION 3.16) + +project(YFinancePP) + +set(CMAKE_CXX_STANDARD 17) + +if (MSVC) + # warning level 4 + add_compile_options(/W4) +else() + # additional warnings + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(Boost 1.81.0 REQUIRED) + +find_package(Doxygen + REQUIRED dot + OPTIONAL_COMPONENTS mscgen dia) + +if (DOXYGEN_FOUND) + # set input and output files + set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/docs/Doxyfile.in) + set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + # request to configure the file + configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + message("Doxygen build started") + + # note the option ALL which allows to build the docs together with the application + add_custom_target( doc_doxygen ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM ) +else (DOXYGEN_FOUND) + message("Doxygen need to be installed to generate the doxygen documentation") +endif (DOXYGEN_FOUND) + + + +include(FetchContent) + +FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git + GIT_TAG 0817715923c9705e68994eb52ef9df3f6845beba) # The commit hash for 1.10.x. Replace with the latest from: https://github.com/libcpr/cpr/releases +FetchContent_MakeAvailable(cpr) + +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) +FetchContent_MakeAvailable(json) + + +add_executable(yfdemo demo/yfdemo.cpp + cpp/base.cpp + cpp/methods.cpp + cpp/requests.cpp + cpp/utils.cpp +) +target_include_directories(yfdemo PRIVATE hpp cpr::cpr nlohmann_json::nlohmann_json) +target_link_libraries(yfdemo PRIVATE cpr::cpr nlohmann_json::nlohmann_json) \ No newline at end of file diff --git a/README.md b/README.md index 9409d43..d4829be 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,31 @@ ### Quick Start This is a quick and simple repository which is still in development. Its aim is to simplify the interaction between the **_Yahoo Finance_** API and **_C++_**. +This project uses [CMake](https://cmake.org/) as its build system. + +It depends on two other projects: + +* [C++ Requests: Curl for People (cpr)](https://github.com/libcpr/cpr) +* [JSON for Modern C++](https://github.com/nlohmann/json) + +This project uses the [Boost Libraries](http://www.boost.org/). + +If you don't have [C++ Requests: Curl for People (cpr)](https://github.com/libcpr/cpr) and/or [JSON for Modern C++](https://github.com/nlohmann/json) you can use CMake's FetchContent to add them. Just add something like + +```cmake +include(FetchContent) + +FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git + GIT_TAG 0817715923c9705e68994eb52ef9df3f6845beba) # The commit hash for 1.10.x. Replace with the latest from: https://github.com/libcpr/cpr/releases +FetchContent_MakeAvailable(cpr) + +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) +FetchContent_MakeAvailable(json) +``` + +to your CMakeLists.txt. Check out this project's [CMakeLists.txt](CMakeLists.txt) to see how to do it. + + ### Version Updates **_v-0.1 (09-30-2022)_**: Added the `get_quotes` and `get_options` member functions for the `Symbol` class. diff --git a/cpp/base.cpp b/cpp/base.cpp index 34f44eb..f9f080d 100644 --- a/cpp/base.cpp +++ b/cpp/base.cpp @@ -1,6 +1,6 @@ -#include "../hpp/base.h" -#include "../hpp/utils.h" -#include "../hpp/methods.h" +#include +#include +#include namespace yfinance { @@ -59,7 +59,7 @@ namespace yfinance { unsigned int size = quotemap["unix"].size(); std::vector open(size), high(size), low(size), close(size); std::vector volume(size); - std::vector unix(size); + std::vector _unix(size); std::transform(quotemap["open"].begin(), quotemap["open"].end(), open.begin(), [](const std::string& token) { return std::stof(token); }); @@ -71,7 +71,7 @@ namespace yfinance { [](const std::string& token) { return std::stof(token); }); std::transform(quotemap["volume"].begin(), quotemap["volume"].end(), volume.begin(), [](const std::string& token) { return std::stoll(token); }); - std::transform(quotemap["unix"].begin(), quotemap["unix"].end(), unix.begin(), + std::transform(quotemap["unix"].begin(), quotemap["unix"].end(), _unix.begin(), [](const std::string& token) { return (time_t)std::stoll(token); }); return Structures::Quotes( @@ -80,7 +80,7 @@ namespace yfinance { std::move(low), std::move(close), std::move(volume), - std::move(unix) + std::move(_unix) ); } else { @@ -113,8 +113,8 @@ namespace yfinance { auto& raw = rjson["optionChain"]["result"][0] ["options"][0][kind]; - unsigned int size = raw.size(); - for (int i = 0; i < size; i++) { + size_t size = raw.size(); + for (size_t i = 0; i < size; i++) { Structures::Option option; for (auto& [key, val] : raw[i].items()) { // As the response from YFINANCE API may be @@ -202,7 +202,7 @@ namespace yfinance { throw std::runtime_error(error_message); } - }; + } nlohmann::json Symbol::get_summary( const std::string&& module diff --git a/cpp/methods.cpp b/cpp/methods.cpp index b0c28e8..56c4697 100644 --- a/cpp/methods.cpp +++ b/cpp/methods.cpp @@ -1,4 +1,5 @@ -#include "../hpp/methods.h" +#include +#include namespace Methods { @@ -24,5 +25,5 @@ namespace Methods { it++; } return indexes; - }; + } } \ No newline at end of file diff --git a/cpp/requests.cpp b/cpp/requests.cpp index b6fcd8d..b215171 100644 --- a/cpp/requests.cpp +++ b/cpp/requests.cpp @@ -1,5 +1,5 @@ -#include "../hpp/requests.h" -#include "../hpp/structures.h" +#include +#include namespace Requests { @@ -13,7 +13,7 @@ namespace Requests { { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; - }; + } Structures::Response Requests( std::string&& url, diff --git a/cpp/utils.cpp b/cpp/utils.cpp index 379b7e4..5815be9 100644 --- a/cpp/utils.cpp +++ b/cpp/utils.cpp @@ -1,5 +1,5 @@ -#include "../hpp/utils.h" -#include "../hpp/structures.h" +#include +#include namespace Utils { diff --git a/demo/news.cpp b/demo/news.cpp index 99eb612..16303a6 100644 --- a/demo/news.cpp +++ b/demo/news.cpp @@ -1,5 +1,5 @@ -#include "../hpp/base.h" -#include "../hpp/benchmark.h" +#include +#include void news() { diff --git a/demo/options.cpp b/demo/options.cpp index 20fef4c..51e2dec 100644 --- a/demo/options.cpp +++ b/demo/options.cpp @@ -1,5 +1,5 @@ -#include "../hpp/base.h" -#include "../hpp/benchmark.h" +#include +#include void options(int argc, char** argv) { diff --git a/demo/quotes.cpp b/demo/quotes.cpp index f1b991d..ec3863d 100644 --- a/demo/quotes.cpp +++ b/demo/quotes.cpp @@ -1,5 +1,5 @@ -#include "../hpp/base.h" -#include "../hpp/benchmark.h" +#include +#include void quotes(int argc, char** argv) { diff --git a/demo/summary.cpp b/demo/summary.cpp index 67afe14..e2f4522 100644 --- a/demo/summary.cpp +++ b/demo/summary.cpp @@ -1,5 +1,5 @@ -#include "../hpp/base.h" -#include "../hpp/benchmark.h" +#include +#include void summary(int argc, char** argv) { diff --git a/demo/yfdemo.cpp b/demo/yfdemo.cpp new file mode 100644 index 0000000..7163aac --- /dev/null +++ b/demo/yfdemo.cpp @@ -0,0 +1,88 @@ +/** + * @file main.cpp + * @author Oliver Ofenloch (57812959+ofenloch@users.noreply.github.com) + * @brief + * @version 0.1 + * @date 2023-12-04 + * + * @copyright Copyright (c) 2023 + * + */ + +#include +#include +int main(int /*argc*/, char * /*argv*/[]) +{ + int iReturnCode = 0; + + // + // demo/news.cpp + // + yfinance::Symbol* symbol; + symbol = new yfinance::Symbol("AAPL"); + // Getting news for the symbol; + auto news = symbol->get_news(); + // Printing the first news; + std::cout << news[0]; + // // Benchmarking; + // auto f = std::bind(&yfinance::Symbol::get_news, symbol); + // auto benchmarkResult = Benchmarking::Timeit(10, f); + // std::cout << benchmarkResult; + + + + // + // demo/options.cpp + // + // Initialize the Ticker object: + yfinance::Symbol *tk; + tk = new yfinance::Symbol("GS"); + // Loading options into struct: + auto options = tk->get_options(); + // Print Option: + std::cout << options["calls"][0]; + // // Benchmarking: + // auto f = std::bind(&yfinance::Symbol::get_options, tk); + // auto timeit = Benchmarking::Timeit(10, f); + // // Printing benchmark results: + // std::cout << timeit; + + // + // demo/quotes.cpp + // + // Initialize the Ticker object: + //yfinance::Symbol* tk; + tk = new yfinance::Symbol("AAPL"); + // Loading quotes into struct: + auto quotes = tk->get_quotes("1d"); + // Print Quotes content: + std::cout << quotes; + // // Benchmarking: + // auto f = std::bind( + // &yfinance::Symbol::get_quotes, tk, + // std::placeholders::_1, std::placeholders::_2, + // std::placeholders::_3, std::placeholders::_4); + // auto timeit = Benchmarking::Timeit(100, f, "1h", -1, -1, ","); + // // Printing benchmark results: + // std::cout << timeit; + + // + // demo/summary.cpp + // + // Initialize the Ticker object: + //yfinance::Symbol* tk; + tk = new yfinance::Symbol("GS"); + // Loading assetProfile into struct: + auto profile = tk->get_profile(); + // Print assetProfile: + std::cout << profile; + // Loading Module (quoteSummary): + auto quoteSummary = tk->get_summary("financialData"); + // Print Module: + for (auto& [k, v] : quoteSummary.items()) + std::cout << k << ':' << v << "\n"; + + + + return iReturnCode; +} \ No newline at end of file diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..8f8f046 --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,12 @@ +PROJECT_NAME = "@CMAKE_PROJECT_NAME@" +PROJECT_NUMBER = @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@ +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ +INPUT = @doxy_main_page@ \ + @PROJECT_SOURCE_DIR@ \ + @PROJECT_BINARY_DIR@ +FILE_PATTERNS = *.cpp \ + *.h \ + *.hpp \ + *.cc +RECURSIVE = YES +USE_MDFILE_AS_MAINPAGE = @doxy_main_page@ diff --git a/hpp/base.h b/hpp/base.h index fee2f2b..b0a99ef 100644 --- a/hpp/base.h +++ b/hpp/base.h @@ -1,13 +1,14 @@ -#pragma once +#ifndef _BASE_H_ +#define _BASE_H_ #include -#include "boost/lexical_cast.hpp" +#include #include #include #include #include #include -#include "../hpp/structures.h" -#include "../hpp/utils.h" +#include +#include using json = nlohmann::json; @@ -50,4 +51,6 @@ namespace yfinance { ); }; -} \ No newline at end of file +} + +#endif // #ifndef _BASE_H_ \ No newline at end of file diff --git a/hpp/benchmark.h b/hpp/benchmark.h index 210b123..cd84d08 100644 --- a/hpp/benchmark.h +++ b/hpp/benchmark.h @@ -1,6 +1,7 @@ -#pragma once -#include "structures.h" -#include "utils.h" +#ifndef _BENCHMARK_H_ +#define _BENCHMARK_H_ +#include +#include namespace Benchmarking { @@ -25,5 +26,6 @@ namespace Benchmarking { milliseconds sum = std::accumulate(durations.begin(), durations.end(), milliseconds(0)); milliseconds avg = sum / durations.size(); return Structures::TimeitResult(iters, min, max, avg, sum); - }; -} \ No newline at end of file + } +} +#endif // #ifndef _BENCHMARK_H_ \ No newline at end of file diff --git a/hpp/methods.h b/hpp/methods.h index 895b2c3..9635113 100644 --- a/hpp/methods.h +++ b/hpp/methods.h @@ -1,4 +1,6 @@ -#pragma once +#ifndef _METHODS_H_ +#define _METHODS_H_ + #include #include @@ -14,4 +16,6 @@ namespace Methods { const std::vector& v, const std::vector& z ); -} \ No newline at end of file +} + +#endif // #ifndef _METHODS_H_ \ No newline at end of file diff --git a/hpp/requests.h b/hpp/requests.h index 2ec997b..189b9c0 100644 --- a/hpp/requests.h +++ b/hpp/requests.h @@ -1,11 +1,14 @@ -#pragma once +#ifndef _REQUESTS_H_ +#define _REQUESTS_H_ + #include #include #include -#include "structures.h" +#include using payload = std::unordered_map; -static const const char* USER_AGENT = - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"; +static const /*const*/ char* USER_AGENT = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"; + namespace Requests { @@ -19,4 +22,5 @@ namespace Requests { const payload&& params = {} ); -} \ No newline at end of file +} +#endif // #ifndef _REQUESTS_H_ \ No newline at end of file diff --git a/hpp/structures.h b/hpp/structures.h index 4bb95ac..b85e9ba 100644 --- a/hpp/structures.h +++ b/hpp/structures.h @@ -1,4 +1,6 @@ -#pragma once +#ifndef _STRUCTURES_H +#define _STRUCTURES_H + #include #include #include @@ -30,14 +32,14 @@ namespace Structures { std::vector low, std::vector close, std::vector volume, - std::vector unix + std::vector _unix ) : m_open(open), m_high(high), m_low(low), m_close(close), m_volume(volume), - m_unix(unix) + m_unix(_unix) {}; friend std::ostream& operator<<( @@ -106,12 +108,12 @@ namespace Structures { m_strike(strike), m_lastPrice(lastPrice), m_change(change), + m_volume(volume), m_bid(bid), m_ask(ask), m_percentChange(percentChange), m_openInterest(openInterest), m_impliedVolatility(impliedVolatility), - m_volume(volume), m_expiration(expiration), m_lastTradeDate(lastTradeDate) {}; @@ -232,10 +234,10 @@ namespace Structures { stream << "=======================================================================\n\n"; stream << "\tIterations completed\t: " << t.m_iters << "\n"; - stream << "\tTotal milliseconds\t:" << t.m_sum << "\n"; - stream << "\tAverage milliseconds\t:" << t.m_avg << "\n"; - stream << "\tMaxima milliseconds\t:" << t.m_max << "\n"; - stream << "\tMinima milliseconds\t:" << t.m_min << "\n\n\n"; + stream << "\tTotal milliseconds\t:" << t.m_sum.count() << "\n"; + stream << "\tAverage milliseconds\t:" << t.m_avg.count() << "\n"; + stream << "\tMaxima milliseconds\t:" << t.m_max.count() << "\n"; + stream << "\tMinima milliseconds\t:" << t.m_min.count() << "\n\n\n"; return stream; } }; @@ -302,4 +304,6 @@ namespace Structures { }; }; -} \ No newline at end of file +} + +#endif // #ifndef _STRUCTURES_H \ No newline at end of file diff --git a/hpp/utils.h b/hpp/utils.h index a2ef2f7..daed8ed 100644 --- a/hpp/utils.h +++ b/hpp/utils.h @@ -5,7 +5,7 @@ #include #include #include -#include "../hpp/structures.h" +#include using time_point = std::chrono::time_point;