Simple strategy example

Description of the strategy and its source code

The idea of the strategy is to keep one order on the best price at each direction (BID and ASK) with the price of middle_price and a constant offset offset in the corresponding direction. In case a direction has none of our active orders, the strategy places an order with volume of volume. In case an order exists, but happens to be placed on the different price, we cancel it and place a new one. The volume of the placed order can be decreased for us not to get out of the maximum position limit. It is very important for HFT strategy to be able to quickly close the current position. So, we will try to limit the maximum open position to the value of max_pos.

Description of the strategy parameters:

  • volume — volume of the orders being placed.
  • max_pos — maximal position.
  • offset — price difference from the middle_price.

#include "participant_strategy.h"

using namespace hftbattle;

namespace {

class UserStrategy : public ParticipantStrategy {
  UserStrategy(const JsonValue& config) :
      offset_(config["offset"].as<Price>(18)) {

  Amount max_available_order_amount(Amount pos, Dir dir) {
    Amount max_amount = std::min(max_pos_ - dir_sign(dir) * pos, volume_);
    return std::max(0, max_amount);

  void trading_book_update(const OrderBook& order_book) override {
    const auto& orders = order_book.orders();
    Price middle_price = order_book.middle_price();
    Amount pos = executed_amount();

    add_chart_point("middle_price", middle_price);

    for (Dir dir : {BID, ASK}) {
      Price target_price = middle_price - dir_sign(dir) * offset_;
      Amount order_amount = max_available_order_amount(pos, dir);

      if (orders.active_orders_count(dir) == 0) {
        if (order_amount > 0) {
          add_limit_order(dir, target_price, order_amount);
      } else {
        Order* current_order = orders.orders_by_dir(dir).front();
        if (current_order->price() != target_price) {
          if (order_amount > 0) {
            add_limit_order(dir, target_price, order_amount);

  Amount volume_;
  Amount max_pos_;
  Price offset_;

}  // namespace

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

from py_defs import *
from py_defs import Decimal as Price
from common_enums import *

class Params:

def init(strat, config):
    Params.VOLUME = config.get('VOLUME', 1)
    Params.MAX_POS = config.get('MAX_POS', 1)
    Params.OFFSET = Price(config.get('OFFSET', 18))


def max_available_order_amount(pos, dir):
    max_amount = min(Params.MAX_POS - dir_sign(dir) * pos, Params.VOLUME)
    return max(max_amount, 0)

def trading_book_update(strat, order_book):
    orders = order_book.orders()
    middle_price = order_book.middle_price()
    pos = strat.executed_amount()

    strat.add_chart_point('middle_price', middle_price)

    for dir in (BID, ASK):
        target_price = middle_price - dir_sign(dir) * Params.OFFSET
        order_amount = max_available_order_amount(pos, dir)

        if orders.active_orders_count(dir) == 0:
            if order_amount > 0:
                strat.add_limit_order(dir, target_price, order_amount)
            current_order = orders.orders_by_dir(dir)[0]
            if current_order.price() != target_price:
                if order_amount > 0:
                    strat.add_limit_order(dir, target_price, order_amount)

The strategy analysis

Since the strategy keeps only 1 order with a volume of 1 lot for each direction, it does not make enough deals to produce a good profit. On the other hand, limiting position would not allow the strategy to keep its position in one direction for a long time. Staying in one-directed position leads to large losses in periods of order book fluctuations.

More complicated strategy and ideas for further implementation are available here.

results matching ""

    No results matching ""