Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algo/volume/volume_strategy.hpp>
- using namespace mira;
- const int volume::VolumeBot::aux_ = StrategyBuilder::add_strategy<VolumeBot>("VOLUME_BOT");
- volume::VolumeBot::VolumeBot(const strategy_config_t& config) : BasicStrategy(config) {
- *static_cast<strategy_config_t*>(&config_) = config;
- using conv_fn = std::function<void(const std::string&)>;
- std::unordered_map<std::string, conv_fn> cnv = {
- {"volume", [this](const auto& v) { config_.volume = std::stod(v); }},
- {"min_order_size", [this](const auto& v) { config_.min_order_size = std::stod(v); }},
- {"symbol", [this](const auto& v) { config_.symbol_str = v; }},
- {"sigma", [this](const auto& v) { config_.sigma = std::stod(v); }},
- {"volume_sigma", [this](const auto& v) { config_.volume_sigma = std::stod(v); }},
- {"path_to_price_file", [this](const auto& v) { config_.path_to_price_file = v; }},
- {"time_frequency",
- [this](const auto& v) {
- config_.cooldown = std::stoi(v);
- config_.sleep_time = config_.cooldown;
- }
- },
- };
- for (const auto &[key, fn] : cnv) {
- try {
- if (config_.args.count(key)) {
- fn(config_.args[key].s());
- }
- } catch (const std::exception& e) {
- config_.logger->log("Error for key " + key + ": " + e.what());
- std::exit(EXIT_FAILURE);
- }
- }
- config_.time_distribution = std::normal_distribution{static_cast<double>(config_.cooldown), config_.cooldown * 0.1};
- config_.volume_distribution = std::normal_distribution{static_cast<double>(config_.volume), config_.volume * config_.volume_sigma};
- auto bid_and_ask = config_.shared_state->get_data_getter(config_.symbols.back()).get_order_book()[0];
- auto market_mid_price = (bid_and_ask.ask_price + bid_and_ask.bid_price) / 2;
- if (config_.path_to_price_file == "") {
- config_.logger->log("no volume price file");
- config_.previous_price = market_mid_price;
- } else {
- config_.logger->log("opening volume price file: " + config_.path_to_price_file);
- config_.price_file.open(config_.path_to_price_file, std::ios::app);
- if (!config_.price_file.is_open()) {
- config_.logger->log("can't open volume price file!");
- exit(EXIT_FAILURE);
- }
- if (std::filesystem::file_size(config_.path_to_price_file) == 0) {
- config_.logger->log("volume price file is empty -> writing price = " + std::to_string(market_mid_price));
- config_.price_file << "{\"market_price\": \"" + std::to_string(market_mid_price) + "\"}" << std::flush;
- }
- std::string all_string = "", buf;
- std::ifstream config(config_.path_to_price_file);
- while (config >> buf) {
- all_string += buf;
- }
- config_.logger->log("initial price from file: " + all_string);
- config_.previous_price = field_t::deserialize(all_string).at("market_price").f();
- if (config_.previous_price >= bid_and_ask.ask_price || config_.previous_price <= bid_and_ask.bid_price) {
- config_.logger->log("config_.previous_price >= bid_and_ask.ask_price || config_.previous_price <= bid_and_ask.bid_price");
- config_.previous_price = market_mid_price;
- }
- }
- }
- order_event volume::VolumeBot::_process(const market_event& event) {
- order_event res;
- // config_.logger->log("event");
- // if (event.type == e_market_event::TICK) {
- // config_.logger->log("tick");
- // }
- if (get_timestamp() - config_.upd_time < config_.sleep_time) { // 0-момент по-идее сюда не попадёт
- return res;
- }
- config_.logger->log("delta time = " + std::to_string(get_timestamp() - config_.upd_time));
- config_.upd_time = get_timestamp();
- if (event.type == e_market_event::ORDER_BOOK) {
- auto orderbook_event = event.get<market_order_book_event>();
- config_.sleep_time = calculate_deviated_value(config_.time_distribution, 0.8 * config_.cooldown, 1.2 * config_.cooldown);
- config_.logger->log("sleep time = " + std::to_string(config_.sleep_time));
- auto ask_price = event.symbol->make_price(orderbook_event.order_book[0].ask_price);
- auto bid_price = event.symbol->make_price(orderbook_event.order_book[0].bid_price);
- if (!ask_price.initialized() || !bid_price.initialized()) {
- config_.logger->log("No ask or bid");
- return res;
- }
- size_t spread_ticks = (ask_price - bid_price).to_scaled();
- config_.logger->log("ask price " + ask_price.to_string() + " bid price: " + bid_price.to_string());
- if (spread_ticks == event.symbol->price_step.to_scaled()) { // норм ли сравниваются precised_float?
- config_.logger->log("Narrow spread");
- return res;
- }
- double current_volume = calculate_deviated_value(config_.volume_distribution, 0.8 * config_.volume, 1.2 * config_.volume);
- config_.logger->log("current_volume: " + std::to_string(current_volume) + " previous price = " + std::to_string(config_.previous_price));
- config_.logger->log("start calculating new normal distributed price");
- double current_price = calculate_normal_distributed_price(config_.previous_price, (bid_price + 1).to_double(), (ask_price - 1).to_double());
- double quantity = current_volume / current_price;
- config_.previous_price = current_price;
- if (config_.price_file.is_open()) {
- config_.logger->log("writing to volume price file");
- std::filesystem::resize_file(config_.path_to_price_file, 0);
- config_.price_file.seekp(0);
- config_.price_file << "{\"market_price\": \"" + std::to_string(current_price) + "\"}" << std::flush;
- }
- config_.logger->log("price: " + std::to_string(current_price) + "\nquantity: " + std::to_string(quantity));
- res.set(order_self_trade_event(current_price, quantity));
- res.set_symbol(event.symbol);
- } else if (event.type == e_market_event::TICK) {
- }
- return res;
- }
- double volume::VolumeBot::calculate_deviated_value(std::normal_distribution<double>& distribution, double lower_bound, double upper_bound) {
- auto sampled_value = distribution(config_.gen);
- return std::max(std::min(sampled_value, upper_bound), lower_bound);
- }
- double volume::VolumeBot::calculate_normal_distributed_price(double current_price, double lower_bound, double upper_bound) {
- /* the probability of being in the [p * (1 - sigma), p * (1 + sigma)] is about 96% (= erf(sqrt(2)))*/
- std::normal_distribution<double> price_distr(current_price, current_price * config_.sigma / 2);
- double new_price = calculate_deviated_value(price_distr, current_price * (1 - config_.sigma), current_price * (1 + config_.sigma));
- config_.logger->log("calculate deviated price (new) = " + std::to_string(new_price) + " current price = " + std::to_string(current_price));
- double delta = new_price - current_price;
- config_.logger->log("delta = " + std::to_string(delta));
- if (new_price > upper_bound) { // здесь delta > 0
- config_.logger->log("new_price > upper_bound");
- new_price = std::min(std::max(current_price - std::abs(delta), lower_bound), upper_bound);
- } else if (new_price < lower_bound) { // здесь delta < 0 будет
- config_.logger->log("new_price < lower_bound");
- new_price = std::max(std::min(current_price + std::abs(delta), upper_bound), lower_bound);
- }
- config_.logger->log("new price after = " + std::to_string(new_price));
- return new_price;
- }
- order_event volume::VolumeBot::calculate_trade_event(const market_event& event, precised_float ask_price, precised_float bid_price) {
- order_event res;
- if (!ask_price.initialized() || !bid_price.initialized()) {
- config_.logger->log("No ask or bid");
- return res;
- }
- size_t spread_ticks = (ask_price - bid_price).to_scaled();
- config_.logger->log("ask price " + ask_price.to_string() + " bid price: " + bid_price.to_string());
- if (spread_ticks == event.symbol->price_step.to_scaled()) { // норм ли сравниваются precised_float?
- config_.logger->log("Narrow spread");
- return res;
- }
- double current_volume = calculate_deviated_value(config_.volume_distribution, 0.8 * config_.volume, 1.2 * config_.volume);
- config_.logger->log("current_volume: " + std::to_string(current_volume) + " previous price = " + std::to_string(config_.previous_price));
- config_.logger->log("start calculating new normal distributed price");
- double current_price = calculate_normal_distributed_price(config_.previous_price, (bid_price + 1).to_double(), (ask_price - 1).to_double());
- double quantity = current_volume / current_price;
- config_.previous_price = current_price;
- if (config_.price_file.is_open()) {
- config_.logger->log("writing to volume price file");
- std::filesystem::resize_file(config_.path_to_price_file, 0);
- config_.price_file.seekp(0);
- config_.price_file << "{\"market_price\": \"" + std::to_string(current_price) + "\"}" << std::flush;
- }
- config_.logger->log("price: " + std::to_string(current_price) + "\nquantity: " + std::to_string(quantity));
- res.set(order_self_trade_event(current_price, quantity));
- res.set_symbol(event.symbol);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement