Advertisement
den4ik2003

Untitled

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