Advertisement
den4ik2003

Untitled

Jun 11th, 2024
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.29 KB | None | 0 0
  1. #include <strategy/market_making/mexc_spot/mm_strategy.hpp>
  2.  
  3. namespace mira {
  4.  
  5. namespace marketmaking {
  6.  
  7. MexcSpotMarketMaking::MexcSpotMarketMaking(strategy_config_t config) : Strategy(config) {
  8. using conv_fn = std::function<void(const std::string&)>;
  9.  
  10. *reinterpret_cast<strategy_config_t*>(&config_) = config; // init parent part
  11.  
  12. std::unordered_map<std::string, conv_fn> cnv = {
  13. {"api", [this](const auto& v) { config_.api_key = v; }},
  14. {"secret", [this](const auto& v) { config_.secret_key = v; }},
  15. {"available_base_balance_to_total", [this](const auto& v) { config_.available_base_balance_to_total = std::stod(v); }},
  16. {"available_quote_balance_to_total", [this](const auto& v) { config_.available_quote_balance_to_total = std::stod(v); }},
  17. {"cancel_on_signal_event", [this](const auto& v) { config_.cancel_on_signal_event = std::stoi(v); }},
  18. {"min_order_size", [this](const auto& v) { config_.min_order_size = std::stod(v); }},
  19. {"n_base", [this](const auto& v) { config_.n_base = std::stoi(v); }},
  20. {"n_lvl", [this](const auto& v) { config_.n_lvl = std::stoi(v); }},
  21. {"price_step", [this](const auto& v) { config_.price_step = std::stoi(v); }},
  22. {"cooldown", [this](const auto& v) { config_.cooldown = std::stoi(v); }},
  23. {"spread_size", [this](const auto& v) { config_.spread_size = std::stod(v); }},
  24. {"symbol", [this](const auto& v) { config_.symbol_str = v; }},
  25. {"target_price", [this](const auto& v) { config_.target.price = std::stod(v); }},
  26. {"debug", [this](const auto& v) { config_.debug = std::stoi(v); }},
  27. {"target_type",
  28. [this](const auto& v) {
  29. if (v == "up") {
  30. config_.target.type = target::targetType::Up;
  31. } else if (v == "down") {
  32. config_.target.type = target::targetType::Down;
  33. } else if (v == "stable") {
  34. config_.target.type = target::targetType::Stable;
  35. }
  36. }
  37. },
  38. };
  39.  
  40. for (const auto &[key, fn] : cnv) {
  41. try {
  42. if (config_.init_args.count(key)) {
  43. fn(config_.init_args[key].s());
  44. }
  45. } catch (const std::exception& e) {
  46. config_.logger->log("Error for key " + key + ": " + e.what());
  47. std::exit(EXIT_FAILURE);
  48. }
  49. }
  50.  
  51. // Validate some parameters
  52. if (config_.target.type == target::targetType::Stable && !config_.target.price.has_value()) {
  53. config_.logger->log("Wrong target type: \"Stable\", but no targetPrice specified.");
  54. exit(EXIT_FAILURE);
  55. }
  56.  
  57. // if (!config_.debug) {
  58. // std::string fname = "/mnt/logs/" + config_.symbol_str + "-" + get_date(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) + ".log";
  59. // std::cout << "***\n"
  60. // << fname << "\n***\n";
  61. // std::freopen(fname.c_str(), "w", stderr);
  62. // }
  63. }
  64.  
  65. order_event MexcSpotMarketMaking::_process(const market_event& event) {
  66. order_event res;
  67. if (event.type == e_market_event::ORDER_BOOK) {
  68. auto orderbook_event = event.get<market_order_book_event>();
  69.  
  70. _update_mid_price(orderbook_event);
  71.  
  72. if (config_hidden_.previous_mid_price == config_hidden_.mid_price) {
  73. return res;
  74. }
  75.  
  76. int spread_ticks = std::max(
  77. (config_hidden_.mid_price * config_.spread_size).to_scaled(), INT_64_ONE
  78. );
  79.  
  80. auto [asks, bids] = calculate_orders(config_hidden_.mid_price, spread_ticks);
  81.  
  82. auto limit_event = order_limit_grid_event(asks, bids);
  83. res.set(std::move(limit_event));
  84. res.set_symbol(config_.symbol);
  85. // config_.logger->log(res, e_severity_level::DEBUG);
  86. }
  87.  
  88. return res;
  89. }
  90.  
  91. MexcSpotMarketMaking::asks_and_bids MexcSpotMarketMaking::calculate_orders(precised_float mid_price, int spread_ticks) // TODO залогировать
  92. {
  93. // config_.logger->log("start orders calculating");
  94. auto& balance_getter = config_.shared_state.get()->get_balance_getter(config_.market, config_.init_args.at("account_name").s());
  95.  
  96. auto base_balance_res = balance_getter.get_balance(config_.symbol->base);
  97. auto quote_balance_res = balance_getter.get_balance(config_.symbol->quote);
  98.  
  99. // config_.logger->log(base_balance_res, e_severity_level::DEBUG, "base balance");
  100. // config_.logger->log(quote_balance_res, e_severity_level::DEBUG, "quote balance");
  101.  
  102. auto base_balance = (base_balance_res.free + base_balance_res.locked) * config_.available_base_balance_to_total;
  103. auto quote_balance = (quote_balance_res.free + quote_balance_res.locked) * config_.available_quote_balance_to_total;
  104.  
  105. // if (quote_balance / config_.available_quote_balance_to_total < 250) {
  106. // std::cerr << "hardcode low balance indicator im gonna die: " << (quote_balance_res.free + quote_balance_res.locked);
  107. // exit(EXIT_FAILURE);
  108. // }
  109.  
  110. const auto& bid_and_asks_levels = config_.shared_state->get_data_getter(config_.symbol).get_order_book()[0]; // TODO: это же не факт, что органика
  111. auto ask_price = std::max(mid_price, config_.symbol->make_price(bid_and_asks_levels.bid_price) + 1) + (spread_ticks + 1) / 2;
  112. auto bid_price = std::min(mid_price, config_.symbol->make_price(bid_and_asks_levels.ask_price) - 1) - spread_ticks / 2;
  113.  
  114. double base_amount_per_level = base_balance / config_.n_base;
  115. double quote_amount_per_level = quote_balance / config_.n_base;
  116.  
  117. std::vector<std::pair<double, double>> asks, bids;
  118.  
  119. for (int i = 0; i < config_.n_lvl; ++i) {
  120. // SELL orders
  121. auto sell_price = (ask_price + i * config_.price_step).to_double();
  122. asks.push_back(std::make_pair(sell_price, base_amount_per_level));
  123.  
  124. // BUY orders
  125. auto buy_price = (bid_price - i * config_.price_step).to_double();
  126. bids.push_back(std::make_pair(buy_price, quote_amount_per_level / buy_price));
  127. }
  128. // config_.logger->log("calculating completed");
  129. return std::make_pair(std::move(asks), std::move(bids));
  130. }
  131.  
  132. // Обновляет мидпрайс и время её последнего изменения
  133. void MexcSpotMarketMaking::_update_mid_price(const market_order_book_event& event) {
  134. config_.logger.get()->log(event, e_severity_level::INFO, "_update_mid_price: ");
  135. if (!config_hidden_.mid_price.initialized()) {
  136. config_hidden_.mid_price = config_.symbol->make_price(0);
  137. }
  138.  
  139. if (config_.target.price.has_value()) {
  140. // ветка для таргетированной цены:
  141. config_hidden_.mid_price = config_.symbol->make_price(config_.target.price.value());
  142. } else {
  143. const auto& bid_and_asks_levels = event.order_book[0];
  144.  
  145. double mid_price;
  146. if (bid_and_asks_levels.ask_price && bid_and_asks_levels.bid_price) { // в стакане есть и бид и аск
  147. mid_price = (bid_and_asks_levels.ask_price + bid_and_asks_levels.bid_price) / 2;
  148. } else if (bid_and_asks_levels.ask_price + bid_and_asks_levels.bid_price != 0) { // в стакане есть либо бид, либо аск
  149.  
  150. if (bid_and_asks_levels.ask_price) { // есть аск
  151. mid_price = bid_and_asks_levels.ask_price * (1 - config_.spread_size / 2);
  152. } else { // есть бид
  153. mid_price = bid_and_asks_levels.bid_price * (1 + config_.spread_size / 2);
  154. }
  155.  
  156. } else { // пустой стакан
  157. mid_price = 1;
  158. }
  159. config_hidden_.previous_mid_price = config_hidden_.mid_price;
  160. config_hidden_.mid_price = config_.symbol->make_price(mid_price);
  161. }
  162. // config_.logger->log("new mid price: " + config_hidden_.mid_price.to_string());
  163.  
  164. }
  165.  
  166. } // namespace marketmaking
  167.  
  168.  
  169. } // namespace mira
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement