Advertisement
den4ik2003

Untitled

Jul 2nd, 2024
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 29.20 KB | None | 0 0
  1. #include <execution/execution.hpp>
  2.  
  3. using namespace mira;
  4.  
  5. void execution_config_t::init_additional(const field_t& args) {
  6.     if (args.count("calculate_init_position")) {
  7.         std::string val = args.at("calculate_init_position").s();
  8.         this->calculate_init_position = (val == "true" || std::stoi(val));
  9.     }
  10.     if (args.count("cancel_on_start")) {
  11.         std::string val = args.at("cancel_on_start").s();
  12.         if (val == "true" || std::stoi(val)) {
  13.             this->cancel_on_start = "true";
  14.             if (args.count("cancel_group")) {
  15.                 this->cancel_group = e_order_group_from_str(args.at("cancel_group").s());
  16.             }
  17.         }
  18.         this->calculate_init_position = (val == "true" || std::stoi(val));
  19.     }
  20.     if (args.count("orders_update_cooldown")) {
  21.         this->orders_update_cooldown = args.at("orders_update_cooldown").i();
  22.     }
  23.     if (args.count("path_to_position_file")) {
  24.         this->path_to_position_file = args.at("path_to_position_file").s();
  25.     }
  26.     if (args.count("print_ws_events")) {
  27.         std::string val = args.at("print_ws_events").s();
  28.         this->print_ws_events = (val == "true" || std::stoi(val));
  29.     }
  30.     if (args.count("use_tp_market")) {
  31.         std::string val = args.at("use_tp_market").s();
  32.         this->use_tp_market = (val == "true" || std::stoi(val));
  33.     }
  34.     if (args.count("close_pos_on_cd")) {
  35.         this->close_pos_on_cd = args.at("close_pos_on_cd").i();
  36.     }
  37. }
  38.  
  39. void Execution::_order_storage_updater() {
  40.     auto update_routine = [this] () {
  41.         auto orders = config_.api->get_open_orders(config_.symbol);
  42.         std::lock_guard<std::mutex> locker(orders_.locker);
  43.         orders_.limit_orders.clear();
  44.         orders_.market_orders.clear();
  45.         orders_.algo_orders.clear();
  46.         for (auto order : orders.value()) {
  47.             if (order.type == e_order_type::LIMIT) {
  48.                 orders_.limit_orders[order.client_order_id].order = order;
  49.             } else if (order.type != e_order_type::MARKET) {
  50.                 orders_.algo_orders[order.client_order_id].order = order;
  51.             }
  52.         }
  53.     };
  54.     update_routine();
  55.     std::thread {[this, update_routine] () {
  56.         std::this_thread::sleep_for(std::chrono::seconds(config_.orders_update_cooldown));
  57.         update_routine();
  58.     }}.detach();
  59. }
  60.  
  61. Execution::Execution(const execution_config_t& config, const field_t& trader_args) : config_(config) {
  62.     if (trader_args.count("execution")) {
  63.         config_.init_additional(trader_args.at("execution"));
  64.     }
  65.     config_.shared_state->add_execution_getter(this, config_.symbol);
  66.     stream_description_t description;
  67.    
  68.     description.stream = e_stream::ACCOUNT_ORDER;
  69.     config_.api->subscribe(description, this, config_.symbol);
  70.  
  71.     description.stream = e_stream::ACCOUNT_TRADE;
  72.     config_.api->subscribe(description, this, config_.symbol);
  73.  
  74.     position_info_.position_order.symbol = position_info_.position_trade.symbol = config_.symbol; // TODO внести в конструктор
  75.     if (config_.path_to_position_file != "") {
  76.         if (config_.calculate_init_position) {
  77.             _init_position();
  78.         }
  79.     }
  80.  
  81.     if (e_market_account_type(config_.symbol->api->market) == e_account_type::FUTURES) {
  82.         description.stream = e_stream::ACCOUNT_POSITION;
  83.         config_.api->subscribe(description, this, config_.symbol);
  84.         position_info_.reset_position(config_.api->get_position(config_.symbol).value());
  85.     }
  86.  
  87.     if (config_.cancel_on_start) {
  88.         config_.api->cancel_open_orders(config_.symbol, config_.cancel_group);
  89.     }
  90.  
  91.     _order_storage_updater();
  92. }
  93.  
  94. void Execution::_init_position() {
  95.     position_info_.position_file.open(config_.path_to_position_file, std::ios::app);
  96.     if (!position_info_.position_file.is_open()) {
  97.         config_.logger->log("can't open position file!");
  98.         exit(EXIT_FAILURE);
  99.     }
  100.  
  101.     std::ostringstream position_stream;
  102.     position_stream << position_info_.position_file.rdbuf();
  103.     auto prev_position = field_t::deserialize(position_stream.str());
  104.  
  105.     position_info_.position_order = position_info_.position_trade = position_t {
  106.         .base_quantity = prev_position.get("baseQuantity").f(),
  107.         .entry_price = prev_position.get("entryPrice").f(),
  108.         .position_quote = prev_position.get("quotePosition").f(),
  109.         .symbol = config_.symbol
  110.     };
  111.  
  112.     auto prev_base_qty = prev_position.get("baseBalance").f();
  113.     auto prev_quote_amount = prev_position.get("quoteBalance").f();
  114.  
  115.     auto res_cur_base_qty = config_.api->get_account().value().balances.at(config_.symbol->base);
  116.     auto res_cur_quote_amount = config_.api->get_account().value().balances.at(config_.symbol->quote);
  117.  
  118.     auto cur_base_qty = res_cur_base_qty.free + res_cur_base_qty.locked;
  119.     auto cur_quote_amount = res_cur_quote_amount.free + res_cur_quote_amount.locked;
  120.  
  121.     double shutdown_average_price = (cur_quote_amount - prev_quote_amount) / (prev_base_qty - cur_base_qty);
  122.  
  123.     auto shutdown_trade = trade_t {
  124.         .price = config_.symbol->make_price(shutdown_average_price),
  125.         .quantity = config_.symbol->make_quantity(std::abs(prev_base_qty - cur_base_qty)),
  126.         .symbol = config_.symbol,
  127.         .trade_side = (prev_base_qty - cur_base_qty) > 0 ? e_side::SELL : e_side::BUY,
  128.         .trade_time = get_timestamp()
  129.     };
  130.  
  131.     position_info_.open_position(shutdown_trade, 0);
  132.     position_info_.open_position(shutdown_trade, 1);
  133. }
  134.  
  135. void Execution::_process_self_trade(const order_self_trade_event& event) {
  136.     order_request_t req;
  137.     req.symbol = event.symbol;
  138.     req.price = req.symbol->make_price(event.price);
  139.     req.quantity = req.symbol->make_quantity(event.quantity);
  140.     req.type = e_order_type::LIMIT;
  141.     req.post_only = false;
  142.     req.side = e_side::BUY;
  143.     _safe_new_order(req);
  144.     req.side = e_side::SELL;
  145.     _safe_new_order(req);
  146. }
  147.  
  148. void Execution::_process_limit_grid(const order_limit_grid_event& event) {
  149.     std::unordered_map<int64_t, int64_t> requests;
  150.     std::unordered_map<int64_t, order_appendix_t> appendices;
  151.     for (auto req : event.asks) {
  152.         config_.logger->log(req.price, e_severity_level::DEBUG, "in _process_limit_grid");
  153.         config_.logger->log(req.quantity, e_severity_level::DEBUG, "in _process_limit_grid");
  154.         requests[config_.symbol->make_price(req.price).to_scaled()] += config_.symbol->make_quantity(req.quantity).to_scaled();
  155.         appendices[config_.symbol->make_price(req.price).to_scaled()] = req.appendix;
  156.     }
  157.     for (auto req : event.bids) {
  158.         config_.logger->log(req.price, e_severity_level::DEBUG, "in _process_limit_grid");
  159.         config_.logger->log(req.quantity, e_severity_level::DEBUG, "in _process_limit_grid");
  160.         requests[config_.symbol->make_price(req.price).to_scaled()] -= config_.symbol->make_quantity(req.quantity).to_scaled();
  161.         appendices[config_.symbol->make_price(req.price).to_scaled()] = req.appendix;
  162.     }
  163.     std::vector<std::pair<order_request_t, order_appendix_t>> create_requests;
  164.     std::vector<size_t> to_cancel;
  165.     {
  166.         std::lock_guard<std::mutex> lock(orders_.locker);
  167.         for (const auto& [id, extended_order] : orders_.limit_orders) {
  168.             int64_t cq = (extended_order.order.side == e_side::BUY ? -1 : 1) * extended_order.order.quantity.to_scaled();
  169.             auto it = requests.find(extended_order.order.price.to_scaled());
  170.             if (it == requests.end() || it->second != cq) {
  171.                 to_cancel.push_back(id);
  172.             } else {
  173.                 requests.erase(it);
  174.             }
  175.         }
  176.         for (auto [p, q] : requests) {
  177.             if (std::fabs(q) * p < config_.symbol->min_notional) {
  178.                 continue;
  179.             }
  180.             order_request_t req;
  181.             req.symbol = config_.symbol;
  182.             req.type = e_order_type::LIMIT;
  183.             req.side = (q < 0 ? e_side::BUY : e_side::SELL);
  184.             req.price = config_.symbol->make_price_from_scaled(p);
  185.             req.quantity = config_.symbol->make_quantity_from_scaled(std::fabs(q));
  186.             req.post_only = true;
  187.             config_.logger->log(req, e_severity_level::DEBUG, "@#*&* ");
  188.             create_requests.push_back({req, appendices[p]});
  189.         }
  190.     }
  191.     config_.logger->log("csize: " + std::to_string(to_cancel.size()));
  192.     for (auto id : to_cancel) {
  193.         _safe_cancel_order(id, {}, e_order_type::LIMIT);
  194.     }
  195.     for (auto& [req, app] : create_requests) {
  196.         _safe_new_order(req, app);
  197.     }
  198. }
  199.  
  200. void Execution::_process_taker_buy(const order_taker_buy_event& event) {
  201.     order_request_t req;
  202.     req.symbol = event.symbol;
  203.     req.type = e_order_type::MARKET;
  204.     req.side = e_side::BUY;
  205.     req.reduce_only = event.reduce_only;
  206.     if (event.quantity) {
  207.         req.quantity = config_.symbol->make_quantity(event.quantity);
  208.     } else {
  209.         req.amount = event.amount;
  210.     }
  211.     _safe_new_order(req);
  212. }
  213.  
  214. void Execution::_process_taker_sell(const order_taker_sell_event& event) {
  215.     order_request_t req;
  216.     req.symbol = event.symbol;
  217.     req.type = e_order_type::MARKET;
  218.     req.side = e_side::SELL;
  219.     req.reduce_only = event.reduce_only;
  220.     req.quantity = config_.symbol->make_quantity(event.quantity);
  221.     _safe_new_order(req);
  222. }
  223.  
  224. void Execution::_process(const order_event& event) {
  225.     config_.logger->log(event, e_severity_level::INFO);
  226.  
  227.     if (event.type == e_order_event::SELF_TRADE) {
  228.         _process_self_trade(event.get<order_self_trade_event>());
  229.     } else if (event.type == e_order_event::LIMIT_GRID) {
  230.         config_.logger->log("LIMIT GRID");
  231.         _process_limit_grid(event.get<order_limit_grid_event>());
  232.     } else if (event.type == e_order_event::TAKER_BUY) {
  233.         _process_taker_buy(event.get<order_taker_buy_event>());
  234.     } else if (event.type == e_order_event::TAKER_SELL) {
  235.         _process_taker_sell(event.get<order_taker_sell_event>());
  236.     }
  237. }
  238.  
  239. fill_order_event Execution::_process_account_order(const ws_account_order_event& event) {
  240.     if (event.order.type == e_order_type::LIMIT || event.order.type == e_order_type::MARKET) {
  241.         orders_.locker.lock();
  242.         auto& cur_storage = (event.order.type == e_order_type::LIMIT ? orders_.limit_orders : orders_.market_orders);
  243.         if (event.order.type == e_order_type::LIMIT) {
  244.             config_.logger->log("limit");
  245.         } else {
  246.             config_.logger->log("market");
  247.         }
  248.         auto old_it = cur_storage.find(event.order.client_order_id);
  249.         config_.logger->log(event.order, e_severity_level::DEBUG, "Event order: ");
  250.         if (old_it != cur_storage.end()) { // такой ордер уже был
  251.             order_t& old_order = old_it->second.order;
  252.             config_.logger->log(old_order, e_severity_level::DEBUG, "old order: ");
  253.             if (!old_order.filled_quantity.initialized()) {
  254.                 old_order.filled_quantity = old_order.symbol->make_quantity(0);
  255.             }
  256.             precised_float piece = event.order.filled_quantity - old_order.filled_quantity;
  257.             double quote_piece = event.order.filled_quantity.to_double() * event.order.price.to_double() - old_order.filled_quantity.to_double() * old_order.price.to_double();
  258.             if (quote_piece) {
  259.                 trade_t trade{
  260.                     .price = event.order.price,
  261.                     .quantity = piece,
  262.                     .symbol = event.symbol,
  263.                     .trade_side = event.order.side,
  264.                     .trade_time = event.order.update_time
  265.                 };
  266.                 position_info_.open_position(trade, 1);
  267.             }
  268.  
  269.             if (order_cycle_ended(event.order.status)) {
  270.                 config_.logger->log("erase");
  271.                 cur_storage.erase(old_it);
  272.             } else {
  273.                 old_order = event.order;
  274.             }
  275.             std::vector<std::pair<size_t, e_order_type>> to_cancel;
  276.             for (auto& [id, ext_ord] : orders_.algo_orders) {
  277.                 auto& ord = ext_ord.order;
  278.                 bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  279.                 if ((side && (position_info_.get_position().base_quantity < 0)) ||
  280.                     (!side && (position_info_.get_position().base_quantity > 0))) {
  281.                     continue;
  282.                 }
  283.                 to_cancel.push_back({id, ord.type});
  284.             }
  285.             std::vector<std::pair<std::string, e_order_type>> to_cancel_order_id;
  286.             for (auto& [id, ext_ord] : orders_.order_id_algo_orders) {
  287.                 auto& ord = ext_ord.order;
  288.                 bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  289.                 if ((side && (position_info_.get_position().base_quantity < 0)) ||
  290.                     (!side && (position_info_.get_position().base_quantity > 0))) {
  291.                     continue;
  292.                 }
  293.                 to_cancel_order_id.push_back({id, ord.type});
  294.             }
  295.             orders_.locker.unlock();
  296.             for (auto [id, type] : to_cancel) {
  297.                 _safe_cancel_order(id, {}, type);
  298.             }
  299.             for (auto [id, type] : to_cancel_order_id) {
  300.                 _safe_cancel_order(0, id, type);
  301.             }
  302.             return fill_order_event(piece.to_double(), quote_piece, position_info_.get_position(), event.order);
  303.         }
  304.         orders_.locker.unlock();
  305.     } else if (event.order.type == e_order_type::STOP_LOSS ||
  306.                event.order.type == e_order_type::TAKE_PROFIT) {
  307.         std::lock_guard<std::mutex> lock(orders_.locker);
  308.         if (event.order.client_order_id) {
  309.             auto old_it = orders_.algo_orders.find(event.order.client_order_id);
  310.             if (old_it != orders_.algo_orders.end()) {
  311.                 order_t& old_order = old_it->second.order;
  312.                 if (order_cycle_ended(old_order.status)) {
  313.                     orders_.algo_orders.erase(old_it);
  314.                 } else {
  315.                     old_order = event.order;
  316.                 }
  317.                 return fill_order_event(0, 0, position_info_.get_position(), event.order);
  318.             }
  319.         } else {
  320.             auto old_it = orders_.order_id_algo_orders.find(event.order.order_id);
  321.             if (old_it != orders_.order_id_algo_orders.end()) {
  322.                 order_t& old_order = old_it->second.order;
  323.                 if (order_cycle_ended(old_order.status)) {
  324.                     orders_.order_id_algo_orders.erase(old_it);
  325.                 } else {
  326.                     old_order = event.order;
  327.                 }
  328.                 return fill_order_event(0, 0, position_info_.get_position(), event.order);
  329.             } else {
  330.                 orders_.order_id_algo_orders[event.order.order_id].order = event.order;
  331.             }
  332.         }
  333.     }
  334.     return fill_order_event(event.order.filled_quantity.to_double(), event.order.filled_quantity.to_double() * event.order.price.to_double(), position_info_.get_position(), event.order);
  335. }
  336.  
  337. fill_order_event Execution::_process_account_trade(const ws_account_trade_event& event) {
  338.     orders_.locker.lock();
  339.     double piece = event.trade.quantity.to_double();
  340.     double quote_piece = event.trade.price.to_double();
  341.     trade_t trade = event.trade;
  342.     trade.trade_side = (trade.trade_side == e_side::BUY ? e_side::SELL : e_side::BUY);
  343.     position_info_.open_position(trade, 0);
  344.     std::vector<std::pair<size_t, e_order_type>> to_cancel;
  345.     for (auto& [id, ext_ord] : orders_.algo_orders) {
  346.         auto& ord = ext_ord.order;
  347.         bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  348.         if ((side && (position_info_.get_position().base_quantity < 0)) ||
  349.             (!side && (position_info_.get_position().base_quantity > 0))) {
  350.             continue;
  351.         }
  352.         to_cancel.push_back({id, ord.type});
  353.     }
  354.     std::vector<std::pair<std::string, e_order_type>> to_cancel_order_id;
  355.     for (auto& [id, ext_ord] : orders_.order_id_algo_orders) {
  356.         auto& ord = ext_ord.order;
  357.         bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  358.         if ((side && (position_info_.get_position().base_quantity < 0)) ||
  359.             (!side && (position_info_.get_position().base_quantity > 0))) {
  360.             continue;
  361.         }
  362.         to_cancel_order_id.push_back({id, ord.type});
  363.     }
  364.     orders_.locker.unlock();
  365.     for (auto [id, type] : to_cancel) {
  366.         _safe_cancel_order(id, {}, type);
  367.     }
  368.     for (auto [id, type] : to_cancel_order_id) {
  369.         _safe_cancel_order(0, id, type);
  370.     }
  371.     return fill_order_event(piece, quote_piece, position_info_.get_position(), {});
  372. }
  373.  
  374. fill_order_event Execution::_process_account_position(const ws_account_position_event& event) {
  375.     orders_.locker.lock();
  376.     position_info_.reset_position(event.position);
  377.     if (std::fabs(event.position.base_quantity) < 1e-6) {
  378.         position_info_.not_null_time = 0;
  379.     } else if (!position_info_.not_null_time) {
  380.         position_info_.not_null_time = event.position.update_time;
  381.     }
  382.     std::vector<std::pair<size_t, e_order_type>> to_cancel;
  383.     for (auto& [id, ext_ord] : orders_.algo_orders) {
  384.         auto& ord = ext_ord.order;
  385.         bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  386.         if ((side && (position_info_.get_position().base_quantity < 0)) ||
  387.             (!side && (position_info_.get_position().base_quantity > 0))) {
  388.             continue;
  389.         }
  390.         to_cancel.push_back({id, ord.type});
  391.     }
  392.     std::vector<std::pair<std::string, e_order_type>> to_cancel_order_id;
  393.     for (auto& [id, ext_ord] : orders_.order_id_algo_orders) {
  394.         auto& ord = ext_ord.order;
  395.         bool side = (ord.side == e_side::BUY) ^ (ord.type == e_order_type::STOP_LOSS);
  396.         if ((side && (position_info_.get_position().base_quantity < 0)) ||
  397.             (!side && (position_info_.get_position().base_quantity > 0))) {
  398.             continue;
  399.         }
  400.         to_cancel_order_id.push_back({id, ord.type});
  401.     }
  402.     orders_.locker.unlock();
  403.     for (auto [id, type] : to_cancel) {
  404.         _safe_cancel_order(id, {}, type);
  405.     }
  406.     for (auto [id, type] : to_cancel_order_id) {
  407.         _safe_cancel_order(0, id, type);
  408.     }
  409.     return fill_order_event(0, 0, position_info_.get_position(), {}, event.rpnl);
  410. }
  411.  
  412. fill_event Execution::_process(const ws_event& event) {
  413.     if (config_.print_ws_events) {
  414.         std::cout << event << '\n';
  415.     }
  416.     config_.logger->log(event, e_severity_level::INFO);
  417.     fill_event res;
  418.     if (event.type == e_stream::ACCOUNT_ORDER) {
  419.         auto account_order_event = event.get<ws_account_order_event>();
  420.         res.set(_process_account_order(account_order_event));
  421.     } else if (event.type == e_stream::ACCOUNT_TRADE) {
  422.         auto account_trade_event = event.get<ws_account_trade_event>();
  423.         res.set(_process_account_trade(account_trade_event));
  424.     } else if (event.type == e_stream::ACCOUNT_POSITION) {
  425.         auto account_position_event = event.get<ws_account_position_event>();
  426.         res.set(_process_account_position(account_position_event));
  427.     } else if (event.type == e_stream::TICK) {
  428.         res.type = e_fill_event::TICK;
  429.     }
  430.     res.set_symbol(event.symbol);
  431.     if (config_.close_pos_on_cd && position_info_.not_null_time && position_info_.not_null_time + config_.close_pos_on_cd < get_timestamp()) {
  432.         position_t cur_pos = position_info_.get_position();
  433.         if (cur_pos.base_quantity) {
  434.             order_request_t req;
  435.             req.symbol = cur_pos.symbol;
  436.             req.quantity = req.symbol->make_quantity(cur_pos.base_quantity);
  437.             req.amount = cur_pos.position_quote;
  438.             req.side = (cur_pos.base_quantity > 0 ? e_side::SELL : e_side::BUY);
  439.             req.type = e_order_type::MARKET;
  440.             req.reduce_only = true;
  441.             position_info_.not_null_time = get_timestamp();
  442.             _safe_new_order(req);
  443.         }
  444.     }
  445.     return res;
  446. }
  447.  
  448. void Execution::_safe_new_order(order_request_t req, order_appendix_t app) {
  449.     req.client_order_id = _gen_client_order_id();
  450.     order_t new_ord;
  451.     new_ord.symbol = req.symbol;
  452.     new_ord.type = req.type;
  453.     new_ord.side = req.side;
  454.     new_ord.client_order_id = *req.client_order_id;
  455.     if (req.price.has_value()) {
  456.         new_ord.price = *req.price;
  457.     }
  458.     if (req.quantity.has_value()) {
  459.         new_ord.quantity = *req.quantity;
  460.     }
  461.     if (req.stop_price.has_value()) {
  462.         new_ord.stop_price = *req.stop_price;
  463.     }
  464.     new_ord.post_only = req.post_only;
  465.     new_ord.reduce_only = req.reduce_only;
  466.     new_ord.status = e_order_status::PENDING;
  467.     if (req.symbol->api->market == e_market::BYBIT_FUTURES && app.tp_bips) {
  468.         double bips = *app.tp_bips * 1e-4;
  469.         double stop_price = req.price->to_double() * (1 + (req.side == e_side::BUY ? 1 : -1) * bips);
  470.         req.stop_price = req.symbol->make_price(stop_price);
  471.         req.algo_limit = !config_.use_tp_market;
  472.     }
  473.     {
  474.         std::lock_guard<std::mutex> lock(orders_.locker);
  475.         if (req.type == e_order_type::LIMIT) {
  476.             orders_.limit_orders[*req.client_order_id] = {new_ord, app};
  477.         } else if (req.type == e_order_type::MARKET) {
  478.             orders_.market_orders[*req.client_order_id] = {new_ord, app};
  479.         } else {
  480.             orders_.algo_orders[*req.client_order_id] = {new_ord, app};
  481.         }
  482.     }
  483.     std::thread {[req, this] () {
  484.         config_.logger->log(req, e_severity_level::DEBUG, "! new");
  485.         auto res = config_.api->new_order(req);
  486.         config_.logger->log(res, e_severity_level::DEBUG, "? new");
  487.         if (!res) {
  488.             config_.logger->log(res, e_severity_level::ERROR, "new order error: request=" + to_string(req));
  489.             std::lock_guard<std::mutex> lock(orders_.locker);
  490.             if (req.type == e_order_type::LIMIT) {
  491.                 orders_.limit_orders.erase(*req.client_order_id);
  492.             } else if (req.type == e_order_type::MARKET) {
  493.                 orders_.market_orders.erase(*req.client_order_id);
  494.             } else{
  495.                 orders_.algo_orders.erase(*req.client_order_id);
  496.             }
  497.         }
  498.     }}.detach();
  499. }
  500.  
  501. void Execution::_safe_cancel_order(size_t client_order_id, std::optional<std::string> order_id, e_order_type type) {
  502.     extended_order_t prev_ord;
  503.     {
  504.         std::lock_guard<std::mutex> lock(orders_.locker);
  505.         if (type == e_order_type::LIMIT) {
  506.             auto it = orders_.limit_orders.find(client_order_id);
  507.             if (it == orders_.limit_orders.end()) {
  508.                 return;
  509.             }
  510.             prev_ord = it->second;
  511.         } else {
  512.             if (!order_id) {
  513.                 auto it = orders_.algo_orders.find(client_order_id);
  514.                 if (it == orders_.algo_orders.end()) {
  515.                     return;
  516.                 }
  517.                 prev_ord = it->second;
  518.             } else {
  519.                 auto it = orders_.order_id_algo_orders.find(*order_id);
  520.                 if (it == orders_.order_id_algo_orders.end()) {
  521.                     return;
  522.                 }
  523.                 prev_ord = it->second;
  524.                 orders_.order_id_algo_orders.erase(it);
  525.             }
  526.         }
  527.     }
  528.     std::thread {[client_order_id, order_id, prev_ord, this] () {
  529.         config_.logger->log(prev_ord.order, e_severity_level::DEBUG, "! cancel");
  530.         auto res = config_.api->cancel_order(prev_ord.order.symbol, (order_id ? std::optional<size_t>() : prev_ord.order.client_order_id), order_id);
  531.         config_.logger->log(res, e_severity_level::DEBUG, "? cancel");
  532.         if (!res) {
  533.             config_.logger->log(res, e_severity_level::ERROR, "cancel order error");
  534.             std::lock_guard<std::mutex> lock(orders_.locker);
  535.             if (prev_ord.order.type == e_order_type::LIMIT) {
  536.                 orders_.limit_orders[client_order_id] = prev_ord;
  537.             } else {
  538.                 if (!order_id) {
  539.                     orders_.algo_orders[client_order_id] = prev_ord;
  540.                 } else {
  541.                     orders_.order_id_algo_orders[*order_id] = prev_ord;
  542.                 }
  543.             }
  544.         }
  545.     }}.detach();
  546. }
  547.  
  548. result_t<order_t, e_execution_error> ExecutionGetter::get_order(size_t client_order_id) const {
  549.     result_t<order_t, e_execution_error> res;
  550.  
  551.     auto& orders_storage = exec_->orders_;
  552.     std::lock_guard<std::mutex> locker(orders_storage.locker);
  553.  
  554.     auto it = orders_storage.limit_orders.find(client_order_id);
  555.     if (it != orders_storage.limit_orders.end()) {
  556.         res.set_value(it->second.order);
  557.         return res;
  558.     }
  559.    
  560.     it = orders_storage.algo_orders.find(client_order_id);
  561.     if (it != orders_storage.algo_orders.end()) {
  562.         res.set_value(it->second.order);
  563.         return res;
  564.     }
  565.    
  566.     res.set_error(e_execution_error::ORDER_NOT_FOUND);
  567.     return res;
  568. }
  569.  
  570. float_limit_grid_t ExecutionGetter::get_limit_grid() const {
  571.     float_limit_grid_t res;
  572.  
  573.     auto& orders_storage = exec_->orders_;
  574.     std::lock_guard<std::mutex> locker(orders_storage.locker);
  575.  
  576.     for (auto& [id, ext_ord] : orders_storage.limit_orders) {
  577.         auto& ord = ext_ord.order;
  578.         if (ord.side == e_side::BUY) {
  579.             res.bid_orders[ord.price.to_double()] = (ord.quantity - ord.filled_quantity).to_double();
  580.         } else {
  581.             res.ask_orders[ord.price.to_double()] = (ord.quantity - ord.filled_quantity).to_double();
  582.         }
  583.     }
  584.    
  585.     return res;
  586. }
  587.  
  588. void Execution::_position_info_t::open_position(const trade_t& trade, bool is_order) {
  589.     std::lock_guard lock(locker);
  590.  
  591.     std::cerr << "$$$ " << trade << '\n';
  592.  
  593.     exec->config_.logger->log(trade, e_severity_level::INFO, "Open position: ");
  594.  
  595.     position_t position = (is_order ? position_order : position_trade);
  596.    
  597.     int prev_pos_sgn = (position.base_quantity > 0);
  598.  
  599.     if (trade.trade_side == e_side::BUY) {
  600.         position.position_quote += trade.price.to_double() * trade.quantity.to_double();
  601.         position.base_quantity += trade.quantity.to_double();
  602.     }
  603.     if (trade.trade_side == e_side::SELL) {
  604.         position.position_quote -= trade.price.to_double() * trade.quantity.to_double();
  605.         position.base_quantity -= trade.quantity.to_double();
  606.     }
  607.  
  608.     int cur_pos_sgn = (position.base_quantity > 0);
  609.  
  610.     if (position.base_quantity == 0) {
  611.         position.position_quote = 0;
  612.         position.entry_price = 0;
  613.     } else {
  614.         if (position.position_quote != 0) { // Пример: BUY (p1, q1) = (1, 1) -> SELL (p2, q2) = (1.25, 0.8) -> q_remain = 0.2 but position = 0
  615.             if (prev_pos_sgn == cur_pos_sgn) { // случай, когда мы усредняемся по цене
  616.                 position.entry_price = std::abs(position.position_quote / position.base_quantity);  
  617.             } else { // случай, когда наша позиция сменила сторону (например, с SELL на BUY)
  618.                 position.entry_price = trade.price.to_double();
  619.             }
  620.         }
  621.     }
  622.  
  623.     position.update_time = trade.trade_time;
  624.  
  625.     if (is_order) {
  626.         position_order = position;
  627.     } else {
  628.         position_trade = position;
  629.     }
  630.  
  631.     exec->config_.logger->log(position, e_severity_level::INFO, "new position");
  632.  
  633.     if (exec->config_.path_to_position_file != "") {
  634.         if (exec->position_info_.position_file.is_open()) {
  635.             const auto& balances = exec->config_.api->get_account().value().balances;
  636.             auto base_balance = balances.at(exec->config_.symbol->base);
  637.             auto quote_balance = balances.at(exec->config_.symbol->quote);
  638.  
  639.             exec->config_.logger->log("writing to volume price file");
  640.             std::filesystem::resize_file(exec->config_.path_to_position_file, 0);
  641.             exec->position_info_.position_file.seekp(0);
  642.  
  643.             exec->config_.logger->log("{\"baseQuantity\": \"" + std::to_string(position.base_quantity) + "\",\n" +
  644.                 "\"entryPrice\": \"" + std::to_string(position.entry_price) + "\",\n" +
  645.                 "\"quotePosition\": \"" + std::to_string(position.position_quote) + "\",\n" +
  646.                 "\"baseBalance\": \"" + std::to_string(base_balance.locked + base_balance.free) + "\",\n" +
  647.                 "\"quoteBalance\": \"" + std::to_string(quote_balance.locked + quote_balance.free) + "\",\n" + "}");
  648.  
  649.             exec->position_info_.position_file <<
  650.                 "{\"baseQuantity\": \"" + std::to_string(position.base_quantity) + "\",\n" <<
  651.                 "\"entryPrice\": \"" + std::to_string(position.entry_price) + "\",\n" <<
  652.                 "\"quotePosition\": \"" + std::to_string(position.position_quote) + "\",\n" <<
  653.                 "\"baseBalance\": \"" + std::to_string(base_balance.locked + base_balance.free) + "\",\n" <<
  654.                 "\"quoteBalance\": \"" + std::to_string(quote_balance.locked + quote_balance.free) + "\",\n" << "}" << std::flush;
  655.         } else {
  656.             exec->config_.logger->log("execution position file is not open but has non zero path");
  657.         }
  658.          
  659.     }
  660. }
  661.  
  662. void Execution::_position_info_t::reset_position(const position_t& position) {
  663.     std::lock_guard lock(locker);
  664.  
  665.     position_order = position;
  666.     position_trade = position;
  667.  
  668.     exec->config_.logger->log(position, e_severity_level::INFO, "new position");
  669. }
  670.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement