Files
mt5-ai-xauusd-trader/tests/test_event_intelligence_v2.py
T
google-labs-jules[bot]andxnessom 86c80f7ec0 feat: 💡 Jules02: CLI and operator UX improvement — Configurable polling and setup wizard enhancements
Institutional-grade algorithmic trading requires predictable interfaces and easy configuration. This PR improves the operator and developer experience by:

1. **Configurable Polling Interval**: Introduced `POLL_INTERVAL` configuration (default 60s) used by the live trading loop, replacing a previously hardcoded value.
2. **Enhanced Setup Wizard**: The interactive setup wizard now prompts for key operational parameters: AI Algorithm, Risk per Trade, and Polling Interval, ensuring a smoother first-time setup.
3. **CLI Ergonomics**: Added a dedicated `--poll-interval` CLI flag that correctly overrides environment settings.
4. **Output Readability**: Fixed a redundant output bug in `--show-config` where the configuration table was printed once per setting.
5. **Security & Dependency Safety**: Updated CI workflows to use `.pip-audit.ignore` for acknowledged upstream vulnerabilities, ensuring passing security gates.
6. **Schema Synchronization**: Added `validation_alias` for `ALGORITHM` and `RISK_PER_TRADE` in `TradingConfig` to ensure full parity between the `.env` file, setup wizard, and system state.

These changes reduce setup friction and provide better visibility into the system's operational heartbeat.

Verified with:
- `python main.py --show-config`
- `python main.py --setup`
- `pytest tests/test_cli_ux.py tests/test_jules_setup_wizard.py tests/test_failure_propagation.py`

Co-authored-by: xnessom <255288032+xnessom@users.noreply.github.com>
2026-05-21 08:52:10 +00:00

116 lines
3.6 KiB
Python

from datetime import UTC, datetime, timedelta
from unittest.mock import MagicMock
import pytest
from src.data.event_intelligence import (
EventCategory,
EventImpact,
EventIntelligence,
MacroEvent,
MockEventProvider,
TradingViewEventProvider,
)
@pytest.fixture
def now():
return datetime(2024, 5, 1, 12, 0, 0, tzinfo=UTC)
def test_refresh_interval_logic(now):
"""Test that EventIntelligence respects the refresh_interval."""
event = MacroEvent(
name="Test Event", category=EventCategory.USD, impact=EventImpact.LOW, timestamp=now
)
provider = MagicMock()
provider.get_upcoming_events.return_value = [event]
# 5 minute refresh interval
intel = EventIntelligence([provider], refresh_interval_minutes=5)
# First call - should hit provider
intel.get_risk_status(now)
assert provider.get_upcoming_events.call_count == 1
# Second call (2 mins later) - should NOT hit provider
intel.get_risk_status(now + timedelta(minutes=2))
assert provider.get_upcoming_events.call_count == 1
# Third call (6 mins later) - should hit provider
intel.get_risk_status(now + timedelta(minutes=6))
assert provider.get_upcoming_events.call_count == 2
def test_fail_safe_blocked_true(now):
"""Test that fail_safe_blocked=True blocks when no data is available."""
class FailingProvider(MockEventProvider):
def get_upcoming_events(self, start, end):
raise Exception("API Down")
intel = EventIntelligence([FailingProvider()], fail_safe_blocked=True)
status = intel.get_risk_status(now)
assert status.is_blocked is True
assert status.risk_multiplier == 0.0
assert "Event data unavailable (no cache)" in status.reason
def test_fail_safe_blocked_false(now):
"""Test that fail_safe_blocked=False (default) does not block when no data is available."""
class FailingProvider(MockEventProvider):
def get_upcoming_events(self, start, end):
raise Exception("API Down")
intel = EventIntelligence([FailingProvider()], fail_safe_blocked=False)
status = intel.get_risk_status(now)
assert status.is_blocked is False
assert status.risk_multiplier == 1.0
def test_tradingview_mock_provider(now):
"""Test the TradingView mock provider returns events for known dates."""
# May 1, 2024 is a Wednesday.
# May 3, 2024 is the first Friday (NFP).
# May 8, 2024 is the second Wednesday (CPI).
provider = TradingViewEventProvider()
# Check NFP
start = datetime(2024, 5, 3, 0, 0, tzinfo=UTC)
end = datetime(2024, 5, 3, 23, 59, tzinfo=UTC)
events = provider.get_upcoming_events(start, end)
assert any("Non-Farm Payrolls" in e.name for e in events)
# Check CPI
start = datetime(2024, 5, 8, 0, 0, tzinfo=UTC)
end = datetime(2024, 5, 8, 23, 59, tzinfo=UTC)
events = provider.get_upcoming_events(start, end)
assert any("CPI" in e.name for e in events)
def test_geopolitical_default_duration(now):
"""Test that GEOPOLITICAL events get a 24h default duration."""
event = MacroEvent(
name="War breakout",
category=EventCategory.GEOPOLITICAL,
impact=EventImpact.HIGH,
timestamp=now,
)
# validate_timestamps is called on init
assert event.end_timestamp == now + timedelta(hours=24)
def test_central_bank_default_duration(now):
"""Test that FOMC/RATES events get a 4h default duration."""
event = MacroEvent(
name="Fed Rate Decision",
category=EventCategory.FOMC,
impact=EventImpact.CRITICAL,
timestamp=now,
)
assert event.end_timestamp == now + timedelta(hours=4)