1
+ #include " auto-trade-processor.hpp"
2
+
3
+ #include < thread>
4
+
5
+ #include " auto-trade-options.hpp"
6
+ #include " cct_exception.hpp"
7
+ #include " timestring.hpp"
8
+
9
+ namespace cct {
10
+
11
+ AutoTradeProcessor::AutoTradeProcessor (const AutoTradeOptions &autoTradeOptions)
12
+ : _exchangeStatusVector(autoTradeOptions.publicExchanges().size()) {
13
+ int publicExchangePos = 0 ;
14
+ for (const auto &[exchangeNameEnum, publicExchangeAutoTradeOptions] : autoTradeOptions) {
15
+ ExchangeStatus &selectedExchangesStatus = _exchangeStatusVector[publicExchangePos];
16
+ selectedExchangesStatus.pPublicExchangeAutoTradeOptions = &publicExchangeAutoTradeOptions;
17
+ for (const auto &[market, marketAutoTradeOptions] : publicExchangeAutoTradeOptions) {
18
+ MarketStatus &marketStatus = selectedExchangesStatus.marketStatusVector .emplace_back ();
19
+
20
+ marketStatus.market = market;
21
+ marketStatus.pMarketAutoTradeOptions = &marketAutoTradeOptions;
22
+
23
+ for (std::string_view account : marketAutoTradeOptions.accounts ) {
24
+ marketStatus.privateExchangeNames .emplace_back (exchangeNameEnum, account);
25
+ }
26
+ }
27
+ ++publicExchangePos;
28
+ }
29
+ }
30
+
31
+ namespace {
32
+ const auto &GetAutoTradeMarketConfig (Market market, const auto &publicExchangeAutoTradeOptions) {
33
+ const auto it = publicExchangeAutoTradeOptions.find (market);
34
+ if (it == publicExchangeAutoTradeOptions.end ()) {
35
+ throw exception (" Should not happen - market not found in account auto trade options" );
36
+ }
37
+ return it->second ;
38
+ }
39
+
40
+ bool IsQueryTooEarly (TimePoint nowTs, const auto &marketStatus, const auto &publicExchangeAutoTradeOptions) {
41
+ const auto &marketAutoTradeOptions = GetAutoTradeMarketConfig (marketStatus.market , publicExchangeAutoTradeOptions);
42
+ return marketStatus.lastQueryTime + marketAutoTradeOptions.repeatTime .duration > nowTs;
43
+ }
44
+ } // namespace
45
+
46
+ AutoTradeProcessor::SelectedMarketVector AutoTradeProcessor::computeSelectedMarkets () {
47
+ SelectedMarketVector selectedMarketVector;
48
+
49
+ auto ts = Clock::now ();
50
+
51
+ TimePoint earliestQueryTime = TimePoint::max ();
52
+
53
+ for (ExchangeStatus &exchangeStatus : _exchangeStatusVector) {
54
+ const auto &publicExchangeAutoTradeOptions = *exchangeStatus.pPublicExchangeAutoTradeOptions ;
55
+
56
+ auto &marketStatusVector = exchangeStatus.marketStatusVector ;
57
+
58
+ if (marketStatusVector.empty ()) {
59
+ continue ;
60
+ }
61
+
62
+ // Sort markets by ascending last query time, discarding those (placed at the end of the vector) which cannot be
63
+ // queried right now
64
+ std::ranges::sort (marketStatusVector,
65
+ [ts, &publicExchangeAutoTradeOptions](const MarketStatus &lhs, const MarketStatus &rhs) {
66
+ const bool lhsIsTooEarly = IsQueryTooEarly (ts, lhs, publicExchangeAutoTradeOptions);
67
+ const bool rhsIsTooEarly = IsQueryTooEarly (ts, rhs, publicExchangeAutoTradeOptions);
68
+
69
+ if (lhsIsTooEarly != rhsIsTooEarly) {
70
+ return !lhsIsTooEarly;
71
+ }
72
+
73
+ return lhs.lastQueryTime < rhs.lastQueryTime ;
74
+ });
75
+
76
+ MarketStatus &selectedMarketStatus = marketStatusVector.front ();
77
+ if (IsQueryTooEarly (ts, selectedMarketStatus, publicExchangeAutoTradeOptions)) {
78
+ const auto repeatTime =
79
+ GetAutoTradeMarketConfig (selectedMarketStatus.market , publicExchangeAutoTradeOptions).repeatTime .duration ;
80
+ earliestQueryTime = std::min (earliestQueryTime, selectedMarketStatus.lastQueryTime + repeatTime);
81
+ continue ;
82
+ }
83
+
84
+ selectedMarketStatus.lastQueryTime = ts;
85
+ selectedMarketVector.emplace_back (selectedMarketStatus.privateExchangeNames , selectedMarketStatus.market );
86
+ }
87
+
88
+ if (selectedMarketVector.empty () && earliestQueryTime != TimePoint::max ()) {
89
+ log ::debug (" Sleeping until {}" , TimeToString (earliestQueryTime));
90
+ std::this_thread::sleep_until (earliestQueryTime + std::chrono::milliseconds (1 ));
91
+ selectedMarketVector = computeSelectedMarkets ();
92
+ if (selectedMarketVector.empty ()) {
93
+ throw exception (" Waiting sufficient time should return at least one market for the next turn" );
94
+ }
95
+ }
96
+
97
+ return selectedMarketVector;
98
+ }
99
+
100
+ } // namespace cct
0 commit comments