Files
mt5-ai-xauusd-trader/tests/test_harmonization.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

82 lines
2.7 KiB
Python

"""
Tests for system harmonization and cross-agent conflict resolution.
"""
from unittest.mock import MagicMock, patch
def test_risk_manager_consolidated_initialization():
"""Verify RiskManager can be initialized with both logger and monitor."""
from src.core.config import TradingConfig
from src.core.monitor import Monitor
from src.core.trade_logger import TradeLogger
from src.trading.risk_manager import RiskManager
config = MagicMock(spec=TradingConfig)
logger = MagicMock(spec=TradeLogger)
monitor = MagicMock(spec=Monitor)
risk = RiskManager(config=config, account_balance=10000.0, logger_db=logger, monitor=monitor)
assert risk.trade_logger == logger
assert risk.monitor == monitor
assert risk.balance == 10000.0
def test_config_singleton_loading():
"""Verify get_config returns a TradingConfig singleton."""
# Ensure environment variables required for validation are present and valid
with patch.dict(
"os.environ", {"MT5_PASSWORD": "dummy", "MT5_SERVER": "dummy", "RISK_PER_TRADE": "0.01"}
):
from src.core.config import TradingConfig, get_config
# We need to clear the lru_cache for testing purpose if it was already populated
get_config.cache_clear()
cfg1 = get_config()
cfg2 = get_config()
assert isinstance(cfg1, TradingConfig)
assert cfg1 is cfg2
def test_model_action_to_direction_mapping():
"""Verify that ModelAction maps correctly to SignalDirection."""
from src.core.constants import ModelAction, SignalDirection
assert ModelAction.HOLD.to_direction() == SignalDirection.HOLD
assert ModelAction.BUY.to_direction() == SignalDirection.BUY
assert ModelAction.SELL.to_direction() == SignalDirection.SELL
assert SignalDirection.HOLD == 0
assert SignalDirection.BUY == 1
assert SignalDirection.SELL == -1
def test_signal_explainer_mapping_alignment():
"""Verify that SignalExplainer uses unified ModelAction mapping."""
from src.core.constants import SignalDirection
from src.core.explainability import SignalExplainer
explainer = SignalExplainer()
# Votes: ppo=1 (BUY), lstm=2 (SELL)
model_votes = {"ppo": 1, "lstm": 2}
model_weights = {"ppo": 0.5, "lstm": 0.5}
explanation = explainer.explain(
symbol="XAUUSD",
direction=1,
confidence=0.7,
model_votes=model_votes,
model_weights=model_weights,
risk_data={"passed": True},
regime_info={"name": "Trending"},
)
# Verify attribution mapping
for attr in explanation.model_attributions:
if attr.model_name == "ppo":
assert attr.vote == SignalDirection.BUY
elif attr.model_name == "lstm":
assert attr.vote == SignalDirection.SELL