The offcenter_oanda project is a C++ library that provides access to the OANDA v20 REST API.
This project is hosted on github under user CodeRancher.
To clone this repository use the git command:
git clone https://github.com/CodeRancher/offcenter_oanda.gitThe most simple build, if dependencies are installed globally.
cd offcenter_oanda
mkdir build
cd build
cmake ..
makeA more complicated build if the libraries are in non-standard locations.
cd offcenter_oanda
mkdir build
cd build
cmake \
-DCMAKE_INSTALL_PREFIX=<installation path> \
-DBUILD_DOC=<ON|OFF> \
-DCMAKE_PREFIX_PATH="<nlohmann json path>;<cpprestsdk path>" \
-DBOOST_ROOT=<boost root> \
-DEASYLOGGINGPP_ROOT=<easyloggingpp root> \
-DEASYLOGGINGPP_USE_STATIC_LIBS=<ON|OFF> \
-DGTEST_ROOT=<googletest root> \
..
make installImportant make commands.
| Command | Action |
|---|---|
| make | Build library. Build documentation if ${BUILD_DOC}=ON |
| make install | Build library and install to ${CMAKE_INSTALL_PREFIX}. Build documentation if ${BUILD_DOC}=ON |
| make doc_doxygen | Build library. Build documentation if ${BUILD_DOC}=ON |
Important cmake build variables.
| Variable | Description | Examples |
|---|---|---|
| CMAKE_INSTALL_PREFIX | Install directory for make install. |
e.g. ${HOME}/libs |
| CMAKE_PREFIX_PATH | Directories to search during make. |
${HOME}/libs/cmake/nlohmann_json;${HOME}/libs/cmake/cpprestsdk |
| BUILD_DOC | Build Doxygen documentation during make doc_doxygen. Can be 'ON' or 'OFF'. |
ON |
| LOG_V20_ACCESS | Build with logging to EasyLogging++. Can be 'ON' or 'OFF'. | ON |
| BOOST_ROOT | Boost library location. | e.g. ${HOME}/libs |
| EASYLOGGINGPP_ROOT | Easylogging++ library location. | e.g. ${HOME}/libs |
| EASYLOGGINGPP_USE_STATIC_LIBS | If ${EASYLOGGINGPP_USE_STATIC_LIBS} is ON then static libs are searched. | ON |
| GTEST_ROOT | The root directory of the Google Test installation. | e.g. ${HOME}/libs |
| Library | Minimum Version | License |
|---|---|---|
| nlohmann json | 3.9.1 | MIT |
| C++ REST SDK | 2.10.16 | MIT |
| Boost | 1.74 | Boost Software License 1.0 |
| Easylogging++ | 9.97.0 | MIT |
| GoogleTest | 1.10.0 | BSD 3-Clause "New" or "Revised" License (modified) |
| OpenSSL | 1.1.1 |
| Tools |
|---|
| Doxygen |
The offcenter_oanda C++ library has been designed to mimic the OANDA v20 REST API as much as possible.
Accessing the OANDA v20 REST API will follow a simple pattern of:
- Connect to Oanda endpoint
- Initialize the Request data needed by the endpoint
- Initialize the Parameter data needed by the endpoint
- Call the endpoint (Synchronous or Asynchronous) with the Request and Parameter data and callback lambda
- The callback lambda will have the Response data returned from the OANDA v20 REST API.
Here is a simple application that will retrieve the last 1000 Daily Mid candlesticks for the EUR/USD and print them out in a csv format.
Command Line
The Oanda Access Token and User Acount number are needed for this example.
Expected command line:
eur_usd_to_csv <access_token> <account>
access_token: Oanda supplied access token
account: User AccountHeader Files
The iostream and OandaEndpints.hpp header files are required for this example. Typically the OandaEndpints.hpp header is all you will need to access this library.
#include <iostream>
#include "oanda/v20/endpoint/OandaEndpoints.hpp"
using namespace oanda::v20;
Validate Command Line
This is a simple way to validate the expected command line.
if(argc != 3) {
std::cerr << "Incorrect Number Of Arguments: " << argc << std::endl;
std::cerr << "Expected command line:" << std::endl << std::endl;
std::cerr << " eur_usd_to_csv <access_token> <account>" << std::endl << std::endl;
std::cerr << "access_token: Oanda supplied access token" << std::endl;
std::cerr << "account: User Account" << std::endl;
return 1;
}
Connect to the Oanda Server
Connecting to the Oanda server requires the type of server to connect to (practice or trade) and the Oanda Access Token.
endpoint::OandaPracticeServer server;
endpoint::OandaAuthorization authorization(argv[1]);
endpoint::OandaEndpoints oandaEndpoints(server, authorization);
Request and Parameters
Each call to the OANDA v20 REST API may have a set of parameters (header, path, or query) or a request body (in json). These are set by using the Request and Parameters classes required by each endpoint call.
endpoint::pricing::candles::Request request;
endpoint::pricing::candles::Parameters parameters;
parameters.accountID = argv[2];
parameters.instrument = "EUR_USD";
parameters.granularity = "D";
parameters.price = "M";
parameters.smooth = "True";
parameters.count = "1000";
Call Endpoint
Call the endpoint with the request and parameters values. The endpoint can be called synchronously (sync) or asynchronously (async). The callback lambda will receive the data returned from the call.
The to_string(candles.granularity, granularity) helper will convert the granularity enum into a string.
oandaEndpoints.pricing.candles(request, parameters)->sync([](endpoint::pricing::candles::Response candles) -> void {
std::string granularity;
to_string(candles.granularity, granularity);
// Output headers
std::cout <<
candles.instrument << " - " << granularity << "," <<
"Open," << "Low," << "High," << "Close" << std::endl;
// Output candlestick values
for (oanda::v20::instrument::Candlestick& candlestick : candles.candles) {
std::cout <<
candlestick.time << "," << candlestick.mid.o << "," << candlestick.mid.l << "," <<
candlestick.mid.h << "," << candlestick.mid.c << std::endl;
}
});
Complete Example
Here is the complete example (with logging).
#include <iostream>
#include "easylogging++.h"
INITIALIZE_EASYLOGGINGPP
#include "oanda/v20/endpoint/OandaEndpoints.hpp"
using namespace oanda::v20;
/**
* Query Oanda for a 1000 daily mid candles for EUR/USD that are smoothed.
*/
int main(int argc, char* argv[])
{
START_EASYLOGGINGPP(argc, argv);
// Move logging to a file so stdout is not flooded
el::Loggers::reconfigureAllLoggers(el::ConfigurationType::ToFile, "true");
el::Loggers::reconfigureAllLoggers(el::ConfigurationType::ToStandardOutput, "false");
el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Format, "%datetime:%thread [%level] %msg");
el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Filename, "eur_usd_to_csv.log");
// Verify correct number of command line arguments
if(argc != 3) {
std::cerr << "Incorrect Number Of Arguments: " << argc << std::endl;
std::cerr << "Expected command line:" << std::endl << std::endl;
std::cerr << " eur_usd_to_csv <access_token> <account>" << std::endl << std::endl;
std::cerr << "access_token: Oanda supplied access token" << std::endl;
std::cerr << "account: User Account" << std::endl;
return 1;
}
// Connect to the Oanda server
endpoint::OandaPracticeServer server;
endpoint::OandaAuthorization authorization(argv[1]);
std::string accountID = argv[2];
endpoint::OandaEndpoints oandaEndpoints(server, authorization);
// Initialize Request and Parameter values
endpoint::pricing::candles::Request request;
endpoint::pricing::candles::Parameters parameters;
parameters.accountID = accountID;
parameters.instrument = "EUR_USD";
parameters.granularity = "D";
parameters.price = "M";
parameters.smooth = "True";
parameters.count = "1000";
// Synchronously retrieve the candle values
oandaEndpoints.pricing.candles(request, parameters)->sync([](endpoint::pricing::candles::Response candles) -> void {
std::string granularity;
to_string(candles.granularity, granularity);
// Output headers
std::cout <<
candles.instrument << " - " << granularity << "," <<
"Open," <<
"Low," <<
"High," <<
"Close" << std::endl;
// Output candlestick values
for (oanda::v20::instrument::Candlestick& candlestick : candles.candles) {
std::cout <<
candlestick.time << "," <<
candlestick.mid.o << "," <<
candlestick.mid.l << "," <<
candlestick.mid.h << "," <<
candlestick.mid.c << std::endl;
}
});
return 0;
}
Testing
The library needs testing from end-to-end. There are basic tests and examples for some of the most used calls but the rest of the system needs validation.
One problem with testing much of the system is that the repeated calls to Oanda can trigger a violation of their policies and get the account cancelled. Testing needs to be performed carefully.
Documentation
- Create the missing documenation.
- Add examples.