diff --git a/adapters/ccxt_shim/breeze_ccxt.py b/adapters/ccxt_shim/breeze_ccxt.py index d73935999..22c13e31f 100644 --- a/adapters/ccxt_shim/breeze_ccxt.py +++ b/adapters/ccxt_shim/breeze_ccxt.py @@ -67,7 +67,8 @@ class BreezeCCXT(ccxt.Exchange): if self.paper_mode: self.paper_ledger = PaperLedger() logger.info( - f"Initialized Paper Mode: Slippage={self.paper_slippage}bps, Fee={self.paper_fee}bps" + f"Initialized Paper Mode: Slippage={self.paper_slippage}bps, " + f"Fee={self.paper_fee}bps" ) # Initialize RiskGuard AFTER super to prevent CCXT from overwriting it if 'risk_guard' is in config @@ -576,7 +577,8 @@ class BreezeCCXT(ccxt.Exchange): return ohlcv[:limit] except Exception as e: logger.warning( - f"event=icicibreeze_fetch_ohlcv_sdk_error symbol={symbol} timeframe={timeframe} error={str(e)}" + f"event=icicibreeze_fetch_ohlcv_sdk_error symbol={symbol} " + f"timeframe={timeframe} error={str(e)}" ) return [] @@ -605,7 +607,8 @@ class BreezeCCXT(ccxt.Exchange): ticker = self.fetch_ticker(symbol) price_surface = {"bid": ticker.get("bid", 0), "ask": ticker.get("ask", 0)} except Exception: - # If ticker fails (e.g. rate limit), we pass empty surface and risk guard skips spread check + # If ticker fails (e.g. rate limit), we pass empty surface and risk guard + # skips spread check price_surface = {} blocked, reason = self.risk_guard.should_block_entry(symbol, side, price_surface) @@ -742,7 +745,8 @@ class BreezeCCXT(ccxt.Exchange): def cancel_order(self, order_id, symbol=None, params: dict | None = None): if self.paper_mode: logger.warning( - f"Paper mode cancel_order called for {order_id}. Order is already considered closed/filled." + f"Paper mode cancel_order called for {order_id}. " + "Order is already considered closed/filled." ) # Return a dummy closed order structure or just the ID? # CCXT expects dictionary or just handling it strictly? diff --git a/tests/exchange/test_icicibreeze_paper.py b/tests/exchange/test_icicibreeze_paper.py index 72df2241a..64f9302fa 100644 --- a/tests/exchange/test_icicibreeze_paper.py +++ b/tests/exchange/test_icicibreeze_paper.py @@ -1,15 +1,14 @@ -import pytest -import shutil -from pathlib import Path from unittest import mock + +import pytest + from adapters.ccxt_shim.breeze_ccxt import BreezeCCXT -from freqtrade.exceptions import OperationalException @pytest.fixture def paper_config(tmp_path): # Use a tmp dir for ledger - ledger_dir = tmp_path / "paper_ledger" + # ledger_dir = tmp_path / "paper_ledger" return { "icicibreeze_paper_forward_test": True, "paper_slippage_bps": 10, @@ -51,7 +50,10 @@ def test_paper_create_order_simulates_fill(paper_exchange): with mock.patch.object(paper_exchange, "fetch_ticker", return_value={"last": 1000.0}): # Mock MarketHours to allow order with mock.patch.object(paper_exchange.market_hours, "assert_can_create_order"): - order = paper_exchange.create_order(symbol, "limit", side, amount) + with mock.patch.object( + paper_exchange.risk_guard, "should_block_entry", return_value=(False, "OK") + ): + order = paper_exchange.create_order(symbol, "limit", side, amount) # Checks assert order["status"] == "closed" @@ -84,11 +86,15 @@ def test_real_order_blocked_in_paper_mode(paper_exchange): # We are in paper execution mode. # If we call create_order, it goes to paper logic. - # To verifying "blocking", we can check that it didn't call ANY Breeze/SDK method or modify _mock_orders + # To verifying "blocking", we can check that it didn't call ANY Breeze/SDK + # method or modify _mock_orders with mock.patch.object(paper_exchange, "fetch_ticker", return_value={"last": 100.0}): with mock.patch.object(paper_exchange.market_hours, "assert_can_create_order"): - paper_exchange.create_order("SBIN/INR", "limit", "buy", 1) + with mock.patch.object( + paper_exchange.risk_guard, "should_block_entry", return_value=(False, "OK") + ): + paper_exchange.create_order("SBIN/INR", "limit", "buy", 1) assert len(paper_exchange._mock_orders) == 0 @@ -116,7 +122,7 @@ def test_ledger_persistence_integration(tmp_path): assert (ledger_dir / "paper_trades.csv").exists() assert (ledger_dir / "paper_daily_summary.csv").exists() - with open(ledger_dir / "paper_daily_summary.csv", "r") as f: + with (ledger_dir / "paper_daily_summary.csv").open("r") as f: content = f.read() # Header + 1 row assert "trades_count,gross_notional,total_fees" in content