pull/12760/head
vijay sharma 4 months ago
parent c1164e8b8c
commit 13ccce5238

@ -66,6 +66,7 @@ class BreezeCCXT(ccxt.Exchange):
# Rate Limiting
# P17: Switched to centralized RateLimiter with Env support
self.rate_limiter = RateLimiter()
self._security_master_cache: dict[str, Any] | None = None
self.market_hours = MarketHoursGuard()
self.degraded_guard = DegradedModeGuard()
self.order_router = OrderRouter(lambda: self.markets)

@ -32,6 +32,9 @@ ALL_GATES=(
"p14_market_hours"
"p15_risk_guardrails"
"p16_order_router"
"p17_rate_limit"
"p17_degraded_mode"
"p17_invalid_symbol"
)
# Parse flags

@ -0,0 +1,24 @@
#!/bin/bash
set -e
source scripts/gates/common.sh
# P17 Degraded Mode Gate
# Verifies degraded mode blocking.
echo "=========================================================="
echo "GATE: P17 Degraded Mode"
echo "=========================================================="
echo "1. Verify Forced Degraded Mode (Integration)"
# Uses tests/exchange/test_icicibreeze_integration_degraded.py
# Matches "degraded_block"
pytest -v tests/exchange/test_icicibreeze_integration_degraded.py
echo " [+] Integration Verified"
echo "2. Verify Logic (Unit Tests)"
pytest -v tests/test_degraded_mode_force_block.py tests/test_degraded_mode_auto_trigger.py
echo " [+] Logic Verified"
echo "----------------------------------------------------------"
echo "GATE P17-DegradedMode PASSED"
echo "----------------------------------------------------------"

@ -0,0 +1,18 @@
#!/bin/bash
set -e
source scripts/gates/common.sh
# P17 Invalid Symbol Resilience Gate
# Verifies system handles bad data gracefully.
echo "=========================================================="
echo "GATE: P17 Invalid Symbol"
echo "=========================================================="
echo "1. Verify Invalid Symbol Handling (Pytest)"
pytest -v tests/exchange/test_icicibreeze_invalid_symbol.py
echo " [+] Resilience Verified"
echo "----------------------------------------------------------"
echo "GATE P17-InvalidSymbol PASSED"
echo "----------------------------------------------------------"

@ -0,0 +1,27 @@
#!/bin/bash
set -e
source scripts/gates/common.sh
# P17 Rate Limit Gate
# Verifies that shim enforces rate limits in both sleep (default) and block modes.
echo "=========================================================="
echo "GATE: P17 Rate Limiter"
echo "=========================================================="
echo "1. Verify Block Mode (Pytest Integration w/ Env)"
# Uses tests/exchange/test_icicibreeze_rate_limit_applied.py
# Env vars set in the test fixture, but we can double check logic here if needed?
# Actually the test file is self-contained. Is that enough?
# Plan says: "Run pytest tests with specific failure expectations"
# Our integration test file forces block mode.
pytest -v tests/exchange/test_icicibreeze_rate_limit_applied.py
echo " [+] Block Mode Verified"
echo "2. Verify Sleep Mode (Unit Test)"
pytest -v tests/test_rate_limiter_sleep_mode.py
echo " [+] Sleep Mode Verified"
echo "----------------------------------------------------------"
echo "GATE P17-RateLimit PASSED"
echo "----------------------------------------------------------"

@ -0,0 +1,50 @@
import pytest
import os
from unittest import mock
from freqtrade.exceptions import OperationalException
from adapters.ccxt_shim.breeze_ccxt import BreezeCCXT
@pytest.fixture
def exchange_for_resilience():
exchange = BreezeCCXT()
exchange.breeze = mock.Mock() # Mock session
return exchange
def test_fetch_ohlcv_invalid_symbol_raises_cleanly(exchange_for_resilience):
# Mock _load_security_master to return empty master, so any symbol is not found
with mock.patch.object(
exchange_for_resilience,
"_load_security_master",
return_value={"nfo": {}, "nse": {"by_symbol": {}}},
):
# "INVALID/INR" -> Underlying=INVALID, Quote=INR -> CASH
# Lookup INVALID in nse master -> None -> Raise "Cash symbol not found"
with pytest.raises(OperationalException, match="Cash symbol not found"):
exchange_for_resilience.fetch_ohlcv("INVALID/INR", "5m")
def test_fetch_ohlcv_api_error_returns_empty(exchange_for_resilience):
# Case 2: Breeze SDK returns Generic Exception
symbol = "RELIANCE/INR"
# Mock master to find symbol
mock_master = {"nse": {"by_symbol": {"RELIANCE": {"token": "123"}}}, "nfo": {}}
with mock.patch.object(
exchange_for_resilience, "_load_security_master", return_value=mock_master
):
with mock.patch.object(
exchange_for_resilience,
"_parse_symbol",
return_value={"stock_code": "REL", "exchange_code": "NSE", "product_type": "cash"},
):
# Mock Breeze SDK to raise Exception
exchange_for_resilience.breeze.get_historical_data_v2.side_effect = Exception(
"API Error"
)
# Should NOT raise, but return empty list (resilience)
res = exchange_for_resilience.fetch_ohlcv(symbol, "5m")
assert res == []
Loading…
Cancel
Save