Advertisement
den4ik2003

Untitled

May 13th, 2024
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.47 KB | None | 0 0
  1. #include <execution/execution.hpp>
  2.  
  3. using namespace mira;
  4.  
  5. Execution::Execution(const execution_config_t& config) : config_(config) {
  6. config_.shared_state->add_execution_getter(this, config_.symbol);
  7. stream_description_t description;
  8. description.stream = e_stream::ACCOUNT_ORDER;
  9. description.args["symbol"] = config_.symbol->symbol;
  10.  
  11. {
  12. auto orders = config_.api->get_open_orders(config_.symbol);
  13. std::lock_guard<std::mutex> locker(orders_.locker);
  14. for (auto order : orders.value()) {
  15. if (!order.client_order_id) {
  16. continue;
  17. }
  18. if (order.type == e_order_type::LIMIT) {
  19. orders_.limit_orders[order.client_order_id] = order;
  20. } else {
  21. orders_.algo_orders[order.client_order_id] = order;
  22. }
  23. }
  24. }
  25. config_.api->subscribe(description, this);
  26.  
  27. __init_position();
  28. }
  29.  
  30. void Execution::__update_position_with_open_orders() {
  31. position_info_.open_orders_file.open(config_.path_to_open_orders_file);
  32. if (!position_info_.open_orders_file.is_open()) {
  33. std::cerr << "can't open open_orders file!\n";
  34. exit(EXIT_FAILURE);
  35. }
  36.  
  37. auto orders = config_.api->get_open_orders(config_.symbol);
  38.  
  39. std::ostringstream orders_stream;
  40. orders_stream << position_info_.open_orders_file.rdbuf();
  41. auto prev_orders_deserialized = field_t::deserialize(orders_stream.str());
  42. std::vector<order_t> prev_orders;
  43.  
  44. for (size_t i = 0; i < prev_orders_deserialized.size(); ++i) {
  45. prev_orders[i].client_order_id = prev_orders_deserialized[i].get("clientOrderId").i();
  46. prev_orders[i].price = config_.symbol->make_price(prev_orders_deserialized[i].get("price").f());
  47. prev_orders[i].quantity = config_.symbol->make_price(prev_orders_deserialized[i].get("origQty").f());
  48. prev_orders[i].filled_quantity = config_.symbol->make_price(prev_orders_deserialized[i].get("executedQty").f());
  49. prev_orders[i].side = prev_orders_deserialized[i].get("side").s() == "SELL" ? e_side::SELL : e_side::BUY;
  50.  
  51. std::string status = prev_orders_deserialized[i].get("status").s();
  52. if (status == "NEW") {
  53. prev_orders[i].status = e_order_status::NEW;
  54. } else if (status == "PARTIALLY_FILLED") {
  55. prev_orders[i].status = e_order_status::PARTIALLY_FILLED;
  56. } else if (status == "FILLED") {
  57. prev_orders[i].status = e_order_status::FILLED;
  58. } else if (status == "CANCELED" || status == "PARTIALLY_CANCELED") {
  59. prev_orders[i].status = e_order_status::CANCELED;
  60. } else {
  61. throw std::runtime_error("previous order doesn't have status field");
  62. }
  63. }
  64.  
  65. for (const auto& prev_order : prev_orders) {
  66. for (const auto& order : orders.value()) {
  67. if (prev_order.client_order_id == order.client_order_id) {
  68. if (prev_order.filled_quantity != order.filled_quantity) {
  69. trade_t trade{
  70. .price = prev_order.price,
  71. .quantity = order.filled_quantity - prev_order.filled_quantity,
  72. .trade_side = prev_order.side
  73. };
  74. position_info_.position.open_position(trade);
  75. }
  76. break;
  77. }
  78. }
  79. // т.е. ордер не найден -> исполнен был полностью
  80. trade_t trade{
  81. .price = prev_order.price,
  82. .quantity = prev_order.quantity - prev_order.filled_quantity,
  83. .trade_side = prev_order.side
  84. };
  85. position_info_.position.open_position(trade);
  86. }
  87. }
  88.  
  89. void Execution::__init_position() {
  90. position_info_.position_file.open(config_.path_to_position_file);
  91. if (!position_info_.position_file.is_open()) {
  92. std::cerr << "can't open position file!\n";
  93. exit(EXIT_FAILURE);
  94. }
  95.  
  96. std::ostringstream position_stream;
  97. position_stream << position_info_.position_file.rdbuf();
  98. auto prev_position = field_t::deserialize(position_stream.str());
  99.  
  100. position_info_.position = position_t {
  101. .base_quantity = prev_position.get("baseQuantity").f(),
  102. .entry_price = prev_position.get("entryPrice").f(),
  103. .position_quote = prev_position.get("quotePosition").f(),
  104. .symbol = config_.symbol
  105. };
  106.  
  107. auto prev_base_qty = prev_position.get("baseBalance").f();
  108. auto prev_quote_amount = prev_position.get("quoteBalance").f();
  109.  
  110. auto res_cur_base_qty = config_.api->get_account().value().balances.at(config_.symbol->base);
  111. auto res_cur_quote_amount = config_.api->get_account().value().balances.at(config_.symbol->quote);
  112.  
  113. auto cur_base_qty = res_cur_base_qty.free + res_cur_base_qty.locked;
  114. auto cur_quote_amount = res_cur_quote_amount.free + res_cur_quote_amount.locked;
  115.  
  116. double shutdown_average_price = (cur_quote_amount - prev_quote_amount) / (prev_base_qty - cur_base_qty);
  117.  
  118. auto shutdown_trade = trade_t {
  119. .price = config_.symbol->make_price(shutdown_average_price),
  120. .quantity = config_.symbol->make_quantity(std::abs(prev_base_qty - cur_base_qty)),
  121. .trade_side = (prev_base_qty - cur_base_qty) > 0 ? e_side::SELL : e_side::BUY
  122. };
  123.  
  124. position_info_.position.open_position(shutdown_trade);
  125. __update_position_with_open_orders();
  126. }
  127.  
  128. void Execution::__process_limit_grid(const order_limit_grid_event& event) {
  129. std::unordered_map<size_t, double> requests;
  130. for (auto [p, q] : event.asks) {
  131. requests[config_.symbol->make_price(p).to_scaled()] += q;
  132. }
  133. for (auto [p, q] : event.bids) {
  134. requests[config_.symbol->make_price(p).to_scaled()] -= q;
  135. }
  136. std::vector<order_request_t> create_requests;
  137. std::vector<size_t> to_cancel;
  138. {
  139. std::lock_guard<std::mutex> lock(orders_.locker);
  140. for (const auto& [id, order] : orders_.limit_orders) {
  141. double cq = (order.side == e_side::BUY ? -1 : 1) * order.quantity.to_double();
  142. auto it = requests.find(order.price.to_scaled());
  143. if (it == requests.end() || it->second != cq) {
  144. to_cancel.push_back(id);
  145. } else {
  146. requests.erase(it);
  147. }
  148. }
  149. for (auto [p, q] : requests) {
  150. if (std::fabs(q) * p < config_.symbol->min_notional) {
  151. continue;
  152. }
  153. order_request_t req;
  154. req.symbol = config_.symbol;
  155. req.type = e_order_type::LIMIT;
  156. req.side = (q < 0 ? e_side::BUY : e_side::SELL);
  157. req.price = config_.symbol->make_price_from_scaled(p);
  158. req.quantity = config_.symbol->make_quantity(std::fabs(q));
  159. req.client_order_id = __gen_client_order_id();
  160. req.post_only = true;
  161. std::cerr << "@#*&* " << req << '\n';
  162. create_requests.push_back(req);
  163. }
  164. }
  165. std::cerr << "csize: " << to_cancel.size() << '\n';
  166. for (size_t id : to_cancel) {
  167. __safe_cancel_order(id, e_order_type::LIMIT);
  168. }
  169. for (auto& req : create_requests) {
  170. __safe_new_order(req);
  171. }
  172. }
  173.  
  174. void Execution::__process_taker_buy(const order_taker_buy_event& event) {
  175. order_request_t req;
  176. req.symbol = config_.symbol;
  177. req.type = e_order_type::MARKET;
  178. req.side = e_side::BUY;
  179. *req.amount = event.amount;
  180. config_.api->new_order(req);
  181. }
  182.  
  183. void Execution::__process_taker_sell(const order_taker_sell_event& event) {
  184. order_request_t req;
  185. req.symbol = config_.symbol;
  186. req.type = e_order_type::MARKET;
  187. req.side = e_side::SELL;
  188. req.quantity = config_.symbol->make_quantity(event.quantity);
  189. config_.api->new_order(req);
  190. }
  191.  
  192. void Execution::__process(const order_event& event) {
  193. // logger_->log(event, e_severity_level::INFO);
  194. if (event.type == e_order_event::LIMIT_GRID) {
  195. std::cerr << "LIMIT_GRID" << '\n';
  196. __process_limit_grid(event.get<order_limit_grid_event>());
  197. } else if (event.type == e_order_event::TAKER_BUY) {
  198. __process_taker_buy(event.get<order_taker_buy_event>());
  199. } else if (event.type == e_order_event::TAKER_SELL) {
  200. __process_taker_sell(event.get<order_taker_sell_event>());
  201. }
  202. }
  203.  
  204. fill_order_event Execution::__process_account_order(const ws_account_order_event& event) {
  205. std::lock_guard<std::mutex> lock(orders_.locker);
  206. if (event.order.type == e_order_type::LIMIT) {
  207. auto old_it = orders_.limit_orders.find(event.order.client_order_id);
  208. if (old_it != orders_.limit_orders.end()) { // такой ордер уже был
  209. order_t& old_order = old_it->second;
  210. if (!old_order.filled_quantity.initialized()) {
  211. old_order.filled_quantity = old_order.symbol->make_quantity(0);
  212. }
  213. auto piece = event.order.filled_quantity - old_order.filled_quantity;
  214.  
  215. trade_t trade{
  216. .price = event.order.price,
  217. .quantity = piece,
  218. .symbol = event.order.symbol,
  219. .trade_side = event.order.side,
  220. .trade_time = 0
  221. };
  222. position_info_.position.open_position(trade);
  223.  
  224. if (order_cycle_ended(old_order.status)) {
  225. orders_.limit_orders.erase(old_it);
  226. } else {
  227. old_order = event.order;
  228. }
  229. return fill_order_event(event.order, piece.to_double(), position_info_.position);
  230. }
  231. } else if (event.order.type == e_order_type::STOP_LOSS ||
  232. event.order.type == e_order_type::TAKE_PROFIT) {
  233. auto old_it = orders_.algo_orders.find(event.order.client_order_id);
  234. if (old_it != orders_.algo_orders.end()) {
  235. order_t& old_order = old_it->second;
  236. if (order_cycle_ended(old_order.status)) {
  237. orders_.algo_orders.erase(old_it);
  238. } else {
  239. old_order = event.order;
  240. }
  241. return fill_order_event(event.order, 0, position_info_.position);
  242. }
  243. } else if (event.order.type == e_order_type::MARKET) {
  244. trade_t trade{
  245. .price = event.order.price,
  246. .quantity = event.order.quantity,
  247. .symbol = event.order.symbol,
  248. .trade_side = event.order.side,
  249. .trade_time = 0
  250. };
  251. position_info_.position.open_position(trade);
  252. }
  253. return fill_order_event(event.order, event.order.filled_quantity.to_double(), position_info_.position);
  254. }
  255.  
  256. fill_event Execution::__process(const ws_event& event) {
  257. config_.logger->log(event, e_severity_level::INFO);
  258. fill_event res;
  259. if (event.type == e_stream::ACCOUNT_ORDER) {
  260. auto account_order_event = event.get<ws_account_order_event>();
  261. // Этот if станет ненужным, когда пофиксим баг с вызовом хэндлеров для ивентов
  262. if (account_order_event.order.symbol == config_.symbol) { // т.к. может прийти ивент по другой монете, но с того же аккаунта
  263. res.set(__process_account_order(account_order_event));
  264. }
  265. }
  266. return res;
  267. }
  268.  
  269. void Execution::__safe_new_order(const order_request_t& req) {
  270. order_t new_ord;
  271. new_ord.symbol = req.symbol;
  272. new_ord.type = req.type;
  273. new_ord.side = req.side;
  274. new_ord.client_order_id = *req.client_order_id;
  275. new_ord.price = *req.price;
  276. new_ord.quantity = *req.quantity;
  277. if (req.stop_price) {
  278. new_ord.stop_price = *req.stop_price;
  279. }
  280. new_ord.status = e_order_status::PENDING;
  281. {
  282. std::lock_guard<std::mutex> lock(orders_.locker);
  283. if (req.type == e_order_type::LIMIT) {
  284. orders_.limit_orders[*req.client_order_id] = new_ord;
  285. } else {
  286. orders_.algo_orders[*req.client_order_id] = new_ord;
  287. }
  288. }
  289. std::thread {[req, this] () {
  290. std::cerr << req << '\n';
  291. auto res = config_.api->new_order(req);
  292. std::cerr << res << '\n';
  293. if (!res) {
  294. config_.logger->log(res, e_severity_level::ERROR, "new order error");
  295. std::lock_guard<std::mutex> lock(orders_.locker);
  296. if (req.type == e_order_type::LIMIT) {
  297. orders_.limit_orders.erase(*req.client_order_id);
  298. } else {
  299. orders_.algo_orders.erase(*req.client_order_id);
  300. }
  301. }
  302. }}.detach();
  303. }
  304.  
  305. void Execution::__safe_cancel_order(size_t client_order_id, e_order_type type) {
  306. order_t prev_ord;
  307. {
  308. std::lock_guard<std::mutex> lock(orders_.locker);
  309. if (type == e_order_type::LIMIT) {
  310. auto it = orders_.limit_orders.find(client_order_id);
  311. if (it == orders_.limit_orders.end()) {
  312. return;
  313. }
  314. prev_ord = it->second;
  315. } else {
  316. auto it = orders_.algo_orders.find(client_order_id);
  317. if (it == orders_.algo_orders.end()) {
  318. return;
  319. }
  320. prev_ord = it->second;
  321. }
  322. }
  323. std::thread {[prev_ord, this] () {
  324. std::cerr << "! cancel " << prev_ord << '\n';
  325. auto res = config_.api->cancel_order(prev_ord.symbol, prev_ord.client_order_id);
  326. std::cerr << "? " << res << '\n';
  327. if (!res) {
  328. config_.logger->log(res, e_severity_level::ERROR, "cancel order error");
  329. std::lock_guard<std::mutex> lock(orders_.locker);
  330. if (prev_ord.type == e_order_type::LIMIT) {
  331. orders_.limit_orders[prev_ord.client_order_id] = prev_ord;
  332. } else {
  333. orders_.algo_orders[prev_ord.client_order_id] = prev_ord;
  334. }
  335. }
  336. }}.detach();
  337. }
  338.  
  339. result_t<order_t, e_execution_error> ExecutionGetter::get_order(size_t client_order_id) const {
  340. result_t<order_t, e_execution_error> res;
  341.  
  342. auto& orders_storage = exec_->orders_;
  343. std::lock_guard<std::mutex> locker(orders_storage.locker);
  344.  
  345. auto it = orders_storage.limit_orders.find(client_order_id);
  346. if (it != orders_storage.limit_orders.end()) {
  347. res.set_value(it->second);
  348. return res;
  349. }
  350.  
  351. it = orders_storage.algo_orders.find(client_order_id);
  352. if (it != orders_storage.algo_orders.end()) {
  353. res.set_value(it->second);
  354. return res;
  355. }
  356.  
  357. res.set_error(e_execution_error::ORDER_NOT_FOUND);
  358. return res;
  359. }
  360.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement