Skip to content

Commit

Permalink
Merge pull request #263 from northwesternfintech/testing
Browse files Browse the repository at this point in the history
Add full cpp integration test coverage
  • Loading branch information
stevenewald authored Sep 20, 2024
2 parents f545d1e + 0bb5ec7 commit 4eb0ce7
Show file tree
Hide file tree
Showing 30 changed files with 976 additions and 160 deletions.
2 changes: 2 additions & 0 deletions exchange/src/common/types/algorithm/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "local_algorithm.hpp"
#include "remote_algorithm.hpp"

#include <variant>

namespace nutc::common {
using algorithm_variant = std::variant<RemoteAlgorithm, LocalAlgorithm>;

Expand Down
37 changes: 36 additions & 1 deletion exchange/src/common/types/algorithm/local_algorithm.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
#include "local_algorithm.hpp"

#include "base_algorithm.hpp"
#include "common/file_operations/file_operations.hpp"

#include <boost/filesystem.hpp>

#include <cassert>

#include <filesystem>
#include <optional>

namespace nutc::common {
std::string
LocalAlgorithm::compile_cpp_() const
{
assert(get_language() == AlgoLanguage::cpp);
static constexpr std::string_view TEMPLATE_PATH = "test_algos/cpp/template.cpp";
std::string binary_output = (boost::filesystem::temp_directory_path()
/ boost::filesystem::unique_path("%%%%-%%%%-%%%%.tmp"))
.string();
std::string command = fmt::format(
"g++ -std=c++20 -fPIC -shared -o {} -include {} {}", binary_output,
filepath_.string(), TEMPLATE_PATH
);

int result = system(command.c_str());

if (result != 0) {
throw std::runtime_error(
fmt::format("Compilation of {} failed", filepath_.string())
);
}
return binary_output;
}

LocalAlgorithm::LocalAlgorithm(AlgoLanguage language, std::filesystem::path filepath) :
BaseAlgorithm{language}, filepath_{std::move(filepath)}
{
Expand All @@ -24,7 +53,13 @@ LocalAlgorithm::get_path() const
std::string
LocalAlgorithm::get_algo_string() const
{
std::optional<std::string> algorithm = nutc::common::read_file_content(filepath_);
std::optional<std::string> algorithm;
if (get_language() == AlgoLanguage::cpp) {
algorithm = common::read_file_content(compile_cpp_());
}
else {
algorithm = common::read_file_content(filepath_);
}

if (!algorithm) {
throw std::runtime_error(
Expand Down
3 changes: 3 additions & 0 deletions exchange/src/common/types/algorithm/local_algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ class LocalAlgorithm : public BaseAlgorithm {
std::string get_algo_string() const;

std::string get_id() const;

private:
std::string compile_cpp_() const;
};
} // namespace nutc::common
9 changes: 2 additions & 7 deletions exchange/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,10 @@ add_executable(NUTC_tests

src/unit/types/decimal.cpp

src/integration/basic_python.cpp
src/integration/basic_cpp.cpp
src/integration/cancellation.cpp
src/integration/tests/basic.cpp
src/integration/tests/cancellation.cpp
)

if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
target_sources(NUTC_tests PRIVATE src/integration/basic_cpp.cpp)
endif()

target_include_directories(
NUTC_tests ${warning_guard}
PUBLIC
Expand Down
47 changes: 0 additions & 47 deletions exchange/test/src/integration/basic_cpp.cpp

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include <cstdint>

#include <string>

/**
* Place a market order
*
* IMPORTANT:
* You should handle the case where the order fails due to rate limiting
* (maybe wait and try again?)
*
* @param side Side of the order to place ("BUY" or "SELL")
* @param ticker Ticker of the order to place ("ETH", "BTC", or "LTC")
* @param quantity Volume of the order to place
*
* @return true if order succeeded, false if order failed due to rate limiting
*/
bool
place_market_order(std::string const& side, std::string const& ticker, double quantity);

/**
* Place a limit order
*
* IMPORTANT:
* You should handle the case where the order fails due to rate limiting
* (maybe wait and try again?)
*
* @param side Side of the order to place ("BUY" or "SELL")
* @param ticker Ticker of the order to place ("ETH", "BTC", or "LTC")
* @param quantity Volume of the order to place
* @param price Price of the order to place
* @param ioc Immediate or cancel
*
* @return true if order succeeded, false if order failed due to rate limiting
*/
std::int64_t place_limit_order(
std::string const& side, std::string const& ticker, double quantity, double price,
bool ioc = false
);

bool cancel_order(std::string const& ticker, std::int64_t order_id);

class Strategy {
public:
Strategy() { place_market_order("BUY", "ETH", 5); }

/**
* Called whenever two orders match. Could be one of your orders, or two other
* people's orders.
*
* @param ticker Ticker of the orders that were matched ("ETH", "BTC", or
* "LTC)
* @param side Side of the orders that were matched ("BUY" or "SELL")
* @param price Price that trade was executed at
* @quantity quantity Volume traded
*/
void
on_trade_update(std::string ticker, std::string side, double quantity, double price)
{
if (ticker == "ETH" && price <= 101 && price >= 99 && quantity == 5) {
place_limit_order("BUY", "BTC", 1, 100);
}
}

/**
* Called whenever the orderbook changes. This could be because of a trade, or
* because of a new order, or both.
*
* @param ticker Ticker that has an orderbook update ("ETH", "BTC", or "LTC")
* @param side Which orderbook as updated ("BUY" or "SELL")
* @param price Price of orderbook that has an update
* @param quantity Volume placed into orderbook
*/
void
on_orderbook_update(
std::string ticker, std::string side, double quantity, double price
)
{}

/**
* Called whenever one of your orders is filled.
*
* @param ticker Ticker of order that was fulfilled ("ETH", "BTC", or "LTC")
* @param side Side of order that was fulfilled ("BUY" or "SELL")
* @param price Price that order was fulfilled at
* @param quantity Amount of capital after fulfilling order
*/
void
on_account_update(
std::string ticker, std::string side, double price, double quantity,
double capital_remaining
)
{}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <cstdint>

#include <string>

/**
* Place a market order
*
* IMPORTANT:
* You should handle the case where the order fails due to rate limiting
* (maybe wait and try again?)
*
* @param side Side of the order to place ("BUY" or "SELL")
* @param ticker Ticker of the order to place ("ETH", "BTC", or "LTC")
* @param quantity Volume of the order to place
*
* @return true if order succeeded, false if order failed due to rate limiting
*/
bool
place_market_order(std::string const& side, std::string const& ticker, double quantity);

/**
* Place a limit order
*
* IMPORTANT:
* You should handle the case where the order fails due to rate limiting
* (maybe wait and try again?)
*
* @param side Side of the order to place ("BUY" or "SELL")
* @param ticker Ticker of the order to place ("ETH", "BTC", or "LTC")
* @param quantity Volume of the order to place
* @param price Price of the order to place
* @param ioc Immediate or cancel
*
* @return true if order succeeded, false if order failed due to rate limiting
*/
std::int64_t place_limit_order(
std::string const& side, std::string const& ticker, double quantity, double price,
bool ioc = false
);

bool cancel_order(std::string const& ticker, std::int64_t order_id);

class Strategy {
public:
Strategy() = default;

/**
* Called whenever two orders match. Could be one of your orders, or two other
* people's orders.
*
* @param ticker Ticker of the orders that were matched ("ETH", "BTC", or
* "LTC)
* @param side Side of the orders that were matched ("BUY" or "SELL")
* @param price Price that trade was executed at
* @quantity quantity Volume traded
*/
void
on_trade_update(std::string ticker, std::string side, double quantity, double price)
{}

/**
* Called whenever the orderbook changes. This could be because of a trade, or
* because of a new order, or both.
*
* @param ticker Ticker that has an orderbook update ("ETH", "BTC", or "LTC")
* @param side Which orderbook as updated ("BUY" or "SELL")
* @param price Price of orderbook that has an update
* @param quantity Volume placed into orderbook
*/
void
on_orderbook_update(
std::string ticker, std::string side, double quantity, double price
)
{
if (ticker == "ETH" && quantity < 101 && quantity > 99) {
place_limit_order("BUY", "ETH\n", 100, 10);
place_limit_order("BUY", "ETH", 100, 10);
}
}

/**
* Called whenever one of your orders is filled.
*
* @param ticker Ticker of order that was fulfilled ("ETH", "BTC", or "LTC")
* @param side Side of order that was fulfilled ("BUY" or "SELL")
* @param price Price that order was fulfilled at
* @param quantity Amount of capital after fulfilling order
*/
void
on_account_update(
std::string ticker, std::string side, double price, double quantity,
double capital_remaining
)
{}
};
Loading

0 comments on commit 4eb0ce7

Please sign in to comment.