Advanced ideas

The strategy is a better version of improved strategy.

Its main feature is maintaining orders on multiple quotes in each direction during each update. Quotes count is set by MAX_LEVELS parameter, and order amount - by VOLUME.

Certainly strategy becomes more risky in that case. As we are having big volume on each direction we may lose a lot of money during large price shifts. To be safe during such fluctuations you may stop trading in some direction for some fixed period of time after having a beat on that direction with volume larger than some threshold.

Keeping intervals between price levels helps:

  • having our orders executed near middle price and getting some minor profit.
  • having our orders executed with larger (and so deeper i.e. reaching more far levels from middle price) and more profitable beating orders.

The intervals size is handled by DIFF_BETWEEN_LEVELS parameter.

There is a base version of the strategy:

C++
Python
#include "participant_strategy.h"
#include <vector>
#include <unordered_set>

using namespace hftbattle;

namespace {

class UserStrategy : public ParticipantStrategy {
public:
  explicit UserStrategy(const JsonValue& config) :
      volume_(config["VOLUME"].as<Amount>(1)),
      volume_before_our_order_(config["VOLUME_BEFORE_OUR_ORDER"].as<Amount>(3)),
      offset_(config["OFFSET"].as<Price>(24)),
      max_levels_(config["MAX_LEVELS"].as<size_t>(2)),
      offset_between_levels_(config["OFFSET_BETWEEN_LEVELS"].as<Price>(8)) {
    set_max_total_amount(config["MAX_POS"].as<Amount>(50));
  }

  void trading_book_update(const OrderBook& order_book) override {
    auto& orders = order_book.orders();

    for (Dir dir : {BID, ASK}) {
      auto my_prices = orders.orders_by_dir_as_map(dir);
      std::unordered_set<Price> levels_used;

      auto cur_offset = offset_;
      Amount accumulated_volume = 0;
      for (size_t idx = 0; idx < order_book.depth(); ++idx) {
        if (levels_used.size() >= max_levels_) {
          break;
        }

        auto vol = order_book.volume_by_index(dir, idx);
        auto price = order_book.price_by_index(dir, idx);

        vol -= orders.volume(dir, price);
        accumulated_volume += vol;

        if (vol < volume_before_our_order_ || orders.volume(dir, price)) {
          continue;
        }

        Price target_price = price + dir_sign(dir) * order_book.min_step();
        Price diff = abs(order_book.best_price(opposite_dir(dir)) - target_price);
        if (diff < cur_offset) {
          continue;
        }

        if (my_prices.find(target_price) == my_prices.end()) {
          add_limit_order(dir, target_price, volume_);
        }

        cur_offset = diff + offset_between_levels_;
        levels_used.insert(target_price);
      }
      for (Order* order : orders.orders_by_dir(dir)) {
        if (levels_used.find(order->price()) == levels_used.end()) {
          delete_order(order);
        }
      }
    }
  }

private:
  Amount volume_;
  Amount volume_before_our_order_;
  Price offset_;
  size_t max_levels_;
  Price offset_between_levels_;
};

}  // namespace

REGISTER_CONTEST_STRATEGY(UserStrategy, user_strategy)
# -*- coding: utf-8 -*-


from py_defs import *
from common_enums import *


class Params:
    MIN_VOLUME = 1
    FEE = Decimal(8)


def init(strat, config):
    Params.VOLUME = config.get('VOLUME', 1)
    Params.VOLUME_BEFORE_OUR_ORDER = config.get('VOLUME_BEFORE_OUR_ORDER', 3)
    Params.OFFSET = Decimal(config.get('OFFSET', 24))
    Params.MAX_LEVELS = config.get('MAX_LEVELS', 2)
    Params.OFFSET_BETWEEN_LEVELS = config.get('OFFSET_BETWEEN_LEVELS', 8)

    Params.MAX_POS = config.get('MAX_POS', 50)
    strat.set_max_total_amount(Params.MAX_POS)


def trading_book_update(strat, trading_book):
    orders = trading_book.orders()

    for dir in (BID, ASK):
        my_prices = set(order.price() for order in orders.orders_by_dir(dir))
        levels_used = set()

        cur_offset = Params.OFFSET
        accumulated_volume = 0
        for idx in xrange(trading_book.depth()):
            if len(levels_used) >= Params.MAX_LEVELS:
                break

            vol = trading_book.volume_by_index(dir, idx)
            price = trading_book.price_by_index(dir, idx)

            vol -= orders.volume(dir, price)
            accumulated_volume += vol

            if vol < Params.VOLUME_BEFORE_OUR_ORDER or orders.volume(dir, price):
                continue

            target_price = price + dir_sign(dir) * trading_book.min_step()
            diff = abs(trading_book.best_price(opposite_dir(dir)) - target_price)
            if diff < cur_offset:
                continue

            if target_price not in my_prices:
                strat.add_limit_order(dir, target_price, Params.VOLUME)

            cur_offset = diff + Params.OFFSET_BETWEEN_LEVELS
            levels_used.add(target_price)

        for order in orders.orders_by_dir(dir):
            if order.price() not in levels_used:
                strat.delete_order(order)

results matching ""

    No results matching ""