Advertisement
den4ik2003

Untitled

Jan 25th, 2024
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.46 KB | None | 0 0
  1. #include <algorithm>
  2. #include <atomic>
  3. #include <iostream>
  4. #include <cstdlib>
  5. #include <mutex>
  6. #include <random>
  7. #include <optional>
  8. #include <stdexcept>
  9. #include <exception>
  10.  
  11. #include <python_connector.hpp>
  12. #include <tools.hpp>
  13.  
  14. // Constants
  15. const std::string SELL = "sell";
  16. const std::string BUY = "buy";
  17. const std::string LIMIT = "limit";
  18. const std::string LIMIT_MAKER = "limit_maker";
  19. const std::string MARKET = "market";
  20.  
  21. // thought: enum class OrderBookForm { Pyramid, Other };
  22.  
  23. class MarketMakingManager {
  24. public:
  25. MarketMakingManager(int argc, char* argv[]) {
  26. args = tt::parse_args(argc, argv);
  27. market_ = std::make_shared<mm::python_connector>(args["keys"].c_str(), named_args["market"]);
  28. symbol_ = mm::ticker(args["symbol"], *market_);
  29.  
  30. using conv_fn = std::function<void(const std::string&)>;
  31.  
  32. std::unordered_map<std::string, conv_fn> cnv = {
  33. {"n_lvl", [&n_lvl_](const auto& v) { n_lvl_ = std::stoi(v); }},
  34. {"n_base", [&n_base_](const auto& v) { n_base_ = std::stoi(v); }},
  35. {"base_size_to_remain", [&base_size_to_remain_](const auto& v) { base_size_to_remain_ = std::stod(v); }},
  36. {"first_order_size_", [&first_order_size_](const auto& v) { first_order_size_ = std::stod(v); }},
  37. {"balance", [&balance_](const auto& v) { balance_ = std::stod(v); }},
  38. {"spread_size", [&spread_size_](const auto& v) { spread_size_ = std::stod(v); }},
  39. {"cooldown", [&cooldown_](const auto& v) { cooldown_ = std::stod(v); }},
  40. {"price_step", [&price_step_](const auto& v) { price_step_ = std::stoi(v); }},
  41. {"min_order_size", [&min_order_size_](const auto& v) { min_order_size_ = std::stod(v); }},
  42. };
  43.  
  44. for (const auto& [k, c] : cnv) {
  45. try {
  46. if (args.count(k)) c(args[k]);
  47. } catch (const std::exception& e) {
  48. std::cerr << "Error for key " << k << ": " << e.what() << '\n';
  49. std::exit(EXIT_FAILURE);
  50. }
  51. }
  52. }
  53.  
  54. void CalculateOrders(
  55. std::vector<mm::float_param_t>& ask_prices
  56. std::vector<mm::float_param_t>& ask_amount
  57. std::vector<mm::float_param_t>& bid_prices
  58. std::vector<mm::float_param_t>& bid_amount)
  59. {
  60. // thought: вообще, здесь мы хотим, чтобы был лок в коннекторе на операции, чтобы баланс не менялся
  61. double base_balance = market_->get_acc_balance(symbol_.base) * balance_;
  62. double quote_balance = market_->get_acc_balance(symbol_.base) * balance_;
  63.  
  64. auto mid_price = mm::float_x((book_.a + book_.b) / 2, symbol_.price_prec);
  65. auto ask_price = mm::float_x(mid_price(1 + spread_size_ / 2), symbol_.price_prec);
  66. auto bid_price = mm::float_x(mid_price(1 - spread_size_ / 2), symbol_.price_prec);
  67.  
  68.  
  69. if (first_order_size_ * base_balance < min_order_size_) { // thought: тут можно либо упасть, либо выставлять объёмы не по параметрам указанным + лог
  70. std::cerr << "Bad input: first offer < minimal order size";
  71. exit(EXIT_FAILURE);
  72. }
  73.  
  74. if (first_order_size_ * n_base_ > 1) { // thought: пока что не очень хорошая параметризация, надо к процентной перейти
  75. std::cerr << "Bad input: balance / n <= first offer";
  76. exit(EXIT_FAILURE);
  77. }
  78.  
  79. auto delta_volume = 2 * base_size_to_remain_ * base_balance * (1 - first_order_size_ * n_base_) / (n_base_ * (n_base_ - 1));
  80. // пока только base часть, потому что формула итак неоптимальная, надо подправить
  81. for (int i = 0; i < n_base_; ++i) {
  82. volume_i = first_order_size_ * base_balance * base_size_to_remain_ + delta_volume * (i - 1);
  83. ask_prices.push_back(ask_price + price_step_ * symbol_.price_step * (n_base_ - 1)); // thought: тут вроде доп каст нужен, чтобы умножилось
  84. ask_amount.push_back(volume_i / ask_prices[i]);
  85. bid_prices.push_back(bid_price - price_step_ * symbol_.price_step * (n_base_ - 1));
  86. bid_amount.push_back(volume_i / bid_prices[i]);
  87. }
  88. }
  89.  
  90. void BalancesPhaseCb(bool result) {
  91. if (!result) {
  92. // tought: немного странно такую пустую ситуацию ифать, мб можно красивее сделать
  93. // Внутри коннектора мы залогировали эту ситуацию
  94. return;
  95. }
  96.  
  97. // thought: Нужен ли калибровочный ордер?
  98.  
  99. std::vector<mm::float_param_t> a, b, A, B;
  100.  
  101. CalculateOrders(a, A, b, B);
  102.  
  103. // TODO: добавить ретраи
  104. market_->new_batch_order(symbol, SELL, LIMIT_MAKER, A, a, {}); // thought: склеить бы вместе количествои цену тут
  105. market_->new_batch_order(symbol, BUY, LIMIT_MAKER, B, b, {}); // + по-хорошему убелиться бы, что выложили
  106. }
  107.  
  108. void CancelPhaseCb(bool result) {
  109. if (!result) {
  110. return;
  111. }
  112. market_->update_balances(BalancesPhaseCb);
  113. }
  114.  
  115. void ManageOrdersCb(std::vector<mm::book> books) { // now we got one book
  116. // TODO: пока что непонятно при такой архитектуре, где cooldown использовать
  117. std::lock_guard<std::mutex> guard(m_);
  118. book_ = books.front();
  119. // TODO: добавить условия на то, когда перевыставляем ордера
  120. market_->cancel_all_orders(symbol, CancelPhaseCb);
  121. }
  122.  
  123. void Start() {
  124. try {
  125. market_->open_trade_listener(symbol, {});
  126. market_->open_book_listener(symbol, ManageOrdersCb);
  127. market_->start();
  128. } catch (const std::exception& e) {
  129. std::cerr << "Main: Error" << e.what() << "\n";
  130. exit(EXIT_FAILURE);
  131. }
  132.  
  133. /*
  134. // Так как пока непонятно как извне с коннектором работать, то пока закомментим
  135. // Хочется отделить сущность коннектора и маркет мейкингового алгоса
  136.  
  137. std::thread{[&]() {
  138. try {
  139. market->open_trade_listener(symbol, {});
  140. market->open_book_listener(symbol, ManageOrdersCb);
  141. market->start();
  142. } catch (const std::exception& e) {
  143. std::cerr << "Main: Error" << e.what() << "\n";
  144. exit(EXIT_FAILURE);
  145. }
  146. }}.detach(); // thought: а что если коннектор упадёт и может ли такое быть
  147.  
  148. while(true) {
  149. ManageOrders();
  150. std::this_thread::sleep_for(std::chrono::milliseconds(cooldown_)); // thought: далее тут можно condvar на пробуждение поставить
  151. }
  152. */
  153. }
  154.  
  155. private:
  156. // Market
  157. std::make_shared<mm::python_connector> market_;
  158. mm::ticker ticker_;
  159. mm::book book_;
  160.  
  161. // Control
  162. int n_lvl_ = 8;
  163. int n_base = 3;
  164. double base_size_to_remain_ = 0.15; // in percentages
  165. double first_order_size_ = 0.1;
  166. double balance_;
  167. double spread_size_ = 0.05; // in percentages
  168. int cooldown_ = 60000; // in ms
  169. int price_step_ = 1;
  170. double min_order_size_;
  171.  
  172. // System
  173. std::mutex m_;
  174. };
  175.  
  176. /**
  177. ./market_making --symbol=BTCUSDT --latency_in=20, --latency_out=3, --filename=../data/new_19502_1 --bal=5000
  178. ./market_making --keys=../market_making.keys --market=lbank --symbol=wei_usdt --spread_size=0.05
  179.  
  180.  
  181. * Bitmart
  182. ./market_making --keys=../keys/bitmart_mm.keys --market=bitmart --symbol=VAB_USDT --spread_size=0.05
  183.  
  184. Full list:
  185. --keys : Key filepath
  186. --market : Name of market (e.g. lbank, mexc, bitmart)
  187. --symbol : Name of the currency pair. could be in a different format (e.g. wei_usdt, CHEELUSDT, VAB_USDT)
  188. --q : Quantity of account's balance that we're using for trades
  189. --cooldown : Timeout between orders in Ms (approximated)
  190. --n_lvl : Number of levels what we want to have for each side. (Inside spread. (Also same amount of orders outside spread)
  191. --calib_coef : How smooth the calibtaion is. Higher value - stronger calibration.
  192. --spread_size : Targeted spread size. Value in percentage of mid_pr
  193. --tagret_price : Used for price support. Algorithm will try to put orders around target_price, or come closer to it
  194. --ema_mid_price : EMA. System.
  195. --alpha : Alpha coefficient for EMA. Affects more sensetive price changing filter
  196. --price_change_limit : Price change limitation for EMA calculation (0.2 = 10% in two ways)
  197. --qty : Lower balance limit (in Base) for trade termination
  198. --min_order_size : Minimal order size in base currency (USDT)
  199. --beta : Largest order / smallest order coeffitient
  200. */
  201. int main(int argc, char* argv[]) {
  202. auto currentMarketMakingManager = std::make_shared<MarketMakingManager>(argc, argv);
  203. currentMarketMakingManager->Start();
  204. }
  205.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement