はじめに

最良買い気配値と最良売り気配値の表示

[1]:
from numba import njit

import numpy as np

# numba.njit is strongly recommended for fast backtesting.
@njit
def print_bbo(hbt):
    # Iterating until hftbacktest reaches the end of data.
    # Elapses 60-sec every iteration.
    # Time unit is the same as data's timestamp's unit.
    # Timestamp of the sample data is in nanoseconds.
    while hbt.elapse(60 * 1e9) == 0:
        # Gets the market depth for the first asset.
        depth = hbt.depth(0)

        # Prints the best bid and the best offer.
        print(
            'current_timestamp:', hbt.current_timestamp,
            ', best_bid:', np.round(depth.best_bid, 1),
            ', best_ask:', np.round(depth.best_ask, 1)
        )
    return True
[2]:
from hftbacktest import BacktestAsset, HashMapMarketDepthBacktest

asset = (
    BacktestAsset()
        # Sets the data to feed for this asset.
        #
        # Due to the vast size of tick-by-tick market depth and trade data,
        # loading the entire dataset into memory can be challenging,
        # particularly when backtesting across multiple days.
        # HftBacktest offers lazy loading support and is compatible with npy and preferably npz.
        #
        # For details on the normalized feed data, refer to the following documents.
        # * https://hftbacktest.readthedocs.io/en/latest/data.html
        # * https://hftbacktest.readthedocs.io/en/latest/tutorials/Data%20Preparation.html
        .data(['usdm/btcusdt_20240809.npz'])
        # Sets the initial snapshot (optional).
        .initial_snapshot('usdm/btcusdt_20240808_eod.npz')
        # Asset type:
        # * Linear
        # * Inverse.
        # 1.0 represents the contract size, which is the value of the asset per quoted price.
        .linear_asset(1.0)
        # HftBacktest provides two built-in latency models.
        # * constant_latency
        # * intp_order_latency
        # To implement your own latency model, please use Rust.
        #
        # Time unit is the same as data's timestamp's unit. Timestamp of the sample data is in nanoseconds.
        # Sets the order entry latency and response latency to 10ms.
        .constant_latency(10_000_000, 10_000_000)
        # HftBacktest provides several types of built-in queue position models.
        # Please find the details in the documents below.
        # https://hftbacktest.readthedocs.io/en/latest/tutorials/Probability%20Queue%20Models.html
        #
        # To implement your own queue position model, please use Rust.
        .risk_adverse_queue_model()
        # HftBacktest provides two built-in exchange models.
        # * no_partial_fill_exchange
        # * partial_fill_exchange
        # To implement your own exchange model, please use Rust.
        .no_partial_fill_exchange()
        # HftBacktest provides several built-in fee models.
        # * trading_value_fee_model
        # * trading_qty_fee_model
        # * flat_per_trade_fee_model
        #
        # 0.02% maker fee and 0.07% taker fee. If the fee is negative, it represents a rebate.
        # For example, -0.00005 represents a 0.005% rebate for the maker order.
        .trading_value_fee_model(0.0002, 0.0007)
        # Tick size of this asset: minimum price increasement
        .tick_size(0.1)
        # Lot size of this asset: minimum trading unit.
        .lot_size(0.001)
        # Sets the capacity of the vector that stores trades occurring in the market.
        # If you set the size, you need call `clear_last_trades` to clear the vector.
        # A value of 0 indicates that no market trades are stored. (Default)
        .last_trades_capacity(0)
)

# HftBacktest provides several types of built-in market depth implementations.
# HashMapMarketDepthBacktest constructs a Backtest using a HashMap-based market depth implementation.
# Another useful implementation is ROIVectorMarketDepth, which is utilized in ROIVectorMarketDepthBacktest.
# Please find the details in the document below.
hbt = HashMapMarketDepthBacktest([asset])

最良買い気配値と最良売り気配値を60秒ごとに確認できます。価格は32ビット浮動小数点数であるため、浮動小数点誤差が発生する可能性があります。使用する際には注意してください。例では、読みやすさのために価格がティックサイズに基づいて丸められています。

[3]:
print_bbo(hbt)
current_timestamp: 1723161661500000000 , best_bid: 61594.1 , best_ask: 61594.2
current_timestamp: 1723161721500000000 , best_bid: 61576.5 , best_ask: 61576.6
current_timestamp: 1723161781500000000 , best_bid: 61629.6 , best_ask: 61629.7
current_timestamp: 1723161841500000000 , best_bid: 61621.5 , best_ask: 61621.6
current_timestamp: 1723161901500000000 , best_bid: 61583.9 , best_ask: 61584.0
[3]:
True

HftBacktestは再利用できません。したがって、バックテストを使用した後は必ず閉じてください。閉じた後にバックテストを使用するとクラッシュします。

[4]:
_ = hbt.close()

データのフィード

十分なメモリを持っている場合、データをメモリに事前ロードし、繰り返しバックテスト中に遅延ロードするよりも効率的に入力することができます。

[5]:
btcusdt_20230809 = np.load('usdm/btcusdt_20240809.npz')['data']
btcusdt_20230808_eod = np.load('usdm/btcusdt_20240808_eod.npz')['data']

asset = (
    BacktestAsset()
        .data([btcusdt_20230809])
        .initial_snapshot(btcusdt_20230808_eod)
        .linear_asset(1.0)
        .constant_latency(10_000_000, 10_000_000)
        .risk_adverse_queue_model()
        .no_partial_fill_exchange()
        .trading_value_fee_model(0.0002, 0.0007)
        .tick_size(0.1)
        .lot_size(0.001)
)
[6]:
hbt = HashMapMarketDepthBacktest([asset])

print_bbo(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , best_bid: 61594.1 , best_ask: 61594.2
current_timestamp: 1723161721500000000 , best_bid: 61576.5 , best_ask: 61576.6
current_timestamp: 1723161781500000000 , best_bid: 61629.6 , best_ask: 61629.7
current_timestamp: 1723161841500000000 , best_bid: 61621.5 , best_ask: 61621.6
current_timestamp: 1723161901500000000 , best_bid: 61583.9 , best_ask: 61584.0

市場深度の取得

[7]:
@njit
def print_3depth(hbt):
    while hbt.elapse(60 * 1e9) == 0:
        print('current_timestamp:', hbt.current_timestamp)

        # Gets the market depth for the first asset, in the same order as when you created the backtest.
        depth = hbt.depth(0)

        # a key of bid_depth or ask_depth is price in ticks.
        # (integer) price_tick = price / tick_size
        i = 0
        for tick_price in range(depth.best_ask_tick, depth.best_ask_tick + 100):
            qty = depth.ask_qty_at_tick(tick_price)
            if qty > 0:
                print(
                    'ask: ',
                    qty,
                    '@',
                    np.round(tick_price * depth.tick_size, 1)
                )

                i += 1
                if i == 3:
                    break
        i = 0
        for tick_price in range(depth.best_bid_tick, max(depth.best_bid_tick - 100, 0), -1):
            qty = depth.bid_qty_at_tick(tick_price)
            if qty > 0:
                print(
                    'bid: ',
                    qty,
                    '@',
                    np.round(tick_price * depth.tick_size, 1)
                )

                i += 1
                if i == 3:
                    break
    return True
[8]:
hbt = HashMapMarketDepthBacktest([asset])

print_3depth(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000
ask:  1.759 @ 61594.2
ask:  0.006 @ 61594.4
ask:  0.114 @ 61595.2
bid:  3.526 @ 61594.1
bid:  0.016 @ 61594.0
bid:  0.002 @ 61593.9
current_timestamp: 1723161721500000000
ask:  2.575 @ 61576.6
ask:  0.004 @ 61576.7
ask:  0.455 @ 61577.0
bid:  2.558 @ 61576.5
bid:  0.002 @ 61576.0
bid:  0.515 @ 61575.5
current_timestamp: 1723161781500000000
ask:  0.131 @ 61629.7
ask:  0.005 @ 61630.1
ask:  0.005 @ 61630.5
bid:  5.742 @ 61629.6
bid:  0.247 @ 61629.4
bid:  0.034 @ 61629.3
current_timestamp: 1723161841500000000
ask:  0.202 @ 61621.6
ask:  0.002 @ 61622.5
ask:  0.003 @ 61622.6
bid:  3.488 @ 61621.5
bid:  0.86 @ 61620.0
bid:  0.248 @ 61619.6
current_timestamp: 1723161901500000000
ask:  1.397 @ 61584.0
ask:  0.832 @ 61585.1
ask:  0.132 @ 61586.0
bid:  3.307 @ 61583.9
bid:  0.01 @ 61583.8
bid:  0.002 @ 61582.0

注文の提出

[9]:
from hftbacktest import LIMIT, GTC, NONE, NEW, FILLED, CANCELED, EXPIRED

@njit
def print_orders(hbt):
    # You can access open orders and also closed orders via hbt.orders.
    # Gets the OrderDict for the first asset.
    orders = hbt.orders(0)

    # hbt.orders is a dictionary, but be aware that it does not support all dict methods, and its keys are order_id (int).
    order_values = orders.values()
    while order_values.has_next():
        order = order_values.get()

        order_status = ''
        if order.status == NONE:
            order_status = 'NONE' # Exchange hasn't received an order yet.
        elif order.status == NEW:
            order_status = 'NEW'
        elif order.status == FILLED:
            order_status = 'FILLED'
        elif order.status == CANCELED:
            order_status = 'CANCELED'
        elif order.status == EXPIRED:
            order_status = 'EXPIRED'

        order_req = ''
        if order.req == NONE:
            order_req = 'NONE'
        elif order.req == NEW:
            order_req = 'NEW'
        elif order.req == CANCELED:
            order_req = 'CANCEL'

        print(
            'current_timestamp:', hbt.current_timestamp,
             ', order_id:', order.order_id,
             ', order_price:', np.round(order.price, 1),
             ', order_qty:', order.qty,
             ', order_status:', order_status,
             ', order_req:', order_req
        )

@njit
def submit_order(hbt):
    is_order_submitted = False
    while hbt.elapse(30 * 1e9) == 0:
        # Prints open orders.
        print_orders(hbt)

        depth = hbt.depth(0)

        if not is_order_submitted:
            # Submits a buy order at 300 ticks below the best bid for the first asset.
            order_id = 1
            order_price = depth.best_bid - 300 * depth.tick_size
            order_qty = 1
            time_in_force = GTC # Good 'till cancel
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            is_order_submitted = True
    return True
[10]:
hbt = HashMapMarketDepthBacktest([asset])

submit_order(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161691500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161721500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161751500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161781500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161811500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161841500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161871500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161901500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE

非アクティブな注文のクリア (FILLED, CANCELED, EXPIRED)

[11]:
from hftbacktest import GTC

@njit
def clear_inactive_orders(hbt):
    is_order_submitted = False
    while hbt.elapse(30 * 1e9) == 0:
        print_orders(hbt)

        # Removes inactive(FILLED, CANCELED, EXPIRED) orders from hbt.orders for the first asset.
        hbt.clear_inactive_orders(0)

        depth = hbt.depth(0)

        if not is_order_submitted:
            order_id = 1
            order_price = depth.best_bid - 300 * depth.tick_size
            order_qty = 1
            time_in_force = GTC
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            is_order_submitted = True
    return True
[12]:
hbt = HashMapMarketDepthBacktest([asset])

clear_inactive_orders(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , order_id: 1 , order_price: 61643.8 , order_qty: 1.0 , order_status: FILLED , order_req: NONE

注文ステータスの監視 - 注文遅延による保留中

[13]:
from hftbacktest import GTC

@njit
def watch_pending(hbt):
    is_order_submitted = False
    # Elapses 0.01-sec every iteration.
    while hbt.elapse(0.01 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        depth = hbt.depth(0)

        if not is_order_submitted:
            order_id = 1
            order_price = depth.best_bid - 300 * depth.tick_size
            order_qty = 1
            time_in_force = GTC
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            is_order_submitted = True

        # Prevents too many prints
        orders = hbt.orders(0)
        order = orders.get(order_id)
        if order.status == NEW:
            return False
    return True

order_statusは受け入れメッセージが受信されるまでNoneです。

[14]:
hbt = HashMapMarketDepthBacktest([asset])

watch_pending(hbt)

_ = hbt.close()
current_timestamp: 1723161601520000000 , order_id: 1 , order_price: 61629.7 , order_qty: 1.0 , order_status: NONE , order_req: NEW
current_timestamp: 1723161601530000000 , order_id: 1 , order_price: 61629.7 , order_qty: 1.0 , order_status: NEW , order_req: NONE

注文応答の待機

[15]:
from hftbacktest import GTC

@njit
def wait_for_order_response(hbt):
    order_id = 0
    is_order_submitted = False
    while hbt.elapse(0.01 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        # Prevents too many prints
        orders = hbt.orders(0)
        if order_id in orders:
            if orders.get(order_id).status == NEW:
                return False

        depth = hbt.depth(0)

        if not is_order_submitted:
            order_id = 1
            order_price = depth.best_bid
            order_qty = 1
            time_in_force = GTC
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            # Waits for the order response for a given order id for the first asset.
            print('an order is submitted at', hbt.current_timestamp)

            # Timeout is set 1-second.
            hbt.wait_order_response(0, order_id, 1 * 1e9)
            print('an order response is received at', hbt.current_timestamp)
            is_order_submitted = True
    return True

ConstantLatencyモデルが使用されているため、往復遅延は正確に200msです。理想的には、ライブ市場から収集された履歴注文遅延データを使用するのが最良のアプローチです。ただし、このデータが利用できない場合は、フィード遅延に基づいて人工的に生成された注文遅延を使用することから始めるのも一つの方法です。これについては、次の例で詳しく説明します。

[16]:
hbt = HashMapMarketDepthBacktest([asset])

wait_for_order_response(hbt)

_ = hbt.close()
an order is submitted at 1723161601510000000
an order response is received at 1723161601530000000
current_timestamp: 1723161601540000000 , order_id: 1 , order_price: 61659.7 , order_qty: 1.0 , order_status: NEW , order_req: NONE

ポジション、残高、手数料、エクイティの表示

[17]:
@njit
def position(hbt):
    is_order_submitted = False
    while hbt.elapse(60 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        # Prints position
        print(
            'current_timestamp:', hbt.current_timestamp,
            ', position:', hbt.position(0),
            ', balance:', hbt.state_values(0).balance,
            ', fee:', hbt.state_values(0).fee
        )

        depth = hbt.depth(0)

        if not is_order_submitted:
            order_id = 1
            order_price = depth.best_bid
            order_qty = 1
            time_in_force = GTC
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)

            # Timeout is set 1-second.
            hbt.wait_order_response(0, order_id, 1e9)
            is_order_submitted = True
    return True
[18]:
hbt = HashMapMarketDepthBacktest([asset])

position(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , position: 0.0 , balance: 0.0 , fee: 0.0
current_timestamp: 1723161721520000000 , order_id: 1 , order_price: 61594.1 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161721520000000 , position: 1.0 , balance: -61594.100000000006 , fee: 12.318820000000002
current_timestamp: 1723161781520000000 , position: 1.0 , balance: -61594.100000000006 , fee: 12.318820000000002
current_timestamp: 1723161841520000000 , position: 1.0 , balance: -61594.100000000006 , fee: 12.318820000000002
current_timestamp: 1723161901520000000 , position: 1.0 , balance: -61594.100000000006 , fee: 12.318820000000002

オープン注文のキャンセル

[19]:
@njit
def submit_and_cancel_order(hbt):
    is_order_submitted = False
    while hbt.elapse(0.1 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        # Cancels if there is an open order
        orders = hbt.orders(0)
        order_values = orders.values()
        while order_values.has_next():
            order = order_values.get()

            # an order is only cancellable if order status is NEW.
            # cancel request is negated if the order is already filled or filled before cancel request is processed.
            if order.cancellable:
                hbt.cancel(0, order.order_id, False)
                # You can see status still NEW and see req CANCEL.
                print_orders(hbt)
                # cancels request also has order entry/response latencies the same as submitting.
                hbt.wait_order_response(0, order.order_id, 1e9)

        if not is_order_submitted:
            depth = hbt.depth(0)

            order_id = 1
            order_price = depth.best_bid - 100 * depth.tick_size
            order_qty = 1
            time_in_force = GTC
            order_type = LIMIT
            hbt.submit_buy_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)

            # Timeout is set 1-second.
            hbt.wait_order_response(0, order_id, 1e9)
            is_order_submitted = True
        else:
            if len(hbt.orders(0)) == 0:
                return False
    return True
[20]:
hbt = HashMapMarketDepthBacktest([asset])

submit_and_cancel_order(hbt)

_ = hbt.close()
current_timestamp: 1723161601720000000 , order_id: 1 , order_price: 61649.7 , order_qty: 1.0 , order_status: NEW , order_req: NONE
current_timestamp: 1723161601720000000 , order_id: 1 , order_price: 61649.7 , order_qty: 1.0 , order_status: NEW , order_req: CANCEL
current_timestamp: 1723161601840000000 , order_id: 1 , order_price: 61649.7 , order_qty: 1.0 , order_status: CANCELED , order_req: NONE

成行注文

[21]:
from hftbacktest import MARKET

@njit
def print_orders_exec_price(hbt):
    orders = hbt.orders(0)
    order_values = orders.values()
    while order_values.has_next():
        order = order_values.get()

        order_status = ''
        if order.status == NONE:
            order_status = 'NONE'
        elif order.status == NEW:
            order_status = 'NEW'
        elif order.status == FILLED:
            order_status = 'FILLED'
        elif order.status == CANCELED:
            order_status = 'CANCELED'
        elif order.status == EXPIRED:
            order_status = 'EXPIRED'

        order_req = ''
        if order.req == NONE:
            order_req = 'NONE'
        elif order.req == NEW:
            order_req = 'NEW'
        elif order.req == CANCELED:
            order_req = 'CANCEL'

        print(
            'current_timestamp:', hbt.current_timestamp,
             ', order_id:', order.order_id,
             ', order_price:', np.round(order.price, 1),
             ', order_qty:', order.qty,
             ', order_status:', order_status,
             ', exec_price:', np.round(order.exec_price, 1)
        )

@njit
def market_order(hbt):
    is_order_submitted = False
    while hbt.elapse(60 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        state_values = hbt.state_values(0)

        print(
            'current_timestamp:', hbt.current_timestamp,
             ', position:', hbt.position(0),
             ', balance:', state_values.balance,
             ', fee:', state_values.fee
        )

        if not is_order_submitted:
            depth = hbt.depth(0)

            order_id = 1
            # Sets an arbitrary price, which does not affect MARKET orders.
            order_price = depth.best_bid
            order_qty = 1
            time_in_force = GTC
            order_type = MARKET
            hbt.submit_sell_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            hbt.wait_order_response(0, order_id, 1e9)
            # You can see the order immediately filled.
            # Also you can see the order executed at the best bid which is different from what it was submitted at.
            print('best_bid:', depth.best_bid)
            print_orders_exec_price(hbt)
            is_order_submitted = True
    return True
[22]:
hbt = HashMapMarketDepthBacktest([asset])

market_order(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , position: 0.0 , balance: 0.0 , fee: 0.0
best_bid: 61594.100000000006
current_timestamp: 1723161661520000000 , order_id: 1 , order_price: 61594.1 , order_qty: 1.0 , order_status: FILLED , exec_price: 61594.1
current_timestamp: 1723161721520000000 , order_id: 1 , order_price: 61594.1 , order_qty: 1.0 , order_status: FILLED , order_req: NONE
current_timestamp: 1723161721520000000 , position: -1.0 , balance: 61594.100000000006 , fee: 43.11587
current_timestamp: 1723161781520000000 , position: -1.0 , balance: 61594.100000000006 , fee: 43.11587
current_timestamp: 1723161841520000000 , position: -1.0 , balance: 61594.100000000006 , fee: 43.11587
current_timestamp: 1723161901520000000 , position: -1.0 , balance: 61594.100000000006 , fee: 43.11587

GTX, Post-Only注文

[23]:
from hftbacktest import GTX

@njit
def submit_gtx(hbt):
    is_order_submitted = False
    while hbt.elapse(60 * 1e9) == 0:
        print_orders(hbt)

        hbt.clear_inactive_orders(0)

        state_values = hbt.state_values(0)

        print(
            'current_timestamp:', hbt.current_timestamp,
             ', position:', hbt.position(0),
             ', balance:', state_values.balance,
             ', fee:', state_values.fee
        )

        if not is_order_submitted:
            depth = hbt.depth(0)

            order_id = 1
            # Sets a deep price in the opposite side and it will be rejected by GTX.
            order_price = depth.best_bid - 100 * depth.tick_size
            order_qty = 1
            time_in_force = GTX
            order_type = LIMIT
            hbt.submit_sell_order(0, order_id, order_price, order_qty, time_in_force, order_type, False)
            hbt.wait_order_response(0, order_id, 1e9)
            is_order_submitted = True
    return True
[24]:
hbt = HashMapMarketDepthBacktest([asset])

submit_gtx(hbt)

_ = hbt.close()
current_timestamp: 1723161661500000000 , position: 0.0 , balance: 0.0 , fee: 0.0
current_timestamp: 1723161721520000000 , order_id: 1 , order_price: 61584.1 , order_qty: 1.0 , order_status: EXPIRED , order_req: NONE
current_timestamp: 1723161721520000000 , position: 0.0 , balance: 0.0 , fee: 0.0
current_timestamp: 1723161781520000000 , position: 0.0 , balance: 0.0 , fee: 0.0
current_timestamp: 1723161841520000000 , position: 0.0 , balance: 0.0 , fee: 0.0
current_timestamp: 1723161901520000000 , position: 0.0 , balance: 0.0 , fee: 0.0

BBOのプロット

[25]:
@njit
def plot_bbo(hbt, local_timestamp, best_bid, best_ask):
    while hbt.elapse(1 * 1e9) == 0:
        # Records data points
        local_timestamp.append(hbt.current_timestamp)

        depth = hbt.depth(0)

        best_bid.append(depth.best_bid)
        best_ask.append(depth.best_ask)
    return True
[26]:
# Uses Numba list for njit.
from numba.typed import List
from numba import int64, float64

import polars as pl

local_timestamp = List.empty_list(int64, allocated=10000)
best_bid = List.empty_list(float64, allocated=10000)
best_ask = List.empty_list(float64, allocated=10000)

hbt = HashMapMarketDepthBacktest([asset])

plot_bbo(hbt, local_timestamp, best_bid, best_ask)

hbt.close()

df = pl.DataFrame({'timestamp': local_timestamp, 'best_bid': best_bid, 'best_ask': best_ask})
df = df.with_columns(
    pl.from_epoch('timestamp', time_unit='ns')
)

df.plot(x='timestamp')
[26]:

統計の表示

[27]:
@njit
def submit_order_stats(hbt, recorder):
    buy_order_id = 1
    sell_order_id = 2
    half_spread = 5 * hbt.depth(0).tick_size

    while hbt.elapse(1 * 1e9) == 0:
        hbt.clear_inactive_orders(0)

        depth = hbt.depth(0)

        mid_price = (depth.best_bid + depth.best_ask) / 2.0

        if buy_order_id not in hbt.orders(0):
            order_price = round((mid_price - half_spread) / depth.tick_size) * depth.tick_size
            order_qty = 1
            time_in_force = GTX
            order_type = LIMIT
            hbt.submit_buy_order(0, buy_order_id, order_price, order_qty, time_in_force, order_type, False)
        else:
            hbt.cancel(0, buy_order_id, False)

        if sell_order_id not in hbt.orders(0):
            order_price = round((mid_price + half_spread) / depth.tick_size) * depth.tick_size
            order_qty = 1
            time_in_force = GTX
            order_type = LIMIT
            hbt.submit_sell_order(0, sell_order_id, order_price, order_qty, time_in_force, order_type, False)
        else:
            hbt.cancel(0, sell_order_id, False)

        recorder.record(hbt)
    return True
[28]:
from hftbacktest import Recorder

hbt = HashMapMarketDepthBacktest([asset])

recorder = Recorder(
    # The number of assets
    hbt.num_assets,
    # The buffer size for records
    1000000
)

submit_order_stats(hbt, recorder.recorder)

_ = hbt.close()

記録された状態をgetメソッドを使用してアセット番号と共に取得できます。

[29]:
recorder.get(0)
[29]:
array([(1723161602500000000, 61659.85,  0.,  0.000000e+00,    0.     ,   0,   0.,        0. ),
       (1723161603500000000, 61659.95,  1., -6.165940e+04,   12.33188,   1,   1.,    61659.4),
       (1723161604500000000, 61670.85,  1., -6.165940e+04,   12.33188,   1,   1.,    61659.4),
       (1723161605500000000, 61692.45,  0.,  1.200000e+01,   24.66616,   2,   2.,   123330.8),
       (1723161606500000000, 61693.95,  0.,  1.300000e+01,   49.34312,   4,   4.,   246715.6),
       (1723161607500000000, 61695.45, -1.,  6.170740e+04,   61.682  ,   5,   5.,   308410. ),
       (1723161608500000000, 61709.95, -2.,  1.234033e+05,   74.02118,   6,   6.,   370105.9),
       (1723161609500000000, 61707.35, -1.,  6.169390e+04,   86.36306,   7,   7.,   431815.3),
       (1723161610500000000, 61715.85, -1.,  6.169390e+04,   86.36306,   7,   7.,   431815.3),
       (1723161611500000000, 61711.85, -2.,  1.234103e+05,   98.70634,   8,   8.,   493531.7),
       (1723161612500000000, 61713.95, -3.,  1.851227e+05,  111.04882,   9,   9.,   555244.1),
       (1723161613500000000, 61706.15, -4.,  2.468371e+05,  123.3917 ,  10,  10.,   616958.5),
       (1723161614500000000, 61708.25, -5.,  3.085437e+05,  135.73302,  11,  11.,   678665.1),
       (1723161615500000000, 61699.75, -6.,  3.702525e+05,  148.07478,  12,  12.,   740373.9),
       (1723161616500000000, 61700.95, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161617500000000, 61698.05, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161618500000000, 61706.95, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161619500000000, 61695.85, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161620500000000, 61713.45, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161621500000000, 61707.65, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161622500000000, 61713.45, -7.,  4.319527e+05,  160.41482,  13,  13.,   802074.1),
       (1723161623500000000, 61704.05, -6.,  3.702455e+05,  172.75626,  14,  14.,   863781.3),
       (1723161624500000000, 61702.45, -5.,  3.085419e+05,  185.09698,  15,  15.,   925484.9),
       (1723161625500000000, 61704.65, -6.,  3.702448e+05,  197.43756,  16,  16.,   987187.8),
       (1723161626500000000, 61704.65, -6.,  3.702448e+05,  197.43756,  16,  16.,   987187.8),
       (1723161627500000000, 61695.35, -5.,  3.085406e+05,  209.7784 ,  17,  17.,  1048892. ),
       (1723161628500000000, 61693.75, -4.,  2.468458e+05,  222.11736,  18,  18.,  1110586.8),
       (1723161629500000000, 61693.75, -4.,  2.468458e+05,  222.11736,  18,  18.,  1110586.8),
       (1723161630500000000, 61682.35, -4.,  2.468458e+05,  222.11736,  18,  18.,  1110586.8),
       (1723161631500000000, 61673.85, -3.,  1.851640e+05,  234.45372,  19,  19.,  1172268.6),
       (1723161632500000000, 61666.05, -2.,  1.234906e+05,  246.7884 ,  20,  20.,  1233942. ),
       (1723161633500000000, 61671.05, -2.,  1.234906e+05,  246.7884 ,  20,  20.,  1233942. ),
       (1723161634500000000, 61673.75, -3.,  1.851622e+05,  259.12272,  21,  21.,  1295613.6),
       (1723161635500000000, 61673.75, -3.,  1.851622e+05,  259.12272,  21,  21.,  1295613.6),
       (1723161636500000000, 61666.05, -3.,  1.851622e+05,  259.12272,  21,  21.,  1295613.6),
       (1723161637500000000, 61670.45, -4.,  2.468288e+05,  271.45604,  22,  22.,  1357280.2),
       (1723161638500000000, 61664.05, -4.,  2.468288e+05,  271.45604,  22,  22.,  1357280.2),
       (1723161639500000000, 61649.05, -3.,  1.851652e+05,  283.78876,  23,  23.,  1418943.8),
       (1723161640500000000, 61645.05, -3.,  1.851652e+05,  283.78876,  23,  23.,  1418943.8),
       (1723161641500000000, 61640.05, -2.,  1.235206e+05,  296.11768,  24,  24.,  1480588.4),
       (1723161642500000000, 61638.45, -1.,  6.188100e+04,  308.4456 ,  25,  25.,  1542228. ),
       (1723161643500000000, 61636.05,  0.,  2.431000e+02,  320.77318,  26,  26.,  1603865.9),
       (1723161644500000000, 61641.95, -1.,  6.187970e+04,  333.1005 ,  27,  27.,  1665502.5),
       (1723161645500000000, 61641.95, -1.,  6.187970e+04,  333.1005 ,  27,  27.,  1665502.5),
       (1723161646500000000, 61644.35, -1.,  6.187970e+04,  333.1005 ,  27,  27.,  1665502.5),
       (1723161647500000000, 61636.45, -1.,  6.187970e+04,  333.1005 ,  27,  27.,  1665502.5),
       (1723161648500000000, 61630.05,  0.,  2.438000e+02,  345.42768,  28,  28.,  1727138.4),
       (1723161649500000000, 61630.05,  0.,  2.438000e+02,  345.42768,  28,  28.,  1727138.4),
       (1723161650500000000, 61631.65,  0.,  2.438000e+02,  345.42768,  28,  28.,  1727138.4),
       (1723161651500000000, 61639.05, -1.,  6.187600e+04,  357.75412,  29,  29.,  1788770.6),
       (1723161652500000000, 61632.05, -1.,  6.187600e+04,  357.75412,  29,  29.,  1788770.6),
       (1723161653500000000, 61633.95, -1.,  6.187600e+04,  357.75412,  29,  29.,  1788770.6),
       (1723161654500000000, 61632.05, -2.,  1.235104e+05,  370.081  ,  30,  30.,  1850405. ),
       (1723161655500000000, 61604.05, -1.,  6.187880e+04,  382.40732,  31,  31.,  1912036.6),
       (1723161656500000000, 61604.05, -1.,  6.187880e+04,  382.40732,  31,  31.,  1912036.6),
       (1723161657500000000, 61607.05, -1.,  6.187880e+04,  382.40732,  31,  31.,  1912036.6),
       (1723161658500000000, 61603.15,  0.,  2.722000e+02,  394.72864,  32,  32.,  1973643.2),
       (1723161659500000000, 61601.15,  1., -6.133040e+04,  407.04916,  33,  33.,  2035245.8),
       (1723161660500000000, 61595.35,  2., -1.229310e+05,  419.36928,  34,  34.,  2096846.4),
       (1723161661500000000, 61594.15,  3., -1.845258e+05,  431.68824,  35,  35.,  2158441.2),
       (1723161662500000000, 61578.15,  4., -2.461194e+05,  444.00696,  36,  36.,  2220034.8),
       (1723161663500000000, 61565.25,  5., -3.076970e+05,  456.32248,  37,  37.,  2281612.4),
       (1723161664500000000, 61563.65,  5., -3.076960e+05,  480.9486 ,  39,  39.,  2404743. ),
       (1723161665500000000, 61555.05,  6., -3.692592e+05,  493.26124,  40,  40.,  2466306.2),
       (1723161666500000000, 61530.85,  7., -4.308138e+05,  505.57216,  41,  41.,  2527860.8),
       (1723161667500000000, 61522.25,  8., -4.923442e+05,  517.87824,  42,  42.,  2589391.2),
       (1723161668500000000, 61543.  ,  7., -4.308214e+05,  530.1828 ,  43,  43.,  2650914. ),
       (1723161669500000000, 61528.05,  7., -4.308214e+05,  530.1828 ,  43,  43.,  2650914. ),
       (1723161670500000000, 61539.85,  8., -4.923490e+05,  542.48832,  44,  44.,  2712441.6),
       (1723161671500000000, 61524.15,  9., -5.538884e+05,  554.7962 ,  45,  45.,  2773981. ),
       (1723161672500000000, 61524.25,  9., -5.538884e+05,  554.7962 ,  45,  45.,  2773981. ),
       (1723161673500000000, 61535.95,  8., -4.923636e+05,  567.10116,  46,  46.,  2835505.8),
       (1723161674500000000, 61531.45,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161675500000000, 61538.85,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161676500000000, 61536.95,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161677500000000, 61538.85,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161678500000000, 61534.75,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161679500000000, 61538.85,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161680500000000, 61538.05,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161681500000000, 61549.25,  9., -5.538990e+05,  579.40824,  47,  47.,  2897041.2),
       (1723161682500000000, 61552.45,  8., -4.923492e+05,  591.7182 ,  48,  48.,  2958591. ),
       (1723161683500000000, 61552.45,  8., -4.923492e+05,  591.7182 ,  48,  48.,  2958591. ),
       (1723161684500000000, 61552.45,  8., -4.923492e+05,  591.7182 ,  48,  48.,  2958591. ),
       (1723161685500000000, 61565.95,  7., -4.307963e+05,  604.02878,  49,  49.,  3020143.9),
       (1723161686500000000, 61574.45,  6., -3.692299e+05,  616.34206,  50,  50.,  3081710.3),
       (1723161687500000000, 61587.55,  6., -3.692299e+05,  616.34206,  50,  50.,  3081710.3),
       (1723161688500000000, 61592.95,  5., -3.076419e+05,  628.65966,  51,  51.,  3143298.3),
       (1723161689500000000, 61592.95,  5., -3.076419e+05,  628.65966,  51,  51.,  3143298.3),
       (1723161690500000000, 61594.15,  5., -3.076419e+05,  628.65966,  51,  51.,  3143298.3),
       (1723161691500000000, 61598.95,  4., -2.460473e+05,  640.97858,  52,  52.,  3204892.9),
       (1723161692500000000, 61593.05,  3., -1.844479e+05,  653.29846,  53,  53.,  3266492.3),
       (1723161693500000000, 61582.55,  3., -1.844479e+05,  653.29846,  53,  53.,  3266492.3),
       (1723161694500000000, 61582.55,  4., -2.460299e+05,  665.61486,  54,  54.,  3328074.3),
       (1723161695500000000, 61582.55,  4., -2.460299e+05,  665.61486,  54,  54.,  3328074.3),
       (1723161696500000000, 61587.15,  4., -2.460299e+05,  665.61486,  54,  54.,  3328074.3),
       (1723161697500000000, 61587.15,  4., -2.460299e+05,  665.61486,  54,  54.,  3328074.3),
       (1723161698500000000, 61588.75,  4., -2.460299e+05,  665.61486,  54,  54.,  3328074.3),
       (1723161699500000000, 61586.75,  4., -2.460289e+05,  690.25034,  56,  56.,  3451251.7),
       (1723161700500000000, 61582.05,  5., -3.076151e+05,  702.56758,  57,  57.,  3512837.9),
       (1723161701500000000, 61572.05,  6., -3.691967e+05,  714.8839 ,  58,  58.,  3574419.5),
       (1723161702500000000, 61587.45,  5., -3.076241e+05,  727.19842,  59,  59.,  3635992.1),
       (1723161703500000000, 61577.95,  5., -3.076241e+05,  727.19842,  59,  59.,  3635992.1),
       (1723161704500000000, 61582.05,  5., -3.076241e+05,  727.19842,  59,  59.,  3635992.1),
       (1723161705500000000, 61572.05,  5., -3.076189e+05,  751.83042,  61,  61.,  3759152.1),
       (1723161706500000000, 61574.05,  4., -2.460463e+05,  764.14494,  62,  62.,  3820724.7),
       (1723161707500000000, 61574.05,  4., -2.460463e+05,  764.14494,  62,  62.,  3820724.7),
       (1723161708500000000, 61576.05,  3., -1.844717e+05,  776.45986,  63,  63.,  3882299.3),
       (1723161709500000000, 61577.55,  2., -1.228951e+05,  788.77518,  64,  64.,  3943875.9),
       (1723161710500000000, 61581.95,  1., -6.131710e+04,  801.09078,  65,  65.,  4005453.9),
       (1723161711500000000, 61565.65,  1., -6.131710e+04,  801.09078,  65,  65.,  4005453.9),
       (1723161712500000000, 61561.15,  2., -1.228823e+05,  813.40382,  66,  66.,  4067019.1),
       (1723161713500000000, 61570.45,  2., -1.228813e+05,  838.02826,  68,  68.,  4190141.3),
       (1723161714500000000, 61572.45,  1., -6.131040e+04,  850.34244,  69,  69.,  4251712.2),
       (1723161715500000000, 61565.65,  1., -6.131040e+04,  850.34244,  69,  69.,  4251712.2),
       (1723161716500000000, 61561.95,  2., -1.228756e+05,  862.65548,  70,  70.,  4313277.4),
       (1723161717500000000, 61557.05,  3., -1.844370e+05,  874.96776,  71,  71.,  4374838.8),
       (1723161718500000000, 61561.95,  3., -1.844370e+05,  874.96776,  71,  71.,  4374838.8),
       (1723161719500000000, 61568.05,  2., -1.228746e+05,  887.28024,  72,  72.,  4436401.2),
       (1723161720500000000, 61576.55,  1., -6.130600e+04,  899.59396,  73,  73.,  4497969.8),
       (1723161721500000000, 61576.55,  1., -6.130600e+04,  899.59396,  73,  73.,  4497969.8),
       (1723161722500000000, 61589.95,  1., -6.130600e+04,  899.59396,  73,  73.,  4497969.8),
       (1723161723500000000, 61593.95,  0.,  2.844000e+02,  911.91204,  74,  74.,  4559560.2),
       (1723161724500000000, 61615.15, -1.,  6.187880e+04,  924.23092,  75,  75.,  4621154.6),
       (1723161725500000000, 61615.15, -1.,  6.187880e+04,  924.23092,  75,  75.,  4621154.6),
       (1723161726500000000, 61615.15, -1.,  6.187880e+04,  924.23092,  75,  75.,  4621154.6),
       (1723161727500000000, 61617.05, -2.,  1.234944e+05,  936.55404,  76,  76.,  4682770.2),
       (1723161728500000000, 61618.15, -3.,  1.851120e+05,  948.87756,  77,  77.,  4744387.8),
       (1723161729500000000, 61612.55, -3.,  1.851120e+05,  948.87756,  77,  77.,  4744387.8),
       (1723161730500000000, 61609.95, -2.,  1.235000e+05,  961.19996,  78,  78.,  4805999.8),
       (1723161731500000000, 61607.95, -1.,  6.189060e+04,  973.52184,  79,  79.,  4867609.2),
       (1723161732500000000, 61608.95, -1.,  6.189060e+04,  973.52184,  79,  79.,  4867609.2),
       (1723161733500000000, 61606.05, -1.,  6.189060e+04,  973.52184,  79,  79.,  4867609.2),
       (1723161734500000000, 61608.45, -1.,  6.189060e+04,  973.52184,  79,  79.,  4867609.2),
       (1723161735500000000, 61615.95, -2.,  1.234995e+05,  985.84362,  80,  80.,  4929218.1),
       (1723161736500000000, 61618.15, -3.,  1.851159e+05,  998.1669 ,  81,  81.,  4990834.5),
       (1723161737500000000, 61605.55, -3.,  1.851159e+05,  998.1669 ,  81,  81.,  4990834.5),
       (1723161738500000000, 61613.85, -3.,  1.851159e+05,  998.1669 ,  81,  81.,  4990834.5),
       (1723161739500000000, 61619.95, -4.,  2.467303e+05, 1010.48978,  82,  82.,  5052448.9),
       (1723161740500000000, 61636.65, -4.,  2.467303e+05, 1010.48978,  82,  82.,  5052448.9),
       (1723161741500000000, 61649.75, -5.,  3.083675e+05, 1022.81722,  83,  83.,  5114086.1),
       (1723161742500000000, 61653.45, -6.,  3.700177e+05, 1035.14726,  84,  84.,  5175736.3),
       (1723161743500000000, 61668.55, -7.,  4.316716e+05, 1047.47804,  85,  85.,  5237390.2),
       (1723161744500000000, 61668.55, -7.,  4.316716e+05, 1047.47804,  85,  85.,  5237390.2),
       (1723161745500000000, 61673.45, -6.,  3.700036e+05, 1059.81164,  86,  86.,  5299058.2),
       (1723161746500000000, 61675.55, -7.,  4.316775e+05, 1072.14642,  87,  87.,  5360732.1),
       (1723161747500000000, 61671.35, -8.,  4.933535e+05, 1084.48162,  88,  88.,  5422408.1),
       (1723161748500000000, 61656.75, -7.,  4.316827e+05, 1096.81578,  89,  89.,  5484078.9),
       (1723161749500000000, 61660.05, -7.,  4.316827e+05, 1096.81578,  89,  89.,  5484078.9),
       (1723161750500000000, 61662.05, -8.,  4.933433e+05, 1109.1479 ,  90,  90.,  5545739.5),
       (1723161751500000000, 61652.05, -7.,  4.316817e+05, 1121.48022,  91,  91.,  5607401.1),
       (1723161752500000000, 61673.45, -7.,  4.316817e+05, 1121.48022,  91,  91.,  5607401.1),
       (1723161753500000000, 61680.65, -8.,  4.933556e+05, 1133.815  ,  92,  92.,  5669075. ),
       (1723161754500000000, 61672.45, -7.,  4.316754e+05, 1146.15104,  93,  93.,  5730755.2),
       (1723161755500000000, 61659.95, -6.,  3.700035e+05, 1158.48542,  94,  94.,  5792427.1),
       (1723161756500000000, 61661.25, -7.,  4.316639e+05, 1170.8175 ,  95,  95.,  5854087.5),
       (1723161757500000000, 61654.25, -7.,  4.316639e+05, 1170.8175 ,  95,  95.,  5854087.5),
       (1723161758500000000, 61650.05, -6.,  3.700101e+05, 1183.14826,  96,  96.,  5915741.3),
       (1723161759500000000, 61650.05, -6.,  3.700101e+05, 1183.14826,  96,  96.,  5915741.3),
       (1723161760500000000, 61654.25, -6.,  3.700101e+05, 1183.14826,  96,  96.,  5915741.3),
       (1723161761500000000, 61652.65, -5.,  3.083563e+05, 1195.47902,  97,  97.,  5977395.1),
       (1723161762500000000, 61663.95, -5.,  3.083563e+05, 1195.47902,  97,  97.,  5977395.1),
       (1723161763500000000, 61656.05, -5.,  3.083563e+05, 1195.47902,  97,  97.,  5977395.1),
       (1723161764500000000, 61656.05, -6.,  3.700129e+05, 1207.81034,  98,  98.,  6039051.7),
       (1723161765500000000, 61626.35, -6.,  3.700129e+05, 1207.81034,  98,  98.,  6039051.7),
       (1723161766500000000, 61629.85, -6.,  3.700129e+05, 1207.81034,  98,  98.,  6039051.7),
       (1723161767500000000, 61629.85, -6.,  3.700129e+05, 1207.81034,  98,  98.,  6039051.7),
       (1723161768500000000, 61633.05, -6.,  3.700129e+05, 1207.81034,  98,  98.,  6039051.7),
       (1723161769500000000, 61645.45, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161770500000000, 61645.45, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161771500000000, 61649.75, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161772500000000, 61640.85, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161773500000000, 61642.05, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161774500000000, 61629.85, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161775500000000, 61629.75, -7.,  4.316465e+05, 1220.13706,  99,  99.,  6100685.3),
       (1723161776500000000, 61635.25, -8.,  4.932767e+05, 1232.4631 , 100, 100.,  6162315.5),
       (1723161777500000000, 61618.75, -7.,  4.316419e+05, 1244.79006, 101, 101.,  6223950.3),
       (1723161778500000000, 61615.75, -6.,  3.700237e+05, 1257.1137 , 102, 102.,  6285568.5),
       (1723161779500000000, 61602.7 , -5.,  3.084085e+05, 1269.43674, 103, 103.,  6347183.7),
       (1723161780500000000, 61609.75, -4.,  2.468063e+05, 1281.75718, 104, 104.,  6408785.9),
       (1723161781500000000, 61629.65, -5.,  3.084165e+05, 1294.07922, 105, 105.,  6470396.1),
       (1723161782500000000, 61634.15, -6.,  3.700467e+05, 1306.40526, 106, 106.,  6532026.3),
       (1723161783500000000, 61631.95, -5.,  3.084131e+05, 1318.73198, 107, 107.,  6593659.9),
       (1723161784500000000, 61625.55, -4.,  2.467817e+05, 1331.05826, 108, 108.,  6655291.3),
       (1723161785500000000, 61617.05, -3.,  1.851567e+05, 1343.38326, 109, 109.,  6716916.3),
       (1723161786500000000, 61620.05, -2.,  1.235401e+05, 1355.70658, 110, 110.,  6778532.9),
       (1723161787500000000, 61620.05, -2.,  1.235401e+05, 1355.70658, 110, 110.,  6778532.9),
       (1723161788500000000, 61620.05, -2.,  1.235401e+05, 1355.70658, 110, 110.,  6778532.9),
       (1723161789500000000, 61617.05, -1.,  6.192050e+04, 1368.0305 , 111, 111.,  6840152.5),
       (1723161790500000000, 61616.15,  0.,  3.039000e+02, 1380.35382, 112, 112.,  6901769.1),
       (1723161791500000000, 61616.15,  0.,  3.039000e+02, 1380.35382, 112, 112.,  6901769.1),
       (1723161792500000000, 61618.05,  0.,  3.039000e+02, 1380.35382, 112, 112.,  6901769.1),
       (1723161793500000000, 61642.05, -1.,  6.192250e+04, 1392.67754, 113, 113.,  6963387.7),
       (1723161794500000000, 61649.95, -2.,  1.235651e+05, 1405.00606, 114, 114.,  7025030.3),
       (1723161795500000000, 61666.45, -3.,  1.852155e+05, 1417.33614, 115, 115.,  7086680.7),
       (1723161796500000000, 61658.05, -3.,  1.852155e+05, 1417.33614, 115, 115.,  7086680.7),
       (1723161797500000000, 61648.45, -2.,  1.235579e+05, 1429.66766, 116, 116.,  7148338.3),
       (1723161798500000000, 61642.05, -2.,  1.235589e+05, 1454.32702, 118, 118.,  7271635.1),
       (1723161799500000000, 61638.85, -1.,  6.191730e+04, 1466.65534, 119, 119.,  7333276.7),
       (1723161800500000000, 61631.95,  0.,  2.789000e+02, 1478.98302, 120, 120.,  7394915.1),
       (1723161801500000000, 61623.05,  1., -6.135250e+04, 1491.3093 , 121, 121.,  7456546.5),
       (1723161802500000000, 61626.65,  1., -6.135250e+04, 1491.3093 , 121, 121.,  7456546.5),
       (1723161803500000000, 61625.05,  1., -6.135250e+04, 1491.3093 , 121, 121.,  7456546.5),
       (1723161804500000000, 61612.05,  2., -1.229771e+05, 1503.63422, 122, 122.,  7518171.1),
       (1723161805500000000, 61618.05,  1., -6.136450e+04, 1515.95674, 123, 123.,  7579783.7),
       (1723161806500000000, 61616.15,  1., -6.136450e+04, 1515.95674, 123, 123.,  7579783.7),
       (1723161807500000000, 61616.15,  1., -6.136450e+04, 1515.95674, 123, 123.,  7579783.7),
       (1723161808500000000, 61602.45,  1., -6.136450e+04, 1515.95674, 123, 123.,  7579783.7),
       (1723161809500000000, 61592.05,  2., -1.229664e+05, 1528.27712, 124, 124.,  7641385.6),
       (1723161810500000000, 61580.25,  3., -1.845580e+05, 1540.59544, 125, 125.,  7702977.2),
       (1723161811500000000, 61580.25,  3., -1.845580e+05, 1540.59544, 125, 125.,  7702977.2),
       (1723161812500000000, 61586.25,  2., -1.229772e+05, 1552.9116 , 126, 126.,  7764558. ),
       (1723161813500000000, 61594.45,  1., -6.139040e+04, 1565.22896, 127, 127.,  7826144.8),
       (1723161814500000000, 61606.85,  0.,  2.045000e+02, 1577.54794, 128, 128.,  7887739.7),
       (1723161815500000000, 61630.35, -1.,  6.181190e+04, 1589.86942, 129, 129.,  7949347.1),
       (1723161816500000000, 61638.05, -2.,  1.234427e+05, 1602.19558, 130, 130.,  8010977.9),
       (1723161817500000000, 61626.25, -2.,  1.234427e+05, 1602.19558, 130, 130.,  8010977.9),
       (1723161818500000000, 61626.25, -2.,  1.234427e+05, 1602.19558, 130, 130.,  8010977.9),
       (1723161819500000000, 61613.65, -2.,  1.234427e+05, 1602.19558, 130, 130.,  8010977.9),
       (1723161820500000000, 61608.15, -1.,  6.182950e+04, 1614.51822, 131, 131.,  8072591.1),
       (1723161821500000000, 61624.65, -2.,  1.234381e+05, 1626.83994, 132, 132.,  8134199.7),
       (1723161822500000000, 61624.65, -2.,  1.234381e+05, 1626.83994, 132, 132.,  8134199.7),
       (1723161823500000000, 61624.65, -2.,  1.234381e+05, 1626.83994, 132, 132.,  8134199.7),
       (1723161824500000000, 61624.65, -2.,  1.234381e+05, 1626.83994, 132, 132.,  8134199.7),
       (1723161825500000000, 61622.55, -1.,  6.181390e+04, 1639.16478, 133, 133.,  8195823.9),
       (1723161826500000000, 61622.55, -1.,  6.181390e+04, 1639.16478, 133, 133.,  8195823.9),
       (1723161827500000000, 61621.65, -1.,  6.181390e+04, 1639.16478, 133, 133.,  8195823.9),
       (1723161828500000000, 61615.95,  0.,  1.927000e+02, 1651.48902, 134, 134.,  8257445.1),
       (1723161829500000000, 61621.55,  1., -6.142270e+04, 1663.8121 , 135, 135.,  8319060.5),
       (1723161830500000000, 61621.55,  1., -6.142270e+04, 1663.8121 , 135, 135.,  8319060.5),
       (1723161831500000000, 61614.05,  1., -6.142270e+04, 1663.8121 , 135, 135.,  8319060.5),
       (1723161832500000000, 61611.55,  2., -1.230363e+05, 1676.13482, 136, 136.,  8380674.1),
       (1723161833500000000, 61620.05,  2., -1.230363e+05, 1676.13482, 136, 136.,  8380674.1),
       (1723161834500000000, 61622.55,  1., -6.141570e+04, 1688.45894, 137, 137.,  8442294.7),
       (1723161835500000000, 61621.55,  1., -6.141470e+04, 1713.10794, 139, 139.,  8565539.7),
       (1723161836500000000, 61630.35,  0.,  2.073000e+02, 1725.43234, 140, 140.,  8627161.7),
       (1723161837500000000, 61613.75, -1.,  6.183810e+04, 1737.7585 , 141, 141.,  8688792.5),
       (1723161838500000000, 61613.75, -1.,  6.183810e+04, 1737.7585 , 141, 141.,  8688792.5),
       (1723161839500000000, 61605.05, -1.,  6.183810e+04, 1737.7585 , 141, 141.,  8688792.5),
       (1723161840500000000, 61616.05, -2.,  1.234437e+05, 1750.07962, 142, 142.,  8750398.1),
       (1723161841500000000, 61621.55, -3.,  1.850603e+05, 1762.40294, 143, 143.,  8812014.7),
       (1723161842500000000, 61633.95, -4.,  2.466823e+05, 1774.72734, 144, 144.,  8873636.7),
       (1723161843500000000, 61638.05, -5.,  3.083167e+05, 1787.05422, 145, 145.,  8935271.1),
       (1723161844500000000, 61634.95, -4.,  2.466791e+05, 1799.38174, 146, 146.,  8996908.7),
       (1723161845500000000, 61634.95, -4.,  2.466791e+05, 1799.38174, 146, 146.,  8996908.7),
       (1723161846500000000, 61638.05, -5.,  3.083145e+05, 1811.70882, 147, 147.,  9058544.1),
       (1723161847500000000, 61634.95, -5.,  3.083155e+05, 1836.36406, 149, 149.,  9181820.3),
       (1723161848500000000, 61626.05, -4.,  2.466811e+05, 1848.69094, 150, 150.,  9243454.7),
       (1723161849500000000, 61629.95, -4.,  2.466811e+05, 1848.69094, 150, 150.,  9243454.7),
       (1723161850500000000, 61629.95, -4.,  2.466811e+05, 1848.69094, 150, 150.,  9243454.7),
       (1723161851500000000, 61632.25, -4.,  2.466811e+05, 1848.69094, 150, 150.,  9243454.7),
       (1723161852500000000, 61635.95, -5.,  3.083139e+05, 1861.0175 , 151, 151.,  9305087.5),
       (1723161853500000000, 61635.95, -5.,  3.083139e+05, 1861.0175 , 151, 151.,  9305087.5),
       (1723161854500000000, 61638.05, -5.,  3.083139e+05, 1861.0175 , 151, 151.,  9305087.5),
       (1723161855500000000, 61636.25, -4.,  2.466763e+05, 1873.34502, 152, 152.,  9366725.1),
       (1723161856500000000, 61638.05, -4.,  2.466763e+05, 1873.34502, 152, 152.,  9366725.1),
       (1723161857500000000, 61636.05, -5.,  3.083149e+05, 1885.67274, 153, 153.,  9428363.7),
       (1723161858500000000, 61641.45, -6.,  3.699515e+05, 1898.00006, 154, 154.,  9490000.3),
       (1723161859500000000, 61641.45, -6.,  3.699515e+05, 1898.00006, 154, 154.,  9490000.3),
       (1723161860500000000, 61643.25, -6.,  3.699515e+05, 1898.00006, 154, 154.,  9490000.3),
       (1723161861500000000, 61657.25, -7.,  4.315953e+05, 1910.32882, 155, 155.,  9551644.1),
       (1723161862500000000, 61671.45, -8.,  4.932531e+05, 1922.66038, 156, 156.,  9613301.9),
       (1723161863500000000, 61668.05, -8.,  4.932531e+05, 1922.66038, 156, 156.,  9613301.9),
       (1723161864500000000, 61669.15, -8.,  4.932531e+05, 1922.66038, 156, 156.,  9613301.9),
       (1723161865500000000, 61666.75, -8.,  4.932531e+05, 1922.66038, 156, 156.,  9613301.9),
       (1723161866500000000, 61665.05, -7.,  4.315869e+05, 1934.99362, 157, 157.,  9674968.1),
       (1723161867500000000, 61657.15, -6.,  3.699223e+05, 1947.32654, 158, 158.,  9736632.7),
       (1723161868500000000, 61657.15, -6.,  3.699223e+05, 1947.32654, 158, 158.,  9736632.7),
       (1723161869500000000, 61657.15, -6.,  3.699223e+05, 1947.32654, 158, 158.,  9736632.7),
       (1723161870500000000, 61657.15, -6.,  3.699223e+05, 1947.32654, 158, 158.,  9736632.7),
       (1723161871500000000, 61666.75, -7.,  4.315799e+05, 1959.65806, 159, 159.,  9798290.3),
       (1723161872500000000, 61651.55, -6.,  3.699137e+05, 1971.9913 , 160, 160.,  9859956.5),
       (1723161873500000000, 61638.05, -5.,  3.082627e+05, 1984.3215 , 161, 161.,  9921607.5),
       (1723161874500000000, 61634.35, -4.,  2.466251e+05, 1996.64902, 162, 162.,  9983245.1),
       (1723161875500000000, 61638.85, -4.,  2.466251e+05, 1996.64902, 162, 162.,  9983245.1),
       (1723161876500000000, 61638.15, -5.,  3.082645e+05, 2008.9769 , 163, 163., 10044884.5),
       (1723161877500000000, 61621.65, -4.,  2.466269e+05, 2021.30442, 164, 164., 10106522.1),
       (1723161878500000000, 61611.65, -3.,  1.850057e+05, 2033.62866, 165, 165., 10168143.3),
       (1723161879500000000, 61614.95, -4.,  2.466179e+05, 2045.9511 , 166, 166., 10229755.5),
       (1723161880500000000, 61614.15, -4.,  2.466179e+05, 2045.9511 , 166, 166., 10229755.5),
       (1723161881500000000, 61614.15, -4.,  2.466179e+05, 2045.9511 , 166, 166., 10229755.5),
       (1723161882500000000, 61614.15, -4.,  2.466179e+05, 2045.9511 , 166, 166., 10229755.5),
       (1723161883500000000, 61616.15, -4.,  2.466179e+05, 2045.9511 , 166, 166., 10229755.5),
       (1723161884500000000, 61623.95, -5.,  3.082345e+05, 2058.27442, 167, 167., 10291372.1),
       (1723161885500000000, 61627.95, -6.,  3.698589e+05, 2070.5993 , 168, 168., 10352996.5),
       (1723161886500000000, 61621.45, -6.,  3.698589e+05, 2070.5993 , 168, 168., 10352996.5),
       (1723161887500000000, 61620.45, -5.,  3.082380e+05, 2082.92348, 169, 169., 10414617.4),
       (1723161888500000000, 61617.55, -4.,  2.466181e+05, 2095.24746, 170, 170., 10476237.3),
       (1723161889500000000, 61609.45, -3.,  1.850011e+05, 2107.57086, 171, 171., 10537854.3),
       (1723161890500000000, 61609.45, -3.,  1.850011e+05, 2107.57086, 171, 171., 10537854.3),
       (1723161891500000000, 61605.95, -3.,  1.850011e+05, 2107.57086, 171, 171., 10537854.3),
       (1723161892500000000, 61605.95, -3.,  1.850011e+05, 2107.57086, 171, 171., 10537854.3),
       (1723161893500000000, 61596.55, -3.,  1.850011e+05, 2107.57086, 171, 171., 10537854.3),
       (1723161894500000000, 61595.65, -2.,  1.234051e+05, 2119.89006, 172, 172., 10599450.3),
       (1723161895500000000, 61580.75, -1.,  6.180990e+04, 2132.2091 , 173, 173., 10661045.5),
       (1723161896500000000, 61575.05,  0.,  2.297000e+02, 2144.52514, 174, 174., 10722625.7),
       (1723161897500000000, 61585.05,  0.,  2.297000e+02, 2144.52514, 174, 174., 10722625.7),
       (1723161898500000000, 61578.25,  0.,  2.297000e+02, 2144.52514, 174, 174., 10722625.7),
       (1723161899500000000, 61578.25,  0.,  2.297000e+02, 2144.52514, 174, 174., 10722625.7),
       (1723161900500000000, 61583.95, -1.,  6.180850e+04, 2156.8409 , 175, 175., 10784204.5),
       (1723161901500000000, 61583.95, -1.,  6.180850e+04, 2156.8409 , 175, 175., 10784204.5),
       (1723161902500000000, 61583.95, -1.,  6.180850e+04, 2156.8409 , 175, 175., 10784204.5),
       (1723161903500000000, 61585.05, -2.,  1.233929e+05, 2169.15778, 176, 176., 10845788.9)],
      dtype={'names': ['timestamp', 'price', 'position', 'balance', 'fee', 'num_trades', 'trading_volume', 'trading_value'], 'formats': ['<i8', '<f8', '<f8', '<f8', '<f8', '<i8', '<f8', '<f8'], 'offsets': [0, 8, 16, 24, 32, 40, 48, 56], 'itemsize': 64, 'aligned': True})

さらに、to_npzメソッドはすべての記録をnpzファイルに保存し、アセット番号をデータのキーとして使用します。

[30]:
recorder.to_npz('example_record.npz')

HftBacktestは、記録に基づいたパフォーマンスレポートツールも提供しています。詳細については、こちらをご覧ください。

[31]:
from hftbacktest.stats import LinearAssetRecord

# Constructs the LinearAssetRecord from the recorded data.
record = LinearAssetRecord(recorder.get(0))

# Generates the statistics.
# You can generate monthly and daily statistics, as well as custom metrics.
stats = record.stats()

# Prints the summary.
stats.summary()
[31]:
shape: (1, 11)
startendSRSortinoReturnMaxDrawdownDailyNumberOfTradesDailyTradingValueReturnOverMDDReturnOverTradeMaxPositionValue
datetime[μs]datetime[μs]f64f64f64f64f64f64f64f64f64
2024-08-09 00:00:002024-08-09 00:05:00-624.497686-664.628958-1846.544721902.1877850688.03.1236e9-0.970748-0.00017553849.65
[32]:
stats.plot()
../_images/tutorials_Getting_Started_53_0.png

Holoviewsを使用したBokehもサポートされています。

[33]:
import holoviews as hv
hv.extension('bokeh')

stats.plot(backend='holoviews')
[33]: