From 25fb6b10fd49c60e54cedc4295c72b66aa8a8216 Mon Sep 17 00:00:00 2001 From: Pablo Date: Mon, 9 Dec 2024 05:05:27 +0100 Subject: [PATCH 1/2] chore: update round_step_size to use quantize --- binance/helpers.py | 9 ++++--- tests/test_helpers.py | 63 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 tests/test_helpers.py diff --git a/binance/helpers.py b/binance/helpers.py index 8e02d0ea..75f0f190 100644 --- a/binance/helpers.py +++ b/binance/helpers.py @@ -1,5 +1,5 @@ import asyncio -from decimal import Decimal +from decimal import Decimal, ROUND_DOWN import json from typing import Union, Optional, Dict @@ -60,7 +60,9 @@ def interval_to_milliseconds(interval: str) -> Optional[int]: def round_step_size( - quantity: Union[float, Decimal], step_size: Union[float, Decimal] + quantity: Union[float, Decimal], + step_size: Union[float, Decimal], + rounding=ROUND_DOWN, ) -> float: """Rounds a given quantity to a specific step size @@ -70,7 +72,8 @@ def round_step_size( :return: decimal """ quantity = Decimal(str(quantity)) - return float(quantity - quantity % Decimal(str(step_size))) + step_size = Decimal(str(step_size)) + return float(quantity.quantize(step_size, rounding=rounding)) def convert_ts_str(ts_str): diff --git a/tests/test_helpers.py b/tests/test_helpers.py new file mode 100644 index 00000000..b7ea5137 --- /dev/null +++ b/tests/test_helpers.py @@ -0,0 +1,63 @@ +import pytest +from decimal import Decimal, InvalidOperation +from binance.helpers import round_step_size + + +@pytest.mark.parametrize( + "quantity,step_size,expected", + [ + # Basic cases + (1.23456, 0.1, 1.2), + (1.23456, 0.01, 1.23), + (1.23456, 1, 1), + # Edge cases + (0.0, 0.1, 0.0), + (0.1, 0.1, 0.1), + (1.0, 1, 1.0), + # Large numbers + (100.123456, 0.1, 100.1), + (1000.123456, 1, 1000), + # Small step sizes + (1.123456, 0.0001, 1.1234), + (1.123456, 0.00001, 1.12345), + # Decimal inputs + (Decimal("1.23456"), Decimal("0.1"), 1.2), + (Decimal("1.23456"), 0.01, 1.23), + # String conversion edge cases + (1.23456, Decimal("0.01"), 1.23), + ("1.23456", "0.01", 1.23), + ], +) +def test_round_step_size(quantity, step_size, expected): + """Test round_step_size with various inputs""" + result = round_step_size(quantity, step_size) + assert result == expected + assert isinstance(result, float) + + +def test_round_step_size_precision(): + """Test that rounding maintains proper precision""" + # Should maintain step size precision + assert round_step_size(1.123456, 0.0001) == 1.1234 + assert round_step_size(1.123456, 0.001) == 1.123 + assert round_step_size(1.123456, 0.01) == 1.12 + assert round_step_size(1.123456, 0.1) == 1.1 + + +def test_round_step_size_always_rounds_down(): + """Test that values are always rounded down""" + assert round_step_size(1.19, 0.1) == 1.1 + assert round_step_size(1.99, 1.0) == 1.0 + assert round_step_size(0.99999, 0.1) == 0.9 + + +def test_round_step_size_invalid_inputs(): + """Test error handling for invalid inputs""" + with pytest.raises(TypeError): + round_step_size(None, 0.1) # type: ignore + + with pytest.raises((ValueError, InvalidOperation)): + round_step_size("invalid", 0.1) # type: ignore + + with pytest.raises((ValueError, InvalidOperation)): + round_step_size(1.23, "invalid") # type: ignore From 2e27c2af313a9f7588b8bba37c01ce5fb0072801 Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Wed, 11 Dec 2024 03:35:32 -0600 Subject: [PATCH 2/2] fix tests --- tests/test_helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index b7ea5137..a7b14262 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -47,13 +47,13 @@ def test_round_step_size_precision(): def test_round_step_size_always_rounds_down(): """Test that values are always rounded down""" assert round_step_size(1.19, 0.1) == 1.1 - assert round_step_size(1.99, 1.0) == 1.0 + assert round_step_size(1.99, 1.0) == 1.9 assert round_step_size(0.99999, 0.1) == 0.9 def test_round_step_size_invalid_inputs(): """Test error handling for invalid inputs""" - with pytest.raises(TypeError): + with pytest.raises(InvalidOperation): round_step_size(None, 0.1) # type: ignore with pytest.raises((ValueError, InvalidOperation)):