From b2fde5732c7f60f62177f44d393342dceca25f75 Mon Sep 17 00:00:00 2001 From: Jeff West Date: Thu, 15 Oct 2026 06:20:14 -0500 Subject: [PATCH] fix(orderbook): use pl.len() for trade counts (polars 2.0 compat, refs #162) Polars 2.0 rejects argument-less pl.count(); get_statistics() swallowed the TypeError as {'error': 'Analysis failed'}. Use pl.len() and keep the output column name "count". Assert buy/sell trade counts in the existing statistics test. --- CHANGELOG.md | 6 ++++++ src/project_x_py/orderbook/analytics.py | 2 +- tests/orderbook/test_orderbook_analytics.py | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6082d6..443a530e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Orderbook `get_statistics()` failed with "Analysis failed" under polars 2.0 + because `pl.count()` no longer accepts zero arguments. Trade-side counts now + use `pl.len()` (compatible with polars 1.31+ and 2.0). + ### Internal - Normalize Polars `Series.sum()` aggregates to `float`/`int` before diff --git a/src/project_x_py/orderbook/analytics.py b/src/project_x_py/orderbook/analytics.py index d18a5aca..50829385 100644 --- a/src/project_x_py/orderbook/analytics.py +++ b/src/project_x_py/orderbook/analytics.py @@ -592,7 +592,7 @@ async def get_statistics(self) -> dict[str, Any]: # Optimized: Single pass through data with aggregation trade_stats = self.orderbook.recent_trades.group_by("side").agg( [ - pl.count().alias("count"), + pl.len().alias("count"), pl.col("volume").sum().alias("total_volume"), ] ) diff --git a/tests/orderbook/test_orderbook_analytics.py b/tests/orderbook/test_orderbook_analytics.py index 18b9437a..8b1dd8d9 100644 --- a/tests/orderbook/test_orderbook_analytics.py +++ b/tests/orderbook/test_orderbook_analytics.py @@ -447,6 +447,9 @@ async def test_get_statistics(self, market_analytics): assert result["total_bid_size"] == 100 assert result["total_ask_size"] == 100 assert result["total_trades"] == 5 + # Fixture sides: buy, sell, buy, sell, buy + assert result["buy_trades"] == 3 + assert result["sell_trades"] == 2 class TestErrorHandling: