Advertisement
den4ik2003

Untitled

Jul 12th, 2024
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.66 KB | None | 0 0
  1. #include <algo/volume/volume_strategy.hpp>
  2.  
  3. using namespace mira;
  4.  
  5. const int volume::VolumeBot::aux_ = StrategyBuilder::add_strategy<VolumeBot>("VOLUME_BOT");
  6.  
  7. volume::VolumeBot::VolumeBot(const strategy_config_t& config) : BasicStrategy(config) {
  8. *static_cast<strategy_config_t*>(&config_) = config;
  9.  
  10. using conv_fn = std::function<void(const std::string&)>;
  11. std::unordered_map<std::string, conv_fn> cnv = {
  12. {"volume", [this](const auto& v) { config_.volume = std::stod(v); }},
  13. {"min_order_size", [this](const auto& v) { config_.min_order_size = std::stod(v); }},
  14. {"symbol", [this](const auto& v) { config_.symbol_str = v; }},
  15. {"sigma", [this](const auto& v) { config_.sigma = std::stod(v); }},
  16. {"volume_sigma", [this](const auto& v) { config_.volume_sigma = std::stod(v); }},
  17. {"path_to_price_file", [this](const auto& v) { config_.path_to_price_file = v; }},
  18. {"time_frequency",
  19. [this](const auto& v) {
  20. config_.cooldown = std::stoi(v);
  21. config_.sleep_time = config_.cooldown;
  22. }
  23. },
  24. };
  25.  
  26. for (const auto &[key, fn] : cnv) {
  27. try {
  28. if (config_.args.count(key)) {
  29. fn(config_.args[key].s());
  30. }
  31. } catch (const std::exception& e) {
  32. config_.logger->log("Error for key " + key + ": " + e.what());
  33. std::exit(EXIT_FAILURE);
  34. }
  35. }
  36.  
  37. config_.time_distribution = std::normal_distribution{static_cast<double>(config_.cooldown), config_.cooldown * 0.1};
  38. config_.volume_distribution = std::normal_distribution{static_cast<double>(config_.volume), config_.volume * config_.volume_sigma};
  39.  
  40. auto bid_and_ask = config_.shared_state->get_data_getter(config_.symbols.back()).get_order_book()[0];
  41. auto market_mid_price = (bid_and_ask.ask_price + bid_and_ask.bid_price) / 2;
  42.  
  43. if (config_.path_to_price_file == "") {
  44. config_.logger->log("no volume price file");
  45. config_.previous_price = market_mid_price;
  46. } else {
  47. config_.logger->log("opening volume price file: " + config_.path_to_price_file);
  48. config_.price_file.open(config_.path_to_price_file, std::ios::app);
  49. if (!config_.price_file.is_open()) {
  50. config_.logger->log("can't open volume price file!");
  51. exit(EXIT_FAILURE);
  52. }
  53. if (std::filesystem::file_size(config_.path_to_price_file) == 0) {
  54. config_.logger->log("volume price file is empty -> writing price = " + std::to_string(market_mid_price));
  55. config_.price_file << "{\"market_price\": \"" + std::to_string(market_mid_price) + "\"}" << std::flush;
  56. }
  57. std::string all_string = "", buf;
  58. std::ifstream config(config_.path_to_price_file);
  59. while (config >> buf) {
  60. all_string += buf;
  61. }
  62. config_.logger->log("initial price from file: " + all_string);
  63. config_.previous_price = field_t::deserialize(all_string).at("market_price").f();
  64.  
  65. if (config_.previous_price >= bid_and_ask.ask_price || config_.previous_price <= bid_and_ask.bid_price) {
  66. config_.logger->log("config_.previous_price >= bid_and_ask.ask_price || config_.previous_price <= bid_and_ask.bid_price");
  67. config_.previous_price = market_mid_price;
  68. }
  69. }
  70. }
  71.  
  72. order_event volume::VolumeBot::_process(const market_event& event) {
  73. order_event res;
  74. // config_.logger->log("event");
  75. // if (event.type == e_market_event::TICK) {
  76. // config_.logger->log("tick");
  77. // }
  78. if (get_timestamp() - config_.upd_time < config_.sleep_time) { // 0-момент по-идее сюда не попадёт
  79. return res;
  80. }
  81. config_.logger->log("delta time = " + std::to_string(get_timestamp() - config_.upd_time));
  82. config_.upd_time = get_timestamp();
  83.  
  84. if (event.type == e_market_event::ORDER_BOOK) {
  85. auto orderbook_event = event.get<market_order_book_event>();
  86.  
  87. config_.sleep_time = calculate_deviated_value(config_.time_distribution, 0.8 * config_.cooldown, 1.2 * config_.cooldown);
  88. config_.logger->log("sleep time = " + std::to_string(config_.sleep_time));
  89.  
  90. auto ask_price = event.symbol->make_price(orderbook_event.order_book[0].ask_price);
  91. auto bid_price = event.symbol->make_price(orderbook_event.order_book[0].bid_price);
  92.  
  93. if (!ask_price.initialized() || !bid_price.initialized()) {
  94. config_.logger->log("No ask or bid");
  95. return res;
  96. }
  97. size_t spread_ticks = (ask_price - bid_price).to_scaled();
  98.  
  99. config_.logger->log("ask price " + ask_price.to_string() + " bid price: " + bid_price.to_string());
  100.  
  101. if (spread_ticks == event.symbol->price_step.to_scaled()) { // норм ли сравниваются precised_float?
  102. config_.logger->log("Narrow spread");
  103. return res;
  104. }
  105.  
  106. double current_volume = calculate_deviated_value(config_.volume_distribution, 0.8 * config_.volume, 1.2 * config_.volume);
  107. config_.logger->log("current_volume: " + std::to_string(current_volume) + " previous price = " + std::to_string(config_.previous_price));
  108. config_.logger->log("start calculating new normal distributed price");
  109.  
  110. double current_price = calculate_normal_distributed_price(config_.previous_price, (bid_price + 1).to_double(), (ask_price - 1).to_double());
  111. double quantity = current_volume / current_price;
  112.  
  113. config_.previous_price = current_price;
  114. if (config_.price_file.is_open()) {
  115. config_.logger->log("writing to volume price file");
  116. std::filesystem::resize_file(config_.path_to_price_file, 0);
  117. config_.price_file.seekp(0);
  118. config_.price_file << "{\"market_price\": \"" + std::to_string(current_price) + "\"}" << std::flush;
  119. }
  120.  
  121. config_.logger->log("price: " + std::to_string(current_price) + "\nquantity: " + std::to_string(quantity));
  122.  
  123. res.set(order_self_trade_event(current_price, quantity));
  124. res.set_symbol(event.symbol);
  125. } else if (event.type == e_market_event::TICK) {
  126.  
  127. }
  128.  
  129. return res;
  130. }
  131.  
  132. double volume::VolumeBot::calculate_deviated_value(std::normal_distribution<double>& distribution, double lower_bound, double upper_bound) {
  133. auto sampled_value = distribution(config_.gen);
  134. return std::max(std::min(sampled_value, upper_bound), lower_bound);
  135. }
  136.  
  137. double volume::VolumeBot::calculate_normal_distributed_price(double current_price, double lower_bound, double upper_bound) {
  138. /* the probability of being in the [p * (1 - sigma), p * (1 + sigma)] is about 96% (= erf(sqrt(2)))*/
  139. std::normal_distribution<double> price_distr(current_price, current_price * config_.sigma / 2);
  140. double new_price = calculate_deviated_value(price_distr, current_price * (1 - config_.sigma), current_price * (1 + config_.sigma));
  141. config_.logger->log("calculate deviated price (new) = " + std::to_string(new_price) + " current price = " + std::to_string(current_price));
  142. double delta = new_price - current_price;
  143. config_.logger->log("delta = " + std::to_string(delta));
  144. if (new_price > upper_bound) { // здесь delta > 0
  145. config_.logger->log("new_price > upper_bound");
  146. new_price = std::min(std::max(current_price - std::abs(delta), lower_bound), upper_bound);
  147. } else if (new_price < lower_bound) { // здесь delta < 0 будет
  148. config_.logger->log("new_price < lower_bound");
  149. new_price = std::max(std::min(current_price + std::abs(delta), upper_bound), lower_bound);
  150. }
  151. config_.logger->log("new price after = " + std::to_string(new_price));
  152. return new_price;
  153. }
  154.  
  155. order_event volume::VolumeBot::calculate_trade_event(const market_event& event, precised_float ask_price, precised_float bid_price) {
  156. order_event res;
  157.  
  158. if (!ask_price.initialized() || !bid_price.initialized()) {
  159. config_.logger->log("No ask or bid");
  160. return res;
  161. }
  162. size_t spread_ticks = (ask_price - bid_price).to_scaled();
  163.  
  164. config_.logger->log("ask price " + ask_price.to_string() + " bid price: " + bid_price.to_string());
  165.  
  166. if (spread_ticks == event.symbol->price_step.to_scaled()) { // норм ли сравниваются precised_float?
  167. config_.logger->log("Narrow spread");
  168. return res;
  169. }
  170.  
  171. double current_volume = calculate_deviated_value(config_.volume_distribution, 0.8 * config_.volume, 1.2 * config_.volume);
  172. config_.logger->log("current_volume: " + std::to_string(current_volume) + " previous price = " + std::to_string(config_.previous_price));
  173. config_.logger->log("start calculating new normal distributed price");
  174.  
  175. double current_price = calculate_normal_distributed_price(config_.previous_price, (bid_price + 1).to_double(), (ask_price - 1).to_double());
  176. double quantity = current_volume / current_price;
  177.  
  178. config_.previous_price = current_price;
  179. if (config_.price_file.is_open()) {
  180. config_.logger->log("writing to volume price file");
  181. std::filesystem::resize_file(config_.path_to_price_file, 0);
  182. config_.price_file.seekp(0);
  183. config_.price_file << "{\"market_price\": \"" + std::to_string(current_price) + "\"}" << std::flush;
  184. }
  185.  
  186. config_.logger->log("price: " + std::to_string(current_price) + "\nquantity: " + std::to_string(quantity));
  187.  
  188. res.set(order_self_trade_event(current_price, quantity));
  189. res.set_symbol(event.symbol);
  190. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement