Skip to content

Commit

Permalink
Live auto trade mode
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed Nov 19, 2024
1 parent 1d25e51 commit 913ad9d
Show file tree
Hide file tree
Showing 20 changed files with 620 additions and 9 deletions.
63 changes: 63 additions & 0 deletions data/static/auto-trade-example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"kraken": {
"BTC-EUR": {
"accounts": [
"user1",
"user2"
],
"algorithmName": "example-trader",
"repeatTime": "5s",
"baseStartAmount": "0.5BTC",
"quoteStartAmount": "50%EUR",
"stopCriteria": [
{
"type": "duration",
"value": "4h"
},
{
"type": "protectLoss",
"value": "-30%"
},
{
"type": "secureProfit",
"value": "80%"
}
]
},
"ETH-EUR": {
"accounts": [
"user1"
],
"algorithmName": "example-trader",
"repeatTime": "3s",
"baseStartAmount": "45ETH",
"quoteStartAmount": "50%EUR",
"stopCriteria": [
{
"type": "duration",
"value": "4h"
},
{
"type": "protectLoss",
"value": "-30%"
},
{
"type": "secureProfit",
"value": "80%"
}
]
}
},
"binance": {
"XRP-USDT": {
"accounts": [
"user1"
],
"algorithmName": "example-trader",
"repeatTime": "1s",
"baseStartAmount": "50000.56XRP",
"quoteStartAmount": "100%USDT",
"stopCriteria": []
}
}
}
4 changes: 2 additions & 2 deletions src/basic-objects/include/coincentercommandtype.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace cct {
Balance, DepositInfo, OrdersClosed, OrdersOpened, OrdersCancel, RecentDeposits, RecentWithdraws, Trade, Buy, \
Sell, Withdraw, DustSweeper, \
\
MarketData, Replay, ReplayMarkets
MarketData, Replay, ReplayMarkets, AutoTrade

enum class CoincenterCommandType : int8_t { CCT_COINCENTER_COMMAND_TYPES };

Expand All @@ -29,4 +29,4 @@ struct glz::meta<::cct::CoincenterCommandType> {
static constexpr auto value = enumerate(CCT_COINCENTER_COMMAND_TYPES);
};

#undef CCT_COINCENTER_COMMAND_TYPES
#undef CCT_COINCENTER_COMMAND_TYPES
2 changes: 1 addition & 1 deletion src/basic-objects/include/market.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ struct from<JSON, ::cct::Market> {
static void op(auto &&value, is_context auto &&, It &&it, End &&end) noexcept {
// used as a value. As a key, the first quote will not be present.
auto endIt = std::find(*it == '"' ? ++it : it, end, '"');
value = std::string_view(it, endIt);
value = ::cct::Market(std::string_view(it, endIt));
it = ++endIt;
}
};
Expand Down
43 changes: 43 additions & 0 deletions src/basic-objects/test/market_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <gtest/gtest.h>

#include "cct_exception.hpp"
#include "cct_json-serialization.hpp"
#include "currencycode.hpp"

namespace cct {
Expand Down Expand Up @@ -65,4 +66,46 @@ TEST(MarketTest, StrLen) {
market = Market("1INCH", "EUR", Market::Type::kFiatConversionMarket);
EXPECT_EQ(market.strLen(), 10);
}

struct Foo {
bool operator==(const Foo &) const noexcept = default;

Market market;
};

TEST(MarketTest, JsonSerializationValue) {
Foo foo{Market{"DOGE", "BTC"}};

string buffer;
auto res = json::write<json::opts{.raw_string = true}>(foo, buffer); // NOLINT(readability-implicit-bool-conversion)

EXPECT_FALSE(res);

EXPECT_EQ(buffer, R"({"market":"DOGE-BTC"})");
}

using MarketMap = std::map<Market, bool>;

TEST(MarketTest, JsonSerializationKey) {
MarketMap map{{Market{"DOGE", "BTC"}, true}, {Market{"BTC", "ETH"}, false}};

string buffer;
auto res = json::write<json::opts{.raw_string = true}>(map, buffer); // NOLINT(readability-implicit-bool-conversion)

EXPECT_FALSE(res);

EXPECT_EQ(buffer, R"({"BTC-ETH":false,"DOGE-BTC":true})");
}

TEST(MarketTest, JsonDeserialization) {
Foo foo;

// NOLINTNEXTLINE(readability-implicit-bool-conversion)
auto ec = json::read<json::opts{.raw_string = true}>(foo, R"({"market":"DOGE-ETH"})");

ASSERT_FALSE(ec);

EXPECT_EQ(foo, Foo{Market("DOGE", "ETH")});
}

} // namespace cct
58 changes: 58 additions & 0 deletions src/engine/include/auto-trade-options.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once

#include <map>

#include "auto-trade-config.hpp"
#include "cct_const.hpp"
#include "cct_fixedcapacityvector.hpp"
#include "cct_smallvector.hpp"
#include "cct_vector.hpp"
#include "exchange-names.hpp"
#include "exchangename.hpp"

namespace cct {

class AutoTradeOptions {
public:
using AccountAutoTradeOptionsPtrVector =
SmallVector<const schema::AutoTradeExchangeConfig *, kTypicalNbPrivateAccounts>;

struct MarketExchanges {
Market market;
ExchangeNames privateExchangeNames;
const schema::AutoTradeMarketConfig *pMarketAutoTradeOptions{};
};

using MarketStatusVector = vector<MarketExchanges>;

struct MarketExchangeOptions {
MarketStatusVector marketStatusVector;
};

struct PublicExchangeMarketOptions {
ExchangeName publicExchangeName;
MarketExchangeOptions marketExchangeOptions;
};

using PublicExchangeMarketOptionsVector = FixedCapacityVector<schema::AutoTradeExchangeConfig, kNbSupportedExchanges>;

AutoTradeOptions() noexcept = default;

explicit AutoTradeOptions(schema::AutoTradeConfig &&autoTradeConfig);

auto begin() const { return _autoTradeConfig.begin(); }
auto end() const { return _autoTradeConfig.end(); }

ExchangeNames exchangeNames() const;

ExchangeNameEnumVector publicExchanges() const;

AccountAutoTradeOptionsPtrVector accountAutoTradeOptionsPtr(std::string_view publicExchangeName) const;

const schema::AutoTradeExchangeConfig &operator[](ExchangeNameEnum exchangeNameEnum) const;

private:
schema::AutoTradeConfig _autoTradeConfig;
};

} // namespace cct
51 changes: 51 additions & 0 deletions src/engine/include/auto-trade-processor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <compare>
#include <functional>

#include "auto-trade-config.hpp"
#include "cct_smallvector.hpp"
#include "cct_vector.hpp"
#include "exchange-names.hpp"
#include "exchange.hpp"
#include "market.hpp"
#include "timedef.hpp"

namespace cct {
class AutoTradeOptions;

class AutoTradeProcessor {
public:
explicit AutoTradeProcessor(const AutoTradeOptions& autoTradeOptions);

struct SelectedMarket {
ExchangeNames privateExchangeNames;
Market market;
};

using SelectedMarketVector = SmallVector<SelectedMarket, kTypicalNbPrivateAccounts>;

SelectedMarketVector computeSelectedMarkets();

private:
struct MarketStatus {
ExchangeNames privateExchangeNames;
Market market;
TimePoint lastQueryTime;
const schema::AutoTradeMarketConfig* pMarketAutoTradeOptions{};
};

using MarketStatusVector = vector<MarketStatus>;

struct ExchangeStatus {
MarketStatusVector marketStatusVector;
const schema::AutoTradeExchangeConfig* pPublicExchangeAutoTradeOptions{};
};

using ExchangeStatusVector = SmallVector<ExchangeStatus, kTypicalNbPrivateAccounts>;

ExchangeStatusVector _exchangeStatusVector;
TimePoint _startTs = Clock::now();
TimePoint _ts{_startTs};
};
} // namespace cct
4 changes: 4 additions & 0 deletions src/engine/include/coincenter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <span>

#include "apikeysprovider.hpp"
#include "auto-trade-options.hpp"
#include "cct_const.hpp"
#include "cct_fixedcapacityvector.hpp"
#include "coincenterinfo.hpp"
Expand Down Expand Up @@ -149,6 +150,9 @@ class Coincenter {
ReplayResults replay(const AbstractMarketTraderFactory &marketTraderFactory, const ReplayOptions &replayOptions,
Market market, ExchangeNameSpan exchangeNames);

/// Run auto trade.
void autoTrade(const AutoTradeOptions &autoTradeOptions);

/// Dumps the content of all file caches in data directory to save cURL queries.
void updateFileCaches() const;

Expand Down
7 changes: 6 additions & 1 deletion src/engine/include/coincentercommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdint>
#include <optional>
#include <string_view>
#include <type_traits>
#include <variant>

Expand Down Expand Up @@ -47,6 +48,8 @@ class CoincenterCommand {

CoincenterCommand& setReplayOptions(ReplayOptions replayOptions);

CoincenterCommand& setJsonConfigFile(std::string_view jsonConfigFile);

CoincenterCommand& setPercentageAmount(bool value = true);
CoincenterCommand& withBalanceInUse(bool value = true);

Expand Down Expand Up @@ -79,6 +82,8 @@ class CoincenterCommand {

const ReplayOptions& replayOptions() const { return std::get<ReplayOptions>(_specialOptions); }

std::string_view getJsonConfigFile() const { return std::get<std::string_view>(_specialOptions); }

bool operator==(const CoincenterCommand&) const noexcept = default;

using trivially_relocatable =
Expand All @@ -89,7 +94,7 @@ class CoincenterCommand {

private:
using SpecialOptions = std::variant<std::monostate, OrdersConstraints, WithdrawsOrDepositsConstraints, TradeOptions,
WithdrawOptions, ReplayOptions>;
WithdrawOptions, ReplayOptions, std::string_view>;

ExchangeNames _exchangeNames;
SpecialOptions _specialOptions;
Expand Down
2 changes: 2 additions & 0 deletions src/engine/include/coincenteroptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class CoincenterCmdLineOptions {

std::string_view marketData;

std::string_view autoTrade;

std::optional<std::string_view> replay;
std::string_view algorithmNames;
std::string_view market;
Expand Down
16 changes: 16 additions & 0 deletions src/engine/include/coincenteroptionsdef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,22 @@ struct CoincenterAllowedOptions : private CoincenterCmdLineOptionsDefinitions {
"\nNominal replay will not validate input data to optimize performance, use this option to validate data once "
"and for all."},
&OptValueType::validateOnly},
{{{"Automation", 8004},
"auto-trade",
"<path/to/json.conf>",
"Automatic live trading mode. Once you have validated on historical market-data the performance of an "
"algorithm, it's time to try it for real!\n"
"This command has some particularities:\n"
"- next commands will never be executed\n"
"- repeat is ignored (the auto trade will continue until one of terminating signals defined in the "
"configuration file is reached)\n"
"Configuration will be loaded from given json file, with following options (check README to get full "
"configuration schema):\n"
"- 'algorithm' : algorithm name to use\n"
"- 'market' : the market to trade onto\n"
"- 'startAmount' : the starting amount in base currency (can be a percentage of available amount)\n"
"- 'exchange' : exchange with account key (not needed if not ambiguous)"},
&OptValueType::autoTrade},
{{{"Monitoring", 9000},
"--monitoring",
"",
Expand Down
2 changes: 2 additions & 0 deletions src/engine/include/exchangesorchestrator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <optional>
#include <span>

#include "auto-trade-options.hpp"
#include "auto-trade-processor.hpp"
#include "exchange-names.hpp"
#include "exchangename.hpp"
#include "exchangeretriever.hpp"
Expand Down
Loading

0 comments on commit 913ad9d

Please sign in to comment.