Skip to content

Processing TradeTick from bar fails in backtest if bar.volume / 4 and instrument.size_increment both evaluate to < 1 #2275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
miller-moore opened this issue Feb 1, 2025 · 10 comments
Assignees
Labels
bug Something isn't working

Comments

@miller-moore
Copy link
Contributor

miller-moore commented Feb 1, 2025

Bug Report

When the order matching engine processes a trade tick from a bar with a small volume and the instrument size increment is less than 1, the creation of TradeTick fails on Condition.positive_int error because TradeTick enforces size to be a positive int.

Expected Behavior

Take max(bar.volume / 4, instrument.size_increment, 1) instead of just max(bar.volume / 4, instrument.size_increment):

cdef double size_value = max(bar.volume.as_double() / 4.0, self.instrument.size_increment.as_double())

Actual Behavior

Sometimes the bar.volume / 4 combined with instrument.size_increment < 1 results in a float trade tick size of < 1, leading to the Condition.positive_int error on size.

Steps to Reproduce the Problem

  1. Create a bar whose volume is less than 4 and whose instrument.size_increment < 1
  2. Run a backtest with this bar
  3. See the error thrown by Condition.positive_int

Specifications

  • OS platform: MacOS 15.1
  • Python version: 3.12
  • nautilus_trader version: 1.211.0
@miller-moore miller-moore added the bug Something isn't working label Feb 1, 2025
@miller-moore miller-moore changed the title Processing TradeTick from bar fails in backtest if bar.volume / 4 and instrument.min_size both evaluate to 1 Processing TradeTick from bar fails in backtest if bar.volume / 4 and instrument.size_increment both evaluate to 1 Feb 1, 2025
@miller-moore miller-moore changed the title Processing TradeTick from bar fails in backtest if bar.volume / 4 and instrument.size_increment both evaluate to 1 Processing TradeTick from bar fails in backtest if bar.volume / 4 and instrument.size_increment both evaluate to < 1 Feb 1, 2025
@faysou
Copy link
Collaborator

faysou commented Feb 1, 2025

Thanks for the report, I've implemented this code recently, I'll fix it today or tomorrow, I know what to do.

@faysou
Copy link
Collaborator

faysou commented Feb 1, 2025

I don't understand why cdef double size_value = max(bar.volume.as_double() / 4.0, self.instrument.size_increment.as_double()) is not enough.

Can you please send an example reproducing the issue ?

@stefansimik
Copy link
Contributor

As I understood it, the code is OK, but just checked condition is failing: Condition.positive_int.
If such a condition is there, then result of the code can be decimal number (smaller than integer 1), on which condition Condition.positive_int fails...

But let's wait for MRE if needed 👍

@miller-moore
Copy link
Contributor Author

I don't have an MRE ready but I will try to work one up if you still need one after the following attempted explanation.

Basically:

  • bar.volume.as_double() / 4.0 can evaluate to a float smaller than 1
  • self.instrument.size_increment.as_double() can also evaluate to a float smaller than 1

Therefore, size_value may be less than 1, which in turn means size may be less than 1. size then gets passed directly into the TradeTick constructor, where the error is thrown from Condition.positive_int(size):

Condition.positive_int(size._mem.raw, "size")

@cjdsellers
Copy link
Member

Hi @miller-moore

Thanks for the report!

I think the issue was in the quote tick processing from bars (rather than trade tick processing).
https://github.com/nautechsystems/nautilus_trader/blob/develop/nautilus_trader/backtest/matching_engine.pyx#L726

Now fixed on develop branch from commit 7f4e982.

@cjdsellers
Copy link
Member

Apologies, I see you specifically mentioned TradeTick, and so the above was a different bug.

This condition check is on the raw value, so any fractional unit up to maximum precision is fine (we don't need a whole unit size trade) https://github.com/nautechsystems/nautilus_trader/blob/develop/nautilus_trader/model/data.pyx#L4249

So I suspect this may be a mismatch in data vs size_precision or size_increment?

@miller-moore
Copy link
Contributor Author

miller-moore commented Feb 2, 2025

Ok yes, that's reasonable. I had not thought of that.

I'll try to work up an MRE which will hopefully guide what to do if anything. I since overwrote all my catalog bars to have a bigger volume to get through the backtest but, by memory, one error occurred with AAVEUSDT-PERP which had a bar volume of 1 and instrument size_precision and size_increment of 1 and 0.1, respectively. I'm not smart enough to say whether those facts are useful to you or not.

@stefansimik
Copy link
Contributor

@hi @miller-moore ,
just to help and simplify the situation with MRE preparation , I'm sending a template for MRE, where you only need to modify the bars to capture and demonstrate the problem

@cjdsellers
Copy link
Member

Hey @miller-moore

Thanks! For context, the issue you experienced was due to the trade size being zero.
This often happens when a small value gets rounded down to zero because the size precision is too small for the data.

It's also a common preprocessing step to inflate trade volumes if you're going to use bars for processing execution (as you've done), because inferring top-of-book size available from trade volumes alone probably has low accuracy.

@faysou
Copy link
Collaborator

faysou commented Feb 3, 2025

@cjdsellers should I reopen the PR I did yesterday? I don't think we want the backtests to crash, an approximation may be better like what was suggested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Development

No branches or pull requests

4 participants