mirror of
https://github.com/triqbit/mt5-ai-xauusd-trader.git
synced 2026-11-02 06:56:15 +00:00
📦 Jules02: Dependency and environment hygiene — hardened config and synced core deps (#603)
* 📦 Jules02: Dependency and environment hygiene — hardened config and synced core deps - Hardened `TradingConfig` with Pydantic field constraints to match `RISK_LIMITS.md`. - Synchronized `scikit-learn` (1.7.2) and `structlog` (25.5.0) across all environments. - Added type stubs for redis, requests, dateutil, and setuptools to CI requirements. - Updated `test_config_validator.py` to reflect new Pydantic-level enforcement. Co-authored-by: xnessom <255288032+xnessom@users.noreply.github.com> * 📦 Jules02: Dependency and environment hygiene — hardened config, synced core deps, and CI fixes - Hardened `TradingConfig` with Pydantic field constraints to match `RISK_LIMITS.md`. - Synchronized `scikit-learn` (1.7.2) and `structlog` (25.5.0) across all environments. - Added type stubs for redis, requests, dateutil, and setuptools to CI requirements. - Updated `test_config_validator.py` to reflect new Pydantic-level enforcement. - Fixed CI failures: - Added missing `Dict` import in `src/trading/execution_filter.py`. - Created `docs/environment_hygiene.md` to satisfy auto-merge documentation policy. - Added `python-telegram-bot` to migration safety workflow dependencies. Co-authored-by: xnessom <255288032+xnessom@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: xnessom <255288032+xnessom@users.noreply.github.com>
This commit is contained in:
co-authored by
xnessom
google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
parent
2eb4a415bb
commit
6f122d5a8f
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install sqlalchemy==2.0.30 alembic==1.13.1 pydantic==2.11.1 pydantic-settings==2.8.1 numpy==1.26.4 structlog==24.1.0 pandas==2.2.3 scipy==1.15.2 psutil==7.2.2
|
||||
pip install sqlalchemy==2.0.30 alembic==1.13.1 pydantic==2.11.1 pydantic-settings==2.8.1 numpy==1.26.4 structlog==24.1.0 pandas==2.2.3 scipy==1.15.2 psutil==7.2.2 python-telegram-bot==22.7
|
||||
|
||||
- name: Run Migration Reversibility Check
|
||||
run: python scripts/verify_migrations.py
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
### Dependency and Environment Hygiene Improvements
|
||||
|
||||
#### Configuration Hardening
|
||||
- **Alignment with RISK_LIMITS.md:** Updated `src/core/config.py` with strict Pydantic `Field` constraints (`ge`, `le`) to match enterprise risk standards. Unsafe configurations are now rejected at startup.
|
||||
- **Tighter Bounds:**
|
||||
- `max_positions`: reduced maximum from 10 to 5.
|
||||
- `risk_per_trade`: reduced maximum from 5% to 2%.
|
||||
- `max_daily_loss`: reduced maximum from 20% to 6%.
|
||||
- `confidence_threshold`: minimum set to 0.5.
|
||||
- `model_accuracy_floor`: minimum set to 0.5.
|
||||
- `model_win_rate_floor`: minimum set to 0.4.
|
||||
|
||||
#### Dependency Synchronization
|
||||
- **Consistency:** Unified versions of `scikit-learn==1.7.2` and `structlog==25.5.0` across `requirements.txt`, `requirements-linux.txt`, and `requirements-docker.txt` to eliminate environment drift.
|
||||
- **Type Safety:** Added missing type stubs (`types-redis`, `types-requests`, `types-python-dateutil`, `types-setuptools`, `types-PyYAML`) to CI requirements to improve static analysis reliability.
|
||||
|
||||
#### Code Quality & Fixes
|
||||
- **Fix:** Added missing `Dict` import in `src/trading/execution_filter.py` to resolve CI linting errors.
|
||||
- **Validation:** Verified Pydantic enforcement logic and ensured compatibility with existing test suites.
|
||||
+6
-1
@@ -40,9 +40,14 @@ pytest-cov==6.1.0
|
||||
python-telegram-bot
|
||||
fastapi>=0.115.0
|
||||
httpx==0.28.0
|
||||
structlog==24.1.0
|
||||
structlog==25.5.0
|
||||
rich==15.0.0
|
||||
gymnasium==1.3.0
|
||||
jinja2==3.1.6
|
||||
prometheus-client==0.25.0
|
||||
psutil
|
||||
types-redis
|
||||
types-requests
|
||||
types-python-dateutil
|
||||
types-setuptools
|
||||
types-PyYAML
|
||||
|
||||
@@ -35,7 +35,7 @@ redis==5.0.4
|
||||
|
||||
# -- Monitoring & Logging ------------------------------------------
|
||||
prometheus-client==0.25.0
|
||||
structlog==24.1.0
|
||||
structlog==25.5.0
|
||||
rich==15.0.0
|
||||
tqdm==4.66.4
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ redis==5.0.4
|
||||
|
||||
# ── Monitoring & Logging ────────────────────────────────────
|
||||
prometheus-client==0.25.0
|
||||
structlog==24.1.0
|
||||
structlog==25.5.0
|
||||
rich==15.0.0
|
||||
tqdm==4.66.4
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ stable-baselines3==2.8.0
|
||||
gymnasium==0.29.1
|
||||
numpy==2.2.6
|
||||
scipy==1.13.0
|
||||
scikit-learn==1.6.1
|
||||
scikit-learn==1.7.2
|
||||
pandas==2.3.3
|
||||
|
||||
# ── Deep Learning Extras ────────────────────────────────────
|
||||
|
||||
+6
-6
@@ -48,13 +48,13 @@ class TradingConfig(BaseSettings):
|
||||
default="demo", description="Execution mode: demo, live, or backtest"
|
||||
)
|
||||
max_positions: int = Field(
|
||||
default=3, ge=1, le=10, description="Maximum number of concurrent open positions permitted"
|
||||
default=3, ge=1, le=5, description="Maximum number of concurrent open positions permitted"
|
||||
)
|
||||
risk_per_trade: float = Field(
|
||||
default=0.01, ge=0.001, le=0.05, description="Fraction of account equity to risk per trade (e.g., 0.01 = 1%)"
|
||||
default=0.01, ge=0.001, le=0.02, description="Fraction of account equity to risk per trade (e.g., 0.01 = 1%)"
|
||||
)
|
||||
max_daily_loss: float = Field(
|
||||
default=0.05, ge=0.01, le=0.20, description="Maximum daily drawdown percentage before halting trading"
|
||||
default=0.05, ge=0.01, le=0.06, description="Maximum daily drawdown percentage before halting trading"
|
||||
)
|
||||
|
||||
# ── Model ──────────────────────────────────────────────────────────────────
|
||||
@@ -102,16 +102,16 @@ class TradingConfig(BaseSettings):
|
||||
default="", description="Explicit confirmation for LIVE trading (must be 'YES' to start in live mode)"
|
||||
)
|
||||
confidence_threshold: float = Field(
|
||||
default=0.6, ge=0.0, le=1.0, description="Minimum model confidence score required to execute a signal"
|
||||
default=0.6, ge=0.5, le=1.0, description="Minimum model confidence score required to execute a signal"
|
||||
)
|
||||
model_drift_threshold: float = Field(
|
||||
default=0.3, ge=0.05, le=0.5, description="Maximum allowed model drift score before halting trades"
|
||||
)
|
||||
model_accuracy_floor: float = Field(
|
||||
default=0.5, ge=0.4, le=0.9, description="Minimum allowed model accuracy score before halting trades"
|
||||
default=0.5, ge=0.5, le=0.9, description="Minimum allowed model accuracy score before halting trades"
|
||||
)
|
||||
model_win_rate_floor: float = Field(
|
||||
default=0.45, ge=0.3, le=0.7, description="Minimum allowed historical win rate before halting trades"
|
||||
default=0.45, ge=0.4, le=0.7, description="Minimum allowed historical win rate before halting trades"
|
||||
)
|
||||
|
||||
@field_validator("risk_per_trade")
|
||||
|
||||
@@ -11,7 +11,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
@@ -182,13 +182,10 @@ def test_validator_max_daily_loss(monkeypatch, tmp_path):
|
||||
monkeypatch.setenv("DATABASE_URL", "postgresql://user:pass@host:5432/db")
|
||||
monkeypatch.setenv("MODEL_PATH", str(model_file))
|
||||
|
||||
# Hard stop is 6%
|
||||
# Hard stop is 6%. Pydantic catches 7%.
|
||||
monkeypatch.setenv("MAX_DAILY_LOSS", "0.07")
|
||||
cfg = TradingConfig()
|
||||
validator = ConfigValidator(cfg)
|
||||
result = validator.validate()
|
||||
assert result.success is False
|
||||
assert any(e.field == "MAX_DAILY_LOSS" and e.critical for e in result.errors)
|
||||
with pytest.raises(Exception):
|
||||
TradingConfig()
|
||||
|
||||
# Warning if > 5% (Emergency Stop)
|
||||
monkeypatch.setenv("MAX_DAILY_LOSS", "0.055")
|
||||
@@ -207,15 +204,12 @@ def test_validator_incompatible_live_positions(monkeypatch, tmp_path):
|
||||
monkeypatch.setenv("MT5_SERVER", "Broker-Live")
|
||||
monkeypatch.setenv("MODE", "live")
|
||||
monkeypatch.setenv("CONFIRM_LIVE_TRADING", "YES")
|
||||
monkeypatch.setenv("MAX_POSITIONS", "10")
|
||||
monkeypatch.setenv("MAX_POSITIONS", "6") # New limit is 5
|
||||
monkeypatch.setenv("DATABASE_URL", "postgresql://real:pass@host/db")
|
||||
monkeypatch.setenv("MODEL_PATH", str(model_file))
|
||||
|
||||
cfg = TradingConfig()
|
||||
validator = ConfigValidator(cfg)
|
||||
result = validator.validate()
|
||||
assert result.success is False
|
||||
assert any(e.field == "MAX_POSITIONS" and e.critical for e in result.errors)
|
||||
with pytest.raises(Exception):
|
||||
TradingConfig()
|
||||
|
||||
def test_validator_backtest_warning(monkeypatch, tmp_path):
|
||||
"""Test validator gives a non-critical warning for Telegram in backtest."""
|
||||
@@ -366,10 +360,8 @@ def test_validator_confidence_threshold(monkeypatch, tmp_path):
|
||||
|
||||
# Critical breach (< 0.50)
|
||||
monkeypatch.setenv("CONFIDENCE_THRESHOLD", "0.45")
|
||||
cfg = TradingConfig()
|
||||
result = ConfigValidator(cfg).validate()
|
||||
assert result.success is False
|
||||
assert any(e.field == "CONFIDENCE_THRESHOLD" and e.critical for e in result.errors)
|
||||
with pytest.raises(Exception):
|
||||
TradingConfig()
|
||||
|
||||
# Warning (< 0.55)
|
||||
monkeypatch.setenv("CONFIDENCE_THRESHOLD", "0.52")
|
||||
|
||||
Reference in New Issue
Block a user