Claude Opus 4.6 improvements: MT5 concurrency fixes, timezone UTC fixes, sentiment scoring consistency, security validator, and 2025-2026 economic/gold lexicon updates

This commit is contained in:
Mazonia
2026-10-01 05:59:13 +00:00
parent 600210cbf0
commit 82ffae4872
8 changed files with 76 additions and 23 deletions
+7 -7
View File
@@ -112,7 +112,13 @@ class SentimentAggregator:
data_points = len(self._recent_sentiments)
confidence = min(data_points / 10, 1.0) # Max confidence with 10+ articles
# Direction
# Also check from database
db_sentiment = crud.get_recent_sentiment(hours=self.decay_hours)
if db_sentiment != 0.0:
# Blend with DB sentiment
avg_score = avg_score * 0.7 + db_sentiment * 0.3
# Direction (determined after DB blend for consistency)
if avg_score > 0.15:
direction = "BULLISH"
elif avg_score < -0.15:
@@ -120,12 +126,6 @@ class SentimentAggregator:
else:
direction = "NEUTRAL"
# Also check from database
db_sentiment = crud.get_recent_sentiment(hours=self.decay_hours)
if db_sentiment != 0.0:
# Blend with DB sentiment
avg_score = avg_score * 0.7 + db_sentiment * 0.3
return {
"direction": direction,
"score": round(avg_score, 4),
+19
View File
@@ -307,4 +307,23 @@ def get_settings() -> Settings:
global _settings
if _settings is None:
_settings = Settings()
_validate_security(_settings)
return _settings
def _validate_security(settings: Settings):
"""Emit warnings for insecure default credentials (non-breaking)."""
import warnings
if settings.dashboard.secret_key == "change-me-in-production":
warnings.warn(
"⚠️ SECURITY: Dashboard secret_key is still the default. "
"Set DASHBOARD_SECRET_KEY in your .env for production use.",
stacklevel=2,
)
if settings.dashboard.password in ("", "admin123", "password"):
warnings.warn(
"⚠️ SECURITY: Dashboard password is weak/default. "
"Set a strong DASHBOARD_PASSWORD in your .env.",
stacklevel=2,
)
+17 -1
View File
@@ -1,6 +1,6 @@
symbol: XAUUSD
symbol_suffix: ''
active_mode: safe
active_mode: moderate
trading_modes:
safe:
name: Safe / Conservative
@@ -201,6 +201,22 @@ news:
- recession
- employment
- GDP
- BRICS
- de-dollarization
- dedollarization
- central bank gold
- sovereign debt
- sanctions
- stagflation
- yield curve
- debt ceiling
- quantitative tightening
- rate pause
- AI bubble
- crypto
- bitcoin
- safe haven demand
- PPI
confluence:
technical_weight: 40
ai_prediction_weight: 25
+3 -3
View File
@@ -524,7 +524,6 @@ class MT5Connector:
return result_dict
@synchronized
@synchronized
def send_pending_order(
self,
@@ -621,6 +620,7 @@ class MT5Connector:
logger.error(f"Failed to cancel order #{order_ticket}: {result.comment if result else mt5.last_error()}")
return False
@synchronized
def modify_position(
self,
ticket: int,
@@ -748,7 +748,7 @@ class MT5Connector:
return None
try:
from datetime import timedelta
now = datetime.now() + timedelta(days=2)
now = datetime.now(timezone.utc) + timedelta(days=2)
from_date = now - timedelta(days=30)
deals = mt5.history_deals_get(from_date, now, position=ticket)
if deals and len(deals) > 0:
@@ -779,7 +779,7 @@ class MT5Connector:
return []
try:
from datetime import timedelta
now = datetime.now() + timedelta(days=2)
now = datetime.now(timezone.utc) + timedelta(days=2)
from_date = now - timedelta(days=days)
deals = mt5.history_deals_get(from_date, now)
if not deals:
+8
View File
@@ -42,6 +42,14 @@ class EconomicEventsManager:
"ism",
"powell",
"rate decision",
# 2025-2026 additions
"pce", # Fed's preferred inflation gauge
"jolts", # Job openings — Fed watches closely
"adp", # ADP employment change
"ecb", # ECB decisions increasingly correlated with Gold
"tariff", # Trade policy shocks
"debt ceiling", # US debt ceiling showdowns
"treasury auction", # Bond market liquidity events
]
def __init__(self):
+10 -2
View File
@@ -88,7 +88,12 @@ class NewsAnalyzer:
"gold advance", "gold gain", "weak dollar", "dollar slide", "dollar fall", "dollar drop", "dollar sink",
"dollar weak", "dollar soft", "war", "conflict", "geopolitical", "crisis", "tension", "escalat", "strike", "attack",
"recession", "slowdown", "debt", "deficit", "bank failure", "tariff", "trade war",
"stimulus", "liquidity", "central bank", "reserve"
"stimulus", "liquidity", "central bank", "reserve",
# 2025-2026 bullish Gold catalysts
"brics", "de-dollarization", "dedollarization", "central bank gold", "gold buying",
"sovereign debt", "debt crisis", "sanctions", "stagflation", "yield curve inversion",
"debt ceiling", "quantitative easing", "safe haven demand", "rate pause",
"currency debasement", "fiscal deficit", "banking crisis",
]
# Bearish factors for Gold (Rate hikes, hawkish, strong dollar, peace, high yields)
@@ -97,7 +102,10 @@ class NewsAnalyzer:
"disinflation", "strong dollar", "dollar surge", "dollar rally", "dollar jump", "dollar gain", "dollar strong",
"gold drop", "gold fall", "gold tumble", "gold slide", "gold retreat", "gold sink",
"ceasefire", "peace", "de-escalat", "diplomacy", "strong job", "nfp beat", "robust job",
"yield surge", "yields rise", "yields jump"
"yield surge", "yields rise", "yields jump",
# 2025-2026 bearish Gold catalysts
"quantitative tightening", "rate increase", "ai bubble burst", "risk on rally",
"dollar dominance", "crypto surge", "bitcoin rally",
]
bull_matches = [kw for kw in bullish_keywords if kw in t]
+10 -10
View File
@@ -70,16 +70,6 @@ class SignalAggregator:
attention_analysis: Optional[dict] = None,
min_score: float = 65.0,
) -> ConfluenceResult:
# Dynamically synchronize with self-learning adaptive weights
try:
from ai.trade_learner import trade_learner
cw = trade_learner.get_confluence_weights()
self.technical_weight = cw.get("technical", self.technical_weight)
self.ai_weight = cw.get("ai_prediction", self.ai_weight)
self.sentiment_weight = cw.get("sentiment", self.sentiment_weight)
self.regime_weight = cw.get("regime", self.regime_weight)
except Exception:
pass
"""
Calculate the confluence score from all signal sources.
@@ -93,6 +83,16 @@ class SignalAggregator:
Returns:
ConfluenceResult with final score and execution decision.
"""
# Dynamically synchronize with self-learning adaptive weights
try:
from ai.trade_learner import trade_learner
cw = trade_learner.get_confluence_weights()
self.technical_weight = cw.get("technical", self.technical_weight)
self.ai_weight = cw.get("ai_prediction", self.ai_weight)
self.sentiment_weight = cw.get("sentiment", self.sentiment_weight)
self.regime_weight = cw.get("regime", self.regime_weight)
except Exception:
pass
reasons = list(strategy_signal.reasons)
# ── 1. Technical Score (from strategy) ───────────────────────────
+2
View File
@@ -204,6 +204,8 @@ def test_trade_learner_mistake_guard_adaptation():
try:
learner = TradeLearner()
# Reset multipliers so the test doesn't depend on accumulated DB state
learner.strategy_multipliers = {"scalping": 1.0, "day_trading": 1.0, "swing_trading": 1.0}
# Add a mock mistake memory
learner.mistake_memory.append({
"strategy": "scalping",