The order throttle mechanism drops messages if they exceed a predetermined threshold as expected. When the message rate becomes too high, it starts to drop messages. When the order rate goes down, the throttler keeps dropping orders.
Expected Behavior
The throttler should not drop messages if nothing has happened for x seconds.
Actual Behavior
Steps to Reproduce the Problem
from decimal import Decimal
from nautilus_trader.backtest.engine import BacktestEngine, BacktestEngineConfig
from nautilus_trader.common.component import init_logging
from nautilus_trader.common.enums import LogLevel
from nautilus_trader.model.currencies import BTC, USDT
from nautilus_trader.model.data import QuoteTick
from nautilus_trader.model.enums import (
AccountType,
OmsType,
OrderSide,
TimeInForce,
)
from nautilus_trader.model.identifiers import InstrumentId, Symbol, TraderId, Venue
from nautilus_trader.model.instruments import CurrencyPair
from nautilus_trader.model.objects import Money, Price, Quantity
from nautilus_trader.trading.strategy import Strategy
class TestStrategy(Strategy):
def __init__(self, instrument):
super().__init__()
self.instrument = instrument
def on_start(self) -> None:
self.subscribe_quote_ticks(instrument_id=self.instrument.id)
def on_stop(self):
self.cancel_all_orders(self.instrument.id)
self.close_all_positions(self.instrument.id)
self.unsubscribe_quote_ticks(self.instrument.id)
def on_quote_tick(self, tick):
self.cancel_all_orders(self.instrument.id)
order = self.order_factory.limit(
instrument_id=self.instrument.id,
order_side=OrderSide.BUY,
price=self.instrument.make_price(1000),
quantity=self.instrument.make_qty(1),
post_only=True,
time_in_force=TimeInForce.GTC,
)
self.submit_order(order)
def main():
"""Run the test."""
init_logging(level_stdout=LogLevel.DEBUG, level_file=LogLevel.DEBUG)
instrument = CurrencyPair(
instrument_id=InstrumentId(
symbol=Symbol("BTCUSDT"),
venue=Venue("BINANCE"),
),
raw_symbol=Symbol("BTCUSDT"),
base_currency=BTC,
quote_currency=USDT,
price_precision=2,
size_precision=6,
price_increment=Price(1e-02, precision=2),
size_increment=Quantity(1e-06, precision=6),
lot_size=None,
max_quantity=Quantity(9000, precision=6),
min_quantity=Quantity(1e-06, precision=6),
max_notional=None,
min_notional=Money(10.00000000, USDT),
max_price=Price(1000000, precision=2),
min_price=Price(0.01, precision=2),
margin_init=Decimal(1),
margin_maint=Decimal(1),
maker_fee=Decimal("0.00075"),
taker_fee=Decimal("0.00075"),
ts_event=0,
ts_init=0,
)
config = BacktestEngineConfig(trader_id=TraderId("BACKTESTER-001"))
engine = BacktestEngine(config=config)
engine.add_venue(
venue=Venue("BINANCE"),
oms_type=OmsType.NETTING,
account_type=AccountType.MARGIN, # Spot CASH account (not for perpetuals or futures)
base_currency=None, # Multi-currency account
starting_balances=[Money(1_000_000, USDT)],
)
# Add instrument(s)
engine.add_instrument(instrument)
# Add data
quote_ticks = []
for i in range(105):
quote_tick = QuoteTick(
instrument_id=instrument.id,
bid_price=instrument.make_price(1000),
ask_price=instrument.make_price(1001),
bid_size=instrument.make_qty(1),
ask_size=instrument.make_qty(1),
ts_event=1695604690000000312 + i * 1_000_000,
ts_init=1695604690000000312 + i * 1_000_000,
)
quote_ticks.append(quote_tick)
for i in range(105):
quote_tick = QuoteTick(
instrument_id=instrument.id,
bid_price=instrument.make_price(1000),
ask_price=instrument.make_price(1001),
bid_size=instrument.make_qty(1),
ask_size=instrument.make_qty(1),
ts_event=1695604690000000312 + 5604690000000312 + i * 1_000_000,
ts_init=1695604690000000312 + 5604690000000312 + i * 1_000_000,
)
quote_ticks.append(quote_tick)
for i in range(20):
quote_tick = QuoteTick(
instrument_id=instrument.id,
bid_price=instrument.make_price(1000),
ask_price=instrument.make_price(1001),
bid_size=instrument.make_qty(1),
ask_size=instrument.make_qty(1),
ts_event=1695604690000000312 + 2 * 5604690000000312 + i * 1_000_000,
ts_init=1695604690000000312 + 2 * 5604690000000312 + i * 1_000_000,
)
quote_ticks.append(quote_tick)
engine.add_data(quote_ticks)
strategy = TestStrategy(instrument=instrument)
engine.add_strategy(strategy=strategy)
engine.run()
if __name__ == "__main__":
main()
Bug Report
The order throttle mechanism drops messages if they exceed a predetermined threshold as expected. When the message rate becomes too high, it starts to drop messages. When the order rate goes down, the throttler keeps dropping orders.
Expected Behavior
The throttler should not drop messages if nothing has happened for x seconds.
Actual Behavior
Steps to Reproduce the Problem
Specifications
nautilus_trader
version: 1.188.0