Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make some default trade options configurable in exchangeconfig file #502

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions CONFIG.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/api-objects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ add_unit_test(
coincenter_objects
)

add_unit_test(
tradeoptions_test
src/tradeoptions.cpp
test/tradeoptions_test.cpp
LIBRARIES
coincenter_objects
)

add_unit_test(
withdraw_test
test/withdraw_test.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/api-objects/include/ordersconstraints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class OrdersConstraints {

/// Build OrdersConstraints based on given filtering information
explicit OrdersConstraints(CurrencyCode cur1 = CurrencyCode(), CurrencyCode cur2 = CurrencyCode(),
Duration minAge = Duration(), Duration maxAge = Duration(),
Duration minAge = kUndefinedDuration, Duration maxAge = kUndefinedDuration,
OrderIdSet &&ordersIdSet = OrderIdSet());

TimePoint placedBefore() const { return _placedBefore; }
Expand Down
26 changes: 13 additions & 13 deletions src/api-objects/include/tradeoptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@
#include "tradedefinitions.hpp"

namespace cct {
class ExchangeConfig;
class TradeOptions {
public:
static constexpr Duration kDefaultTradeDuration = std::chrono::seconds(30);
static constexpr Duration kDefaultMinTimeBetweenPriceUpdates = std::chrono::seconds(5);

constexpr TradeOptions() noexcept = default;

constexpr explicit TradeOptions(const PriceOptions &priceOptions) : _priceOptions(priceOptions) {}

constexpr explicit TradeOptions(TradeMode tradeMode) : _mode(tradeMode) {}

TradeOptions(TradeTimeoutAction timeoutAction, TradeMode tradeMode, Duration dur, Duration minTimeBetweenPriceUpdates,
TradeTypePolicy tradeTypePolicy, TradeSyncPolicy tradeSyncPolicy = TradeSyncPolicy::kSynchronous);
constexpr explicit TradeOptions(TradeMode tradeMode) : _tradeMode(tradeMode) {}

/// Constructs a TradeOptions based on a continuously updated price from given string representation of trade
/// strategy
TradeOptions(const PriceOptions &priceOptions, TradeTimeoutAction timeoutAction, TradeMode tradeMode, Duration dur,
Duration minTimeBetweenPriceUpdates = kDefaultMinTimeBetweenPriceUpdates,
Duration minTimeBetweenPriceUpdates = kUndefinedDuration,
TradeTypePolicy tradeTypePolicy = TradeTypePolicy::kDefault,
TradeSyncPolicy tradeSyncPolicy = TradeSyncPolicy::kSynchronous);

/// Constructs a new TradeOptions based on 'rhs' with unspecified options overriden from exchange config values
TradeOptions(const TradeOptions &rhs, const ExchangeConfig &exchangeConfig);

constexpr Duration maxTradeTime() const { return _maxTradeTime; }

constexpr Duration minTimeBetweenPriceUpdates() const { return _minTimeBetweenPriceUpdates; }
Expand All @@ -42,7 +42,7 @@ class TradeOptions {

constexpr int relativePrice() const { return _priceOptions.relativePrice(); }

constexpr TradeMode tradeMode() const { return _mode; }
constexpr TradeMode tradeMode() const { return _tradeMode; }

constexpr TradeSyncPolicy tradeSyncPolicy() const { return _tradeSyncPolicy; }

Expand All @@ -52,13 +52,13 @@ class TradeOptions {
return _priceOptions.isTakerStrategy() && (!isSimulation() || !placeRealOrderInSimulationMode);
}

constexpr bool isSimulation() const { return _mode == TradeMode::kSimulation; }
constexpr bool isSimulation() const { return _tradeMode == TradeMode::kSimulation; }

constexpr bool isFixedPrice() const { return _priceOptions.isFixedPrice(); }

constexpr bool isRelativePrice() const { return _priceOptions.isRelativePrice(); }

constexpr bool placeMarketOrderAtTimeout() const { return _timeoutAction == TradeTimeoutAction::kForceMatch; }
constexpr bool placeMarketOrderAtTimeout() const { return _timeoutAction == TradeTimeoutAction::kMatch; }

constexpr void switchToTakerStrategy() { _priceOptions.switchToTakerStrategy(); }

Expand All @@ -71,11 +71,11 @@ class TradeOptions {
bool operator==(const TradeOptions &) const noexcept = default;

private:
Duration _maxTradeTime = kDefaultTradeDuration;
Duration _minTimeBetweenPriceUpdates = kDefaultMinTimeBetweenPriceUpdates;
Duration _maxTradeTime = kUndefinedDuration;
Duration _minTimeBetweenPriceUpdates = kUndefinedDuration;
PriceOptions _priceOptions;
TradeTimeoutAction _timeoutAction = TradeTimeoutAction::kCancel;
TradeMode _mode = TradeMode::kReal;
TradeTimeoutAction _timeoutAction = TradeTimeoutAction::kDefault;
TradeMode _tradeMode = TradeMode::kReal;
TradeTypePolicy _tradeTypePolicy = TradeTypePolicy::kDefault;
TradeSyncPolicy _tradeSyncPolicy = TradeSyncPolicy::kSynchronous;
};
Expand Down
7 changes: 4 additions & 3 deletions src/api-objects/include/withdrawsordepositsconstraints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ class WithdrawsOrDepositsConstraints {
public:
using IdSet = FlatSet<string, std::less<>>;

explicit WithdrawsOrDepositsConstraints(CurrencyCode currencyCode = CurrencyCode(), Duration minAge = Duration(),
Duration maxAge = Duration(), IdSet &&idSet = IdSet());
explicit WithdrawsOrDepositsConstraints(CurrencyCode currencyCode = CurrencyCode(),
Duration minAge = kUndefinedDuration, Duration maxAge = kUndefinedDuration,
IdSet &&idSet = IdSet());

// Creates a WithdrawsOrDepositsConstraints based on a single transaction id and currency code.
// Useful for retrieval of a specific Deposit / Withdraw.
Expand All @@ -33,7 +34,7 @@ class WithdrawsOrDepositsConstraints {

bool validateCur(CurrencyCode cur) const { return _currencyCode.isNeutral() || cur == _currencyCode; }

bool validateTime(TimePoint t) const { return t >= _timeAfter && t <= _timeBefore; }
bool validateTime(TimePoint tp) const { return tp >= _timeAfter && tp <= _timeBefore; }

bool validateId(std::string_view id) const { return !isIdDefined() || _idSet.contains(id); }

Expand Down
6 changes: 3 additions & 3 deletions src/api-objects/src/ordersconstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ OrdersConstraints::OrdersConstraints(CurrencyCode cur1, CurrencyCode cur2, Durat
if (!_ordersIdSet.empty()) {
_orderConstraintsBitmap.set(OrderConstraintsBitmap::ConstraintType::kId);
}
auto now = Clock::now();
if (minAge != Duration()) {
const auto now = Clock::now();
if (minAge != kUndefinedDuration) {
_placedBefore = now - minAge;
_orderConstraintsBitmap.set(OrderConstraintsBitmap::ConstraintType::kPlacedBefore);
}
if (maxAge != Duration()) {
if (maxAge != kUndefinedDuration) {
_placedAfter = now - maxAge;
_orderConstraintsBitmap.set(OrderConstraintsBitmap::ConstraintType::kPlacedAfter);
}
Expand Down
34 changes: 21 additions & 13 deletions src/api-objects/src/tradeoptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,39 @@

#include "cct_string.hpp"
#include "durationstring.hpp"
#include "exchangeconfig.hpp"
#include "priceoptions.hpp"
#include "timedef.hpp"
#include "tradedefinitions.hpp"
#include "unreachable.hpp"

namespace cct {

TradeOptions::TradeOptions(TradeTimeoutAction timeoutAction, TradeMode tradeMode, Duration dur,
Duration minTimeBetweenPriceUpdates, TradeTypePolicy tradeTypePolicy,
TradeSyncPolicy tradeSyncPolicy)
: _maxTradeTime(dur),
_minTimeBetweenPriceUpdates(minTimeBetweenPriceUpdates),
_timeoutAction(timeoutAction),
_mode(tradeMode),
_tradeTypePolicy(tradeTypePolicy),
_tradeSyncPolicy(tradeSyncPolicy) {}

TradeOptions::TradeOptions(const PriceOptions &priceOptions, TradeTimeoutAction timeoutAction, TradeMode tradeMode,
Duration dur, Duration minTimeBetweenPriceUpdates, TradeTypePolicy tradeTypePolicy,
TradeSyncPolicy tradeSyncPolicy)
: _maxTradeTime(dur),
_minTimeBetweenPriceUpdates(minTimeBetweenPriceUpdates),
_priceOptions(priceOptions),
_timeoutAction(timeoutAction),
_mode(tradeMode),
_tradeMode(tradeMode),
_tradeTypePolicy(tradeTypePolicy),
_tradeSyncPolicy(tradeSyncPolicy) {}

TradeOptions::TradeOptions(const TradeOptions &rhs, const ExchangeConfig &exchangeConfig)
: _maxTradeTime(rhs._maxTradeTime == kUndefinedDuration ? exchangeConfig.tradeConfig().timeout()
: rhs._maxTradeTime),
_minTimeBetweenPriceUpdates(rhs._minTimeBetweenPriceUpdates == kUndefinedDuration
? exchangeConfig.tradeConfig().minPriceUpdateDuration()
: rhs._minTimeBetweenPriceUpdates),
_priceOptions(rhs._priceOptions.isDefault() ? PriceOptions(exchangeConfig.tradeConfig()) : rhs._priceOptions),
_timeoutAction(rhs._timeoutAction == TradeTimeoutAction::kDefault
? exchangeConfig.tradeConfig().tradeTimeoutAction()
: rhs._timeoutAction),
_tradeMode(rhs._tradeMode),
_tradeTypePolicy(rhs._tradeTypePolicy),
_tradeSyncPolicy(rhs._tradeSyncPolicy) {}

bool TradeOptions::isMultiTradeAllowed(bool multiTradeAllowedByDefault) const {
switch (_tradeTypePolicy) {
case TradeTypePolicy::kDefault:
Expand All @@ -47,10 +52,13 @@ bool TradeOptions::isMultiTradeAllowed(bool multiTradeAllowedByDefault) const {

std::string_view TradeOptions::timeoutActionStr() const {
switch (_timeoutAction) {
case TradeTimeoutAction::kDefault:
// Default will behave the same as cancel - this field is not publicly exposed
[[fallthrough]];
case TradeTimeoutAction::kCancel:
return "cancel";
case TradeTimeoutAction::kForceMatch:
return "force-match";
case TradeTimeoutAction::kMatch:
return "match";
default:
unreachable();
}
Expand Down
6 changes: 3 additions & 3 deletions src/api-objects/src/withdrawsordepositsconstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ WithdrawsOrDepositsConstraints::WithdrawsOrDepositsConstraints(CurrencyCode curr
if (!_idSet.empty()) {
_currencyIdTimeConstraintsBmp.set(CurrencyIdTimeConstraintsBmp::ConstraintType::kId);
}
auto now = Clock::now();
if (minAge != Duration()) {
const auto now = Clock::now();
if (minAge != kUndefinedDuration) {
_timeBefore = now - minAge;
_currencyIdTimeConstraintsBmp.set(CurrencyIdTimeConstraintsBmp::ConstraintType::kReceivedBefore);
}
if (maxAge != Duration()) {
if (maxAge != kUndefinedDuration) {
_timeAfter = now - maxAge;
_currencyIdTimeConstraintsBmp.set(CurrencyIdTimeConstraintsBmp::ConstraintType::kReceivedAfter);
}
Expand Down
12 changes: 12 additions & 0 deletions src/api-objects/test/tradeoptions_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "tradeoptions.hpp"

#include <gtest/gtest.h>

namespace cct {
TEST(TradeOptionsTest, DefaultTradeTimeoutAction) {
TradeOptions tradeOptions;

EXPECT_FALSE(tradeOptions.placeMarketOrderAtTimeout());
EXPECT_EQ(tradeOptions.timeoutActionStr(), "cancel");
}
} // namespace cct
4 changes: 2 additions & 2 deletions src/api/common/include/exchangeprivateapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "currencyexchangeflatset.hpp"
#include "depositsconstraints.hpp"
#include "exchangebase.hpp"
#include "exchangeinfo.hpp"
#include "exchangeconfig.hpp"
#include "exchangeprivateapitypes.hpp"
#include "exchangepublicapi.hpp"
#include "exchangepublicapitypes.hpp"
Expand Down Expand Up @@ -118,7 +118,7 @@ class ExchangePrivate : public ExchangeBase {
/// Builds an ExchangeName wrapping the exchange and the key name
ExchangeName exchangeName() const { return {_exchangePublic.name(), _apiKey.name()}; }

const ExchangeInfo &exchangeInfo() const { return _exchangePublic.exchangeInfo(); }
const ExchangeConfig &exchangeConfig() const { return _exchangePublic.exchangeConfig(); }

protected:
ExchangePrivate(const CoincenterInfo &coincenterInfo, ExchangePublic &exchangePublic, const APIKey &apiKey);
Expand Down
6 changes: 3 additions & 3 deletions src/api/common/include/exchangepublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
namespace cct {

class CoincenterInfo;
class ExchangeInfo;
class ExchangeConfig;
class FiatConverter;

namespace api {
Expand Down Expand Up @@ -161,7 +161,7 @@ class ExchangePublic : public ExchangeBase {

const CoincenterInfo &coincenterInfo() const { return _coincenterInfo; }

const ExchangeInfo &exchangeInfo() const { return _exchangeInfo; }
const ExchangeConfig &exchangeConfig() const { return _exchangeConfig; }

CommonAPI &commonAPI() { return _commonApi; }

Expand All @@ -180,7 +180,7 @@ class ExchangePublic : public ExchangeBase {
FiatConverter &_fiatConverter;
CommonAPI &_commonApi;
const CoincenterInfo &_coincenterInfo;
const ExchangeInfo &_exchangeInfo;
const ExchangeConfig &_exchangeConfig;
std::mutex _tradableMarketsMutex;
std::mutex _allOrderBooksMutex;
};
Expand Down
31 changes: 18 additions & 13 deletions src/api/common/src/exchangeprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "depositsconstraints.hpp"
#include "durationstring.hpp"
#include "exchangebase.hpp"
#include "exchangeinfo.hpp"
#include "exchangeconfig.hpp"
#include "exchangename.hpp"
#include "exchangeprivateapitypes.hpp"
#include "exchangepublicapi.hpp"
Expand All @@ -40,6 +40,7 @@
#include "tradedamounts.hpp"
#include "tradedefinitions.hpp"
#include "tradeinfo.hpp"
#include "tradeoptions.hpp"
#include "tradeside.hpp"
#include "unreachable.hpp"
#include "withdraw.hpp"
Expand Down Expand Up @@ -85,14 +86,17 @@ void ExchangePrivate::addBalance(BalancePortfolio &balancePortfolio, MonetaryAmo

TradedAmounts ExchangePrivate::trade(MonetaryAmount from, CurrencyCode toCurrency, const TradeOptions &options,
const MarketsPath &conversionPath) {
const bool realOrderPlacedInSimulationMode = !isSimulatedOrderSupported() && exchangeInfo().placeSimulateRealOrder();
// Use exchange config settings for un-overriden trade options
const auto &exchangeConfig = this->exchangeConfig();
const TradeOptions actualOptions(options, exchangeConfig);
const bool realOrderPlacedInSimulationMode = !isSimulatedOrderSupported() && exchangeConfig.placeSimulateRealOrder();
const int nbTrades = static_cast<int>(conversionPath.size());
const bool isMultiTradeAllowed = options.isMultiTradeAllowed(exchangeInfo().multiTradeAllowedByDefault());
const bool isMultiTradeAllowed = actualOptions.isMultiTradeAllowed(exchangeConfig.multiTradeAllowedByDefault());

ExchangeName exchangeName = this->exchangeName();
log::info("{}rade {} -> {} on {} requested", isMultiTradeAllowed && nbTrades > 1 ? "Multi t" : "T", from, toCurrency,
exchangeName);
log::debug(options.str(realOrderPlacedInSimulationMode));
log::debug(actualOptions.str(realOrderPlacedInSimulationMode));

TradedAmounts tradedAmounts(from.currencyCode(), toCurrency);
if (conversionPath.empty()) {
Expand All @@ -108,7 +112,7 @@ TradedAmounts ExchangePrivate::trade(MonetaryAmount from, CurrencyCode toCurrenc
for (int tradePos = 0; tradePos < nbTrades; ++tradePos) {
Market mk = conversionPath[tradePos];
log::info("Step {}/{} - trade {} into {}", tradePos + 1, nbTrades, avAmount, mk.opposite(avAmount.currencyCode()));
TradedAmounts stepTradedAmounts = marketTrade(avAmount, options, mk);
TradedAmounts stepTradedAmounts = marketTrade(avAmount, actualOptions, mk);
avAmount = stepTradedAmounts.to;
if (avAmount == 0) {
break;
Expand All @@ -135,7 +139,7 @@ TradedAmounts ExchangePrivate::marketTrade(MonetaryAmount from, const TradeOptio
TradeContext tradeContext(mk, side, userRef);
TradeInfo tradeInfo(tradeContext, tradeOptions);
TradeOptions &options = tradeInfo.options;
const bool placeSimulatedRealOrder = exchangeInfo().placeSimulateRealOrder();
const bool placeSimulatedRealOrder = exchangeConfig().placeSimulateRealOrder();

enum class NextAction : int8_t { kPlaceInitialOrder, kPlaceLimitOrder, kPlaceMarketOrder, kWait };

Expand Down Expand Up @@ -447,8 +451,9 @@ TradedAmounts ExchangePrivate::buySomeAmountToMakeFutureSellPossible(
}

TradedAmountsVectorWithFinalAmount ExchangePrivate::queryDustSweeper(CurrencyCode currencyCode) {
const MonetaryAmountByCurrencySet &dustThresholds = exchangeInfo().dustAmountsThreshold();
const int dustSweeperMaxNbTrades = exchangeInfo().dustSweeperMaxNbTrades();
const auto &exchangeConfig = this->exchangeConfig();
const MonetaryAmountByCurrencySet &dustThresholds = exchangeConfig.dustAmountsThreshold();
const int dustSweeperMaxNbTrades = exchangeConfig.dustSweeperMaxNbTrades();
const auto dustThresholdLb = dustThresholds.find(MonetaryAmount(0, currencyCode));
const auto eName = exchangeName();

Expand All @@ -460,7 +465,7 @@ TradedAmountsVectorWithFinalAmount ExchangePrivate::queryDustSweeper(CurrencyCod
const MonetaryAmount dustThreshold = *dustThresholdLb;

PriceOptions priceOptions(PriceStrategy::kTaker);
TradeOptions tradeOptions(priceOptions);
TradeOptions tradeOptions(TradeOptions{priceOptions}, exchangeConfig);
MarketSet markets = _exchangePublic.queryTradableMarkets();
MarketPriceMap marketPriceMap;
bool checkAmountBalanceAgainstDustThreshold = true;
Expand Down Expand Up @@ -528,7 +533,7 @@ PlaceOrderInfo ExchangePrivate::placeOrderProcess(MonetaryAmount &from, Monetary
const MonetaryAmount volume(isSell ? from : MonetaryAmount(from / price, mk.base()));

if (tradeInfo.options.isSimulation() && !isSimulatedOrderSupported()) {
if (exchangeInfo().placeSimulateRealOrder()) {
if (exchangeConfig().placeSimulateRealOrder()) {
log::debug("Place simulate real order - price {} will be overriden", price);
MarketOrderBook marketOrderbook = _exchangePublic.queryOrderBook(mk);
price = isSell ? marketOrderbook.getHighestTheoreticalPrice() : marketOrderbook.getLowestTheoreticalPrice();
Expand All @@ -552,13 +557,13 @@ PlaceOrderInfo ExchangePrivate::placeOrderProcess(MonetaryAmount &from, Monetary

PlaceOrderInfo ExchangePrivate::computeSimulatedMatchedPlacedOrderInfo(MonetaryAmount volume, MonetaryAmount price,
const TradeInfo &tradeInfo) const {
const bool placeSimulatedRealOrder = exchangeInfo().placeSimulateRealOrder();
const bool placeSimulatedRealOrder = exchangeConfig().placeSimulateRealOrder();
const bool isTakerStrategy = tradeInfo.options.isTakerStrategy(placeSimulatedRealOrder);
const bool isSell = tradeInfo.tradeContext.side == TradeSide::kSell;

MonetaryAmount toAmount = isSell ? volume.convertTo(price) : volume;
ExchangeInfo::FeeType feeType = isTakerStrategy ? ExchangeInfo::FeeType::kTaker : ExchangeInfo::FeeType::kMaker;
toAmount = _coincenterInfo.exchangeInfo(_exchangePublic.name()).applyFee(toAmount, feeType);
ExchangeConfig::FeeType feeType = isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
toAmount = _coincenterInfo.exchangeConfig(_exchangePublic.name()).applyFee(toAmount, feeType);
PlaceOrderInfo placeOrderInfo(OrderInfo(TradedAmounts(isSell ? volume : volume.toNeutral() * price, toAmount)),
OrderId("SimulatedOrderId"));
placeOrderInfo.setClosed();
Expand Down
Loading
Loading