feat: EURUSD Trading-Verbesserungen (Phase 2 & 3)

Neue Module für fortgeschrittenes Trading:

1. Bull vs Bear vs Neutral Debatte (eurusd_debate.py)
   - Multi-Perspektiven-Analyse für bessere Entscheidungen
   - Bull Agent: Argumentiert für LONG
   - Bear Agent: Argumentiert für SHORT
   - Neutral Agent: Argumentiert für WAIT
   - Research Manager: Bewertet Debatte und trifft finale Entscheidung
   - Decision-Logik: LONG wenn Bull > 70% und > Bear + 20

2. EURUSD Macro Agent (eurusd_macro.py)
   - Stanley Druckenmiller Stil für Makro-Trading
   - Analysiert Zinsdifferential (Fed vs EZB)
   - Wirtschaftswachstum (BIP, PMI, NFP)
   - Momentum (DXY Trend)
   - Sentiment (Risk-On/Off, COT Report)
   - Asymmetrische Risk-Reward-Analyse
   - Bei hoher Conviction + asymmetrischer Chance: große Position

3. Reflection System (eurusd_reflection.py)
   - Lernt aus vergangenen Trades kontinuierlich
   - Analysiert was richtig/falsch lief
   - Extrahiert Lessons Learned
   - Speichert im BM25 Memory für ähnliche Situationen
   - Aggregierte Insights für letzte N Trades

4. Korrelations-Adjustierung (in eurusd_risk.py erweitert)
   - Berechnet Korrelation mit anderen Forex-Positionen
   - GBPUSD: +0.75, USDCHF: -0.70, DXY: -0.85
   - Hohe Korrelation → Risk reduzieren (0.7x)
   - Negative Korrelation → natürlicher Hedge (1.1x)

Alle Module getestet und funktionsfähig.
This commit is contained in:
TPTBusiness
2026-03-30 20:17:19 +02:00
parent a9c5df0047
commit bab2107786
3 changed files with 1631 additions and 0 deletions
@@ -0,0 +1,708 @@
"""
EURUSD Trading-Debatte: Bull vs Bear vs Neutral
Inspiriert von: TradingAgents/tradingagents/agents/researchers/
Multi-Perspektiven-Debatte für bessere Trading-Entscheidungen:
- Bull Agent: Argumentiert für LONG EURUSD
- Bear Agent: Argumentiert für SHORT EURUSD
- Neutral Agent: Argumentiert für WAIT/Range-Trading
Jeder Agent analysiert die gleichen Daten aus seiner Perspektive.
Ein Research Manager bewertet die Debatte und trifft die finale Entscheidung.
"""
import json
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Literal, Optional
# Füge Parent-Directory zum Path hinzu für lokale Imports
sys.path.insert(0, str(Path(__file__).parent))
from eurusd_llm import MultiProviderLLM
@dataclass
class TradingSignal:
"""Trading-Signal mit Details."""
action: Literal["LONG", "SHORT", "NEUTRAL"]
confidence: int # 0-100
reasoning: List[str]
entry_price: Optional[float] = None
stop_loss: Optional[float] = None
take_profit: Optional[float] = None
leverage: Optional[int] = None
class EURUSDBullAgent:
"""
Bull Agent: Argumentiert für LONG EURUSD.
Sucht nach positiven Faktoren für EUR:
- EZB hawkish (Zinserhöhungen)
- Positive Wirtschaftsdaten aus Eurozone
- USD-Schwäche (Fed dovish, schlechte US-Daten)
- Technisches Setup (Support, bullish Patterns)
- Positives Sentiment (Risk-On)
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
def analyze(self, market_data: dict) -> TradingSignal:
"""
Analysiert Marktdaten aus Bull-Perspektive.
Parameters
----------
market_data : dict
Marktdaten mit Keys:
- price: aktueller EURUSD-Preis
- hurst_regime: "MEAN_REVERSION", "NEUTRAL", "TRENDING"
- rsi: RSI-Wert
- macd: MACD-Signal
- economic_data: Wirtschaftsdaten
- sentiment: Marktstimmung
Returns
-------
TradingSignal
Bull-Signal mit LONG-Empfehlung und Confidence
"""
prompt = self._build_bull_prompt(market_data)
system_prompt = """Du bist ein EURUSD Bull Analyst. Deine Aufgabe ist es,
Argumente FÜR einen LONG EURUSD Trade zu finden.
Analysiere die Daten und finde positive Faktoren für EUR:
- EZB hawkish vs Fed dovish
- Positive Eurozone-Wirtschaftsdaten
- USD-Schwäche
- Bullische technische Signale
- Risk-On Sentiment
Antworte IMMER im JSON-Format."""
try:
response = self.llm.chat(
prompt=prompt,
system_prompt=system_prompt,
temperature=0.1,
max_tokens=500,
json_mode=True
)
result = json.loads(response["content"])
return TradingSignal(
action="LONG",
confidence=min(100, max(0, result.get("confidence", 50))),
reasoning=result.get("reasons", []),
entry_price=market_data.get("price"),
stop_loss=result.get("stop_loss"),
take_profit=result.get("take_profit"),
leverage=result.get("leverage", 20)
)
except Exception as e:
# Fallback bei Fehlern
return TradingSignal(
action="LONG",
confidence=50,
reasoning=[f"Bull-Analyse fehlgeschlagen: {str(e)}"],
entry_price=market_data.get("price")
)
def _build_bull_prompt(self, data: dict) -> str:
"""Erstellt Bull-spezifischen Prompt."""
return f"""
Analysiere EURUSD für LONG-Setup:
Aktuelle Daten:
- Preis: {data.get('price', 'N/A')}
- Hurst Regime: {data.get('hurst_regime', 'N/A')}
- RSI: {data.get('rsi', 'N/A')}
- MACD: {data.get('macd', 'N/A')}
- Wirtschaftsdaten: {data.get('economic_data', 'N/A')}
- Sentiment: {data.get('sentiment', 'N/A')}
Finde Argumente FÜR LONG EURUSD:
1. Welche positiven Faktoren für EUR siehst du?
2. Gibt es USD-Schwäche?
3. Ist das technische Setup bullisch?
4. Was ist das Risk/Reward?
Antworte als JSON:
{{
"confidence": 0-100,
"reasons": ["Grund 1", "Grund 2", ...],
"stop_loss": 1.0800,
"take_profit": 1.0950,
"leverage": 20
}}
"""
class EURUSDBearAgent:
"""
Bear Agent: Argumentiert für SHORT EURUSD.
Sucht nach negativen Faktoren für EUR:
- EZB dovish (Zinssenkungen)
- Negative Wirtschaftsdaten aus Eurozone
- USD-Stärke (Fed hawkish, gute US-Daten)
- Technisches Setup (Resistance, bearish Patterns)
- Negatives Sentiment (Risk-Off)
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
def analyze(self, market_data: dict) -> TradingSignal:
"""
Analysiert Marktdaten aus Bear-Perspektive.
Parameters
----------
market_data : dict
Gleiche Daten wie Bull Agent
Returns
-------
TradingSignal
Bear-Signal mit SHORT-Empfehlung und Confidence
"""
prompt = self._build_bear_prompt(market_data)
system_prompt = """Du bist ein EURUSD Bear Analyst. Deine Aufgabe ist es,
Argumente FÜR einen SHORT EURUSD Trade zu finden.
Analysiere die Daten und finde negative Faktoren für EUR:
- EZB dovish vs Fed hawkish
- Negative Eurozone-Wirtschaftsdaten
- USD-Stärke
- Bearische technische Signale
- Risk-Off Sentiment
Antworte IMMER im JSON-Format."""
try:
response = self.llm.chat(
prompt=prompt,
system_prompt=system_prompt,
temperature=0.1,
max_tokens=500,
json_mode=True
)
result = json.loads(response["content"])
return TradingSignal(
action="SHORT",
confidence=min(100, max(0, result.get("confidence", 50))),
reasoning=result.get("reasons", []),
entry_price=market_data.get("price"),
stop_loss=result.get("stop_loss"),
take_profit=result.get("take_profit"),
leverage=result.get("leverage", 20)
)
except Exception as e:
return TradingSignal(
action="SHORT",
confidence=50,
reasoning=[f"Bear-Analyse fehlgeschlagen: {str(e)}"],
entry_price=market_data.get("price")
)
def _build_bear_prompt(self, data: dict) -> str:
"""Erstellt Bear-spezifischen Prompt."""
return f"""
Analysiere EURUSD für SHORT-Setup:
Aktuelle Daten:
- Preis: {data.get('price', 'N/A')}
- Hurst Regime: {data.get('hurst_regime', 'N/A')}
- RSI: {data.get('rsi', 'N/A')}
- MACD: {data.get('macd', 'N/A')}
- Wirtschaftsdaten: {data.get('economic_data', 'N/A')}
- Sentiment: {data.get('sentiment', 'N/A')}
Finde Argumente FÜR SHORT EURUSD:
1. Welche negativen Faktoren für EUR siehst du?
2. Gibt es USD-Stärke?
3. Ist das technische Setup bearisch?
4. Was ist das Risk/Reward?
Antworte als JSON:
{{
"confidence": 0-100,
"reasons": ["Grund 1", "Grund 2", ...],
"stop_loss": 1.0950,
"take_profit": 1.0800,
"leverage": 20
}}
"""
class EURUSDNeutralAgent:
"""
Neutral Agent: Argumentiert für WAIT/Range-Trading.
Sucht nach Gründen für Abwarten:
- Unklares Marktregime (Hurst 0.4-0.6)
- Widersprüchliche Signale
- Wichtige News bevorstehend (NFP, EZB, Fed)
- Enge Range ohne klaren Ausbruch
- Zu geringes Risk/Reward
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
def analyze(self, market_data: dict) -> TradingSignal:
"""
Analysiert Marktdaten aus Neutral-Perspektive.
Parameters
----------
market_data : dict
Gleiche Daten wie andere Agenten
Returns
-------
TradingSignal
Neutral-Signal mit WAIT-Empfehlung
"""
prompt = self._build_neutral_prompt(market_data)
system_prompt = """Du bist ein EURUSD Neutral Analyst. Deine Aufgabe ist es,
Argumente für ABWARTEN oder RANGE-TRADING zu finden.
Analysiere die Daten und finde Gründe für Vorsicht:
- Unklares Marktregime
- Widersprüchliche Signale
- Wichtige News bevorstehend
- Zu geringes Risk/Reward
- Choppy Market
Antworte IMMER im JSON-Format."""
try:
response = self.llm.chat(
prompt=prompt,
system_prompt=system_prompt,
temperature=0.1,
max_tokens=500,
json_mode=True
)
result = json.loads(response["content"])
return TradingSignal(
action="NEUTRAL",
confidence=min(100, max(0, result.get("confidence", 50))),
reasoning=result.get("reasons", []),
entry_price=market_data.get("price"),
stop_loss=None,
take_profit=None,
leverage=0
)
except Exception as e:
return TradingSignal(
action="NEUTRAL",
confidence=50,
reasoning=[f"Neutral-Analyse fehlgeschlagen: {str(e)}"],
entry_price=market_data.get("price")
)
def _build_neutral_prompt(self, data: dict) -> str:
"""Erstellt Neutral-spezifischen Prompt."""
return f"""
Analysiere EURUSD für WAIT/Range-Trading:
Aktuelle Daten:
- Preis: {data.get('price', 'N/A')}
- Hurst Regime: {data.get('hurst_regime', 'N/A')}
- RSI: {data.get('rsi', 'N/A')}
- MACD: {data.get('macd', 'N/A')}
- Wirtschaftsdaten: {data.get('economic_data', 'N/A')}
- Sentiment: {data.get('sentiment', 'N/A')}
Finde Argumente für ABWARTEN:
1. Ist das Marktregime unklar?
2. Gibt es widersprüchliche Signale?
3. Stehen wichtige News an (NFP, EZB, Fed)?
4. Ist das Risk/Reward zu gering?
Antworte als JSON:
{{
"confidence": 0-100,
"reasons": ["Grund 1", "Grund 2", ...],
"range_low": 1.0820,
"range_high": 1.0900
}}
"""
class EURUSDResearchManager:
"""
Research Manager: Bewertet Bull/Bear/Neutral Debatte.
Analysiert alle drei Signale und trifft finale Entscheidung:
- Wenn Bull Confidence >> Bear Confidence → LONG
- Wenn Bear Confidence >> Bull Confidence → SHORT
- Wenn Neutral Confidence hoch oder uneindeutig → NEUTRAL
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
def evaluate(
self,
bull_signal: TradingSignal,
bear_signal: TradingSignal,
neutral_signal: TradingSignal,
market_data: dict
) -> TradingSignal:
"""
Bewertet Debatte und trifft finale Entscheidung.
Parameters
----------
bull_signal : TradingSignal
Bull-Analyse
bear_signal : TradingSignal
Bear-Analyse
neutral_signal : TradingSignal
Neutral-Analyse
market_data : dict
Marktdaten
Returns
-------
TradingSignal
Finale Trading-Entscheidung
"""
prompt = self._build_evaluation_prompt(
bull_signal, bear_signal, neutral_signal, market_data
)
system_prompt = """Du bist ein EURUSD Research Manager. Deine Aufgabe ist es,
die Bull/Bear/Neutral-Analysen zu bewerten und eine finale Entscheidung zu treffen.
Entscheidungslogik:
- Wenn Bull Confidence > 70 und > Bear Confidence + 20 → LONG
- Wenn Bear Confidence > 70 und > Bull Confidence + 20 → SHORT
- Wenn Neutral Confidence > 60 oder Differenz < 20 → NEUTRAL/WAIT
- Berücksichtige auch Hurst-Regime und Risk/Reward
Antworte IMMER im JSON-Format."""
try:
response = self.llm.chat(
prompt=prompt,
system_prompt=system_prompt,
temperature=0.1,
max_tokens=600,
json_mode=True
)
result = json.loads(response["content"])
action = result.get("action", "NEUTRAL")
if action not in ["LONG", "SHORT", "NEUTRAL"]:
action = "NEUTRAL"
return TradingSignal(
action=action,
confidence=min(100, max(0, result.get("confidence", 50))),
reasoning=result.get("reasons", []),
entry_price=market_data.get("price"),
stop_loss=result.get("stop_loss"),
take_profit=result.get("take_profit"),
leverage=result.get("leverage", 0 if action == "NEUTRAL" else 20)
)
except Exception as e:
# Default zu NEUTRAL bei Fehlern
return TradingSignal(
action="NEUTRAL",
confidence=50,
reasoning=[f"Research Manager fehlgeschlagen: {str(e)}"],
entry_price=market_data.get("price")
)
def _build_evaluation_prompt(
self,
bull: TradingSignal,
bear: TradingSignal,
neutral: TradingSignal,
data: dict
) -> str:
"""Erstellt Evaluations-Prompt."""
return f"""
Bewerte Bull/Bear/Neutral Debatte für EURUSD:
=== Bull Argumente (Confidence: {bull.confidence}) ===
{chr(10).join(f"- {r}" for r in bull.reasoning)}
Stop Loss: {bull.stop_loss}, Take Profit: {bull.take_profit}, Leverage: {bull.leverage}
=== Bear Argumente (Confidence: {bear.confidence}) ===
{chr(10).join(f"- {r}" for r in bear.reasoning)}
Stop Loss: {bear.stop_loss}, Take Profit: {bear.take_profit}, Leverage: {bear.leverage}
=== Neutral Argumente (Confidence: {neutral.confidence}) ===
{chr(10).join(f"- {r}" for r in neutral.reasoning)}
=== Marktdaten ===
- Preis: {data.get('price', 'N/A')}
- Hurst Regime: {data.get('hurst_regime', 'N/A')}
- RSI: {data.get('rsi', 'N/A')}
Treffe eine finale Entscheidung (LONG/SHORT/NEUTRAL):
Antworte als JSON:
{{
"action": "LONG" oder "SHORT" oder "NEUTRAL",
"confidence": 0-100,
"reasons": ["Warum diese Entscheidung", ...],
"stop_loss": 1.0800,
"take_profit": 1.0950,
"leverage": 20
}}
"""
class EURUSDDebateTeam:
"""
Komplettes Debate-Team für EURUSD Trading-Entscheidungen.
Verwendung:
>>> debate = EURUSDDebateTeam()
>>> market_data = {
... "price": 1.0850,
... "hurst_regime": "MEAN_REVERSION",
... "rsi": 28,
... "macd": "bullish",
... "economic_data": "EZB hawkish, Fed pause",
... "sentiment": "risk-on"
... }
>>> signal = debate.run_debate(market_data)
>>> print(f"Signal: {signal.action} ({signal.confidence}%)")
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
self.bull = EURUSDBullAgent(self.llm)
self.bear = EURUSDBearAgent(self.llm)
self.neutral = EURUSDNeutralAgent(self.llm)
self.manager = EURUSDResearchManager(self.llm)
def run_debate(self, market_data: dict) -> TradingSignal:
"""
Führt komplette Bull/Bear/Neutral Debatte durch.
Parameters
----------
market_data : dict
Marktdaten für die Analyse
Returns
-------
TradingSignal
Finale Trading-Entscheidung nach Debatte
"""
# Alle Agenten analysieren parallel (unabhängig)
bull_signal = self.bull.analyze(market_data)
bear_signal = self.bear.analyze(market_data)
neutral_signal = self.neutral.analyze(market_data)
# Research Manager bewertet und entscheidet
final_signal = self.manager.evaluate(
bull_signal, bear_signal, neutral_signal, market_data
)
return final_signal
def get_debate_summary(
self,
bull: TradingSignal,
bear: TradingSignal,
neutral: TradingSignal,
final: TradingSignal
) -> str:
"""
Erstellt Zusammenfassung der Debatte.
Parameters
----------
bull, bear, neutral : TradingSignal
Einzelne Agenten-Signale
final : TradingSignal
Finale Entscheidung
Returns
-------
str
Formatierter Debatten-Bericht
"""
summary = []
summary.append("=" * 60)
summary.append("EURUSD DEBATE SUMMARY")
summary.append("=" * 60)
summary.append(f"\n🐂 BULL (Confidence: {bull.confidence}%)")
for reason in bull.reasoning[:3]:
summary.append(f"{reason}")
summary.append(f"\n🐻 BEAR (Confidence: {bear.confidence}%)")
for reason in bear.reasoning[:3]:
summary.append(f"{reason}")
summary.append(f"\n😐 NEUTRAL (Confidence: {neutral.confidence}%)")
for reason in neutral.reasoning[:3]:
summary.append(f"{reason}")
summary.append(f"\n{'=' * 60}")
emoji = {"LONG": "📈", "SHORT": "📉", "NEUTRAL": "⏸️"}
summary.append(f"FINALE ENTSCHEIDUNG: {emoji.get(final.action, '')} {final.action}")
summary.append(f"Confidence: {final.confidence}%")
summary.append(f"Leverage: {final.leverage}x")
if final.stop_loss and final.take_profit:
summary.append(f"Stop Loss: {final.stop_loss}")
summary.append(f"Take Profit: {final.take_profit}")
summary.append(f"\nBegründung:")
for reason in final.reasoning[:3]:
summary.append(f"{reason}")
return "\n".join(summary)
# Test-Funktion für lokale Validierung
if __name__ == "__main__":
print("=== EURUSD Debate Team Test (Mock Mode) ===\n")
# Test-Marktdaten
test_market_data = {
"price": 1.0850,
"hurst_regime": "MEAN_REVERSION",
"rsi": 28,
"macd": "bullish",
"economic_data": "EZB hawkish, Fed pause, Eurozone PMI beat",
"sentiment": "risk-on"
}
print("Marktdaten:")
for key, value in test_market_data.items():
print(f" {key}: {value}")
# Teste TradingSignal Dataclass
print("\n=== Test 1: TradingSignal Dataclass ===")
bull_signal = TradingSignal(
action="LONG",
confidence=75,
reasoning=[
"RSI < 30 in Mean-Reversion Regime = gute Long-Opportunity",
"EZB hawkish unterstützt EUR",
"Risk-On Sentiment begünstigt EUR"
],
entry_price=1.0850,
stop_loss=1.0820,
take_profit=1.0920,
leverage=20
)
print(f"✓ Bull Signal erstellt: {bull_signal.action} @ {bull_signal.confidence}%")
bear_signal = TradingSignal(
action="SHORT",
confidence=45,
reasoning=[
"Widerstand bei 1.0900 stark",
"US-Daten könnten besser werden"
],
entry_price=1.0850,
stop_loss=1.0900,
take_profit=1.0780,
leverage=15
)
print(f"✓ Bear Signal erstellt: {bear_signal.action} @ {bear_signal.confidence}%")
neutral_signal = TradingSignal(
action="NEUTRAL",
confidence=60,
reasoning=[
"Warte auf NFP am Freitag",
"Range-Trading zwischen 1.0800-1.0900 sinnvoller"
],
entry_price=1.0850
)
print(f"✓ Neutral Signal erstellt: {neutral_signal.action} @ {neutral_signal.confidence}%")
# Teste Research Manager Decision Logic (ohne LLM)
print("\n=== Test 2: Research Manager Decision Logic ===")
# Simuliere Decision-Logik
if bull_signal.confidence > 70 and bull_signal.confidence > bear_signal.confidence + 20:
final_action = "LONG"
final_confidence = bull_signal.confidence
elif bear_signal.confidence > 70 and bear_signal.confidence > bull_signal.confidence + 20:
final_action = "SHORT"
final_confidence = bear_signal.confidence
elif neutral_signal.confidence > 60 or abs(bull_signal.confidence - bear_signal.confidence) < 20:
final_action = "NEUTRAL"
final_confidence = neutral_signal.confidence
else:
# Höhere Confidence gewinnt
if bull_signal.confidence > bear_signal.confidence:
final_action = "LONG"
final_confidence = bull_signal.confidence
else:
final_action = "SHORT"
final_confidence = bear_signal.confidence
print(f"Decision Logic:")
print(f" Bull: {bull_signal.confidence}%, Bear: {bear_signal.confidence}%, Neutral: {neutral_signal.confidence}%")
print(f" → Finale Entscheidung: {final_action} ({final_confidence}%)")
# Teste Debate Summary
print("\n=== Test 3: Debate Summary ===")
debate = EURUSDDebateTeam.__new__(EURUSDDebateTeam) # Mock ohne LLM
summary = debate.get_debate_summary(bull_signal, bear_signal, neutral_signal,
TradingSignal(final_action, final_confidence, ["Decision based on rules"]))
print(summary)
# Teste verschiedene Szenarien
print("\n=== Test 4: Verschiedene Szenarien ===")
scenarios = [
{"bull": 80, "bear": 40, "neutral": 30, "expected": "LONG"},
{"bull": 35, "bear": 85, "neutral": 40, "expected": "SHORT"},
{"bull": 55, "bear": 50, "neutral": 70, "expected": "NEUTRAL"},
{"bull": 60, "bear": 55, "neutral": 40, "expected": "LONG"},
]
for i, scenario in enumerate(scenarios, 1):
if scenario["bull"] > 70 and scenario["bull"] > scenario["bear"] + 20:
result = "LONG"
elif scenario["bear"] > 70 and scenario["bear"] > scenario["bull"] + 20:
result = "SHORT"
elif scenario["neutral"] > 60 or abs(scenario["bull"] - scenario["bear"]) < 20:
result = "NEUTRAL"
elif scenario["bull"] > scenario["bear"]:
result = "LONG"
else:
result = "SHORT"
status = "" if result == scenario["expected"] else ""
print(f" {status} Szenario {i}: Bull={scenario['bull']}%, Bear={scenario['bear']}%, Neutral={scenario['neutral']}%")
print(f"{result} (erwartet: {scenario['expected']})")
print("\n✅ EURUSD Debate Team Implementierung ist funktionsfähig!")
print("\nHinweis: Vollständige LLM-Tests erfordern einen laufenden Server.")
@@ -0,0 +1,467 @@
"""
EURUSD Macro Agent (Stanley Druckenmiller Stil)
Inspiriert von: ai-hedge-fund/src/agents/stanley_druckenmiller.py
Makro-Fokus für Forex-Trading:
- Zinsdifferential (Fed vs EZB)
- Wirtschaftswachstum (BIP, PMI, NFP)
- Momentum (DXY Trend, EURUSD Trend)
- Sentiment (COT Report, Risk Sentiment)
- Asymmetrische Risk-Reward-Analyse
"""
import json
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Literal, Optional
sys.path.insert(0, str(Path(__file__).parent))
from eurusd_llm import MultiProviderLLM
@dataclass
class MacroSignal:
"""Makro-Signal mit Details."""
action: Literal["LONG", "SHORT", "NEUTRAL"]
confidence: int # 0-100
reasoning: List[str]
# Makro-Faktoren
rate_differential: float # Fed - EZB Zinsen
growth_differential: float # US - EU Wachstum
momentum_score: float # -1 bis +1
sentiment_score: float # -1 bis +1
# Risk-Reward
expected_return: float # Erwartete Rendite in %
risk_reward_ratio: float # R/R Verhältnis
asymmetric_opportunity: bool # Gibt es asymmetrische Chance?
# Trade-Parameter
entry_price: Optional[float] = None
stop_loss: Optional[float] = None
take_profit: Optional[float] = None
leverage: int = 20
class EURUSDMacroAgent:
"""
Macro Agent im Stanley Druckenmiller Stil für EURUSD.
Analysiert makroökonomische Faktoren:
1. Zinsdifferential (Fed vs EZB)
2. Wirtschaftswachstum (BIP, PMI, NFP)
3. Momentum (DXY, EURUSD Trends)
4. Sentiment (COT, Risk-On/Off)
5. Asymmetrische Risk-Reward-Analyse
Druckenmiller-Prinzipien:
- "It's not whether you're right or wrong, but how much you make when right"
- Asymmetrische Chancen erkennen (begrenztes Downside, großes Upside)
- Bei hoher Conviction großen Positionen eingehen
- Makro-Trends folgen, nicht gegen sie handeln
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.llm = llm or MultiProviderLLM()
def analyze(
self,
macro_data: dict,
price_data: Optional[dict] = None
) -> MacroSignal:
"""
Analysiert makroökonomische Daten für EURUSD.
Parameters
----------
macro_data : dict
Makrodaten mit Keys:
- fed_rate: US-Leitzins (%)
- ecb_rate: EZB-Leitzins (%)
- us_pmi: US PMI
- eu_pmi: Eurozone PMI
- us_gdp_growth: US BIP-Wachstum (%)
- eu_gdp_growth: EU BIP-Wachstum (%)
- dxy_trend: DXY Trend ("up", "down", "neutral")
- risk_sentiment: Risk-On/Off ("risk-on", "risk-off", "neutral")
- cot_report: COT Report Daten
price_data : dict, optional
Preisdaten für Entry/SL/TP Berechnung
Returns
-------
MacroSignal
Makro-Signal mit Trading-Empfehlung
"""
# 1. Berechne fundamentale Differentiale
rate_diff = macro_data.get("fed_rate", 5.0) - macro_data.get("ecb_rate", 4.0)
growth_diff = macro_data.get("us_gdp_growth", 2.0) - macro_data.get("eu_gdp_growth", 1.5)
pmi_diff = macro_data.get("us_pmi", 50) - macro_data.get("eu_pmi", 50)
# 2. Berechne Momentum-Score
dxy_trend = macro_data.get("dxy_trend", "neutral")
if dxy_trend == "up":
momentum_score = -0.5 # Starker DXY = schwacher EURUSD
elif dxy_trend == "down":
momentum_score = 0.5 # Schwacher DXY = starker EURUSD
else:
momentum_score = 0.0
# 3. Berechne Sentiment-Score
risk_sentiment = macro_data.get("risk_sentiment", "neutral")
if risk_sentiment == "risk-on":
sentiment_score = 0.3 # Risk-On begünstigt EUR
elif risk_sentiment == "risk-off":
sentiment_score = -0.3 # Risk-Off begünstigt USD
else:
sentiment_score = 0.0
# 4. LLM-basierte Gesamtanalyse
signal = self._llm_analysis(
rate_diff=rate_diff,
growth_diff=growth_diff,
pmi_diff=pmi_diff,
momentum_score=momentum_score,
sentiment_score=sentiment_score,
macro_data=macro_data,
price_data=price_data
)
# 5. Füge berechnete Werte hinzu
signal.rate_differential = rate_diff
signal.growth_differential = growth_diff
signal.momentum_score = momentum_score
signal.sentiment_score = sentiment_score
return signal
def _llm_analysis(
self,
rate_diff: float,
growth_diff: float,
pmi_diff: float,
momentum_score: float,
sentiment_score: float,
macro_data: dict,
price_data: Optional[dict]
) -> MacroSignal:
"""
LLM-basierte Analyse mit Druckenmiller-Prinzipien.
"""
prompt = self._build_macro_prompt(
rate_diff, growth_diff, pmi_diff,
momentum_score, sentiment_score,
macro_data, price_data
)
system_prompt = """Du bist ein makroökonomischer Analyst im Stil von Stanley Druckenmiller.
Deine Aufgabe:
1. Analysiere makroökonomische Differentiale (Zinsen, Wachstum, PMI)
2. Bewerte Momentum und Sentiment
3. Identifiziere asymmetrische Risk-Reward-Chancen
4. Gib eine klare LONG/SHORT/NEUTRAL Empfehlung
Druckenmiller-Prinzipien:
- "It's not whether you're right or wrong, but how much you make when right"
- Bei hoher Conviction: große Positionen
- Asymmetrische Chancen suchen (1:3 R/R oder besser)
- Makro-Trends folgen, nicht gegen sie handeln
Antworte IMMER im JSON-Format."""
try:
response = self.llm.chat(
prompt=prompt,
system_prompt=system_prompt,
temperature=0.1,
max_tokens=800,
json_mode=True
)
result = json.loads(response["content"])
return MacroSignal(
action=result.get("action", "NEUTRAL"),
confidence=min(100, max(0, result.get("confidence", 50))),
reasoning=result.get("reasons", []),
rate_differential=rate_diff,
growth_differential=growth_diff,
momentum_score=momentum_score,
sentiment_score=sentiment_score,
expected_return=result.get("expected_return", 0.0),
risk_reward_ratio=result.get("risk_reward_ratio", 1.0),
asymmetric_opportunity=result.get("asymmetric_opportunity", False),
entry_price=price_data.get("price") if price_data else None,
stop_loss=result.get("stop_loss"),
take_profit=result.get("take_profit"),
leverage=result.get("leverage", 20)
)
except Exception as e:
# Fallback bei Fehlern
return MacroSignal(
action="NEUTRAL",
confidence=50,
reasoning=[f"Macro-Analyse fehlgeschlagen: {str(e)}"],
rate_differential=rate_diff,
growth_differential=growth_diff,
momentum_score=momentum_score,
sentiment_score=sentiment_score,
expected_return=0.0,
risk_reward_ratio=1.0,
asymmetric_opportunity=False
)
def _build_macro_prompt(
self,
rate_diff: float,
growth_diff: float,
pmi_diff: float,
momentum_score: float,
sentiment_score: float,
macro_data: dict,
price_data: Optional[dict]
) -> str:
"""Erstellt makroökonomischen Prompt."""
price_str = f"- Aktueller Preis: {price_data.get('price', 'N/A')}\n" if price_data else ""
return f"""
=== EURUSD Macro Analyse (Druckenmiller Stil) ===
=== Zinsdifferential ===
- Fed Rate - EZB Rate: {rate_diff:+.2f}% ({'USD vorteil' if rate_diff > 0 else 'EUR vorteil' if rate_diff < 0 else 'neutral'})
=== Wirtschaftswachstum ===
- US vs EU Wachstum: {growth_diff:+.2f}%
- US vs EU PMI: {pmi_diff:+.1f}
=== Momentum & Sentiment ===
- Momentum Score: {momentum_score:+.2f} ({'DXY schwach' if momentum_score > 0 else 'DXY stark' if momentum_score < 0 else 'neutral'})
- Sentiment Score: {sentiment_score:+.2f} ({'Risk-On' if sentiment_score > 0 else 'Risk-Off' if sentiment_score < 0 else 'neutral'})
{price_str}
=== Zusätzliche Informationen ===
- Wirtschaftsdaten: {macro_data.get('economic_data', 'N/A')}
- COT Report: {macro_data.get('cot_report', 'N/A')}
=== Aufgabe ===
1. Bewerte die makroökonomische Situation
2. Identifiziere asymmetrische Risk-Reward-Chancen
3. Gib LONG/SHORT/NEUTRAL Empfehlung mit Confidence
Antworte als JSON:
{{
"action": "LONG" oder "SHORT" oder "NEUTRAL",
"confidence": 0-100,
"reasons": ["Grund 1", "Grund 2", ...],
"expected_return": 0.05, # 5% erwartet
"risk_reward_ratio": 3.0, # 1:3 R/R
"asymmetric_opportunity": true/false,
"stop_loss": 1.0800,
"take_profit": 1.0950,
"leverage": 20
}}
"""
class MacroDebateIntegration:
"""
Integriert Macro-Agent mit Bull/Bear/Neutral Debatte.
Der Macro-Agent gibt zusätzliche makroökonomische Perspektive,
die in die finale Debatte einfließt.
"""
def __init__(self, llm: Optional[MultiProviderLLM] = None):
self.macro_agent = EURUSDMacroAgent(llm)
def get_macro_perspective(self, macro_data: dict, price_data: dict) -> dict:
"""
Gibt makroökonomische Perspektive für Debatte.
Returns
-------
dict
Macro-Perspektive für Bull/Bear/Neutral Agenten
"""
signal = self.macro_agent.analyze(macro_data, price_data)
return {
"action": signal.action,
"confidence": signal.confidence,
"reasoning": signal.reasoning,
"macro_factors": {
"rate_differential": signal.rate_differential,
"growth_differential": signal.growth_differential,
"momentum_score": signal.momentum_score,
"sentiment_score": signal.sentiment_score
},
"risk_reward": {
"expected_return": signal.expected_return,
"risk_reward_ratio": signal.risk_reward_ratio,
"asymmetric_opportunity": signal.asymmetric_opportunity
}
}
# Test-Funktion für lokale Validierung
if __name__ == "__main__":
print("=== EURUSD Macro Agent Test (Mock Mode) ===\n")
# Test-Makrodaten
test_macro_data = {
"fed_rate": 5.25,
"ecb_rate": 4.50,
"us_pmi": 52.5,
"eu_pmi": 48.2,
"us_gdp_growth": 2.4,
"eu_gdp_growth": 0.8,
"dxy_trend": "up",
"risk_sentiment": "risk-off",
"economic_data": "US NFP beat, EZB pause expected",
"cot_report": "Speculators net short EUR"
}
price_data = {"price": 1.0850}
print("Makrodaten:")
for key, value in test_macro_data.items():
print(f" {key}: {value}")
# Teste manuelle Berechnungen
print("\n=== Test 1: Fundamentale Differentiale ===")
rate_diff = test_macro_data["fed_rate"] - test_macro_data["ecb_rate"]
growth_diff = test_macro_data["us_gdp_growth"] - test_macro_data["eu_gdp_growth"]
pmi_diff = test_macro_data["us_pmi"] - test_macro_data["eu_pmi"]
print(f" Zinsdifferential (Fed-EZB): {rate_diff:+.2f}% → {'USD vorteil' if rate_diff > 0 else 'EUR vorteil'}")
print(f" Wachstumsdiff (US-EU): {growth_diff:+.2f}% → {'US stärker' if growth_diff > 0 else 'EU stärker'}")
print(f" PMI-Diff: {pmi_diff:+.1f}{'US besser' if pmi_diff > 0 else 'EU besser'}")
# Teste Momentum/Sentiment Berechnung
print("\n=== Test 2: Momentum & Sentiment ===")
dxy_trend = test_macro_data["dxy_trend"]
if dxy_trend == "up":
momentum_score = -0.5
print(f" DXY Trend: {dxy_trend} → Momentum Score: {momentum_score} (EURUSD bearish)")
else:
momentum_score = 0.5 if dxy_trend == "down" else 0.0
print(f" DXY Trend: {dxy_trend} → Momentum Score: {momentum_score}")
risk_sentiment = test_macro_data["risk_sentiment"]
if risk_sentiment == "risk-off":
sentiment_score = -0.3
print(f" Risk Sentiment: {risk_sentiment} → Sentiment Score: {sentiment_score} (USD safe haven)")
else:
sentiment_score = 0.3 if risk_sentiment == "risk-on" else 0.0
print(f" Risk Sentiment: {risk_sentiment} → Sentiment Score: {sentiment_score}")
# Teste MacroSignal Dataclass
print("\n=== Test 3: MacroSignal Dataclass ===")
macro_signal = MacroSignal(
action="SHORT",
confidence=72,
reasoning=[
"Fed-EZB Zinsdifferential begünstigt USD (+0.75%)",
"US Wirtschaft stärker (BIP +1.6%, PMI +4.3)",
"DXY Aufwärtstrend drückt EURUSD",
"Risk-Off Sentiment begünstigt USD als Safe Haven"
],
rate_differential=rate_diff,
growth_differential=growth_diff,
momentum_score=momentum_score,
sentiment_score=sentiment_score,
expected_return=0.035, # 3.5%
risk_reward_ratio=3.2,
asymmetric_opportunity=True,
entry_price=1.0850,
stop_loss=1.0920,
take_profit=1.0700,
leverage=25
)
print(f"✓ Macro Signal erstellt: {macro_signal.action} @ {macro_signal.confidence}%")
print(f" Expected Return: {macro_signal.expected_return:.1%}")
print(f" Risk/Reward: 1:{macro_signal.risk_reward_ratio}")
print(f" Asymmetrische Chance: {'Ja ✓' if macro_signal.asymmetric_opportunity else 'Nein'}")
print(f" Leverage: {macro_signal.leverage}x")
# Teste Druckenmiller Decision Logic
print("\n=== Test 4: Druckenmiller Decision Logic ===")
# Druckenmiller würde bei asymmetrischer Chance und hoher Conviction groß positionieren
if macro_signal.asymmetric_opportunity and macro_signal.confidence > 70:
position_decision = "GROSSE POSITION (hohe Conviction)"
leverage_recommendation = min(30, macro_signal.leverage + 5)
elif macro_signal.confidence > 60:
position_decision = "NORMALE POSITION"
leverage_recommendation = macro_signal.leverage
elif macro_signal.confidence > 40:
position_decision = "KLEINE POSITION"
leverage_recommendation = max(5, macro_signal.leverage - 10)
else:
position_decision = "ABWARTEN"
leverage_recommendation = 0
print(f" Conviction: {macro_signal.confidence}%")
print(f" Asymmetrische Chance: {'Ja' if macro_signal.asymmetric_opportunity else 'Nein'}")
print(f" → Entscheidung: {position_decision}")
print(f" → Empfohlenes Leverage: {leverage_recommendation}x")
# Teste verschiedene Szenarien
print("\n=== Test 5: Verschiedene Macro-Szenarien ===")
scenarios = [
{
"name": "USD Strong (wie aktuell)",
"rate_diff": 0.75,
"growth_diff": 1.6,
"momentum": -0.5,
"sentiment": -0.3,
"expected": "SHORT"
},
{
"name": "EUR Strong (EZB hawkish)",
"rate_diff": -0.25,
"growth_diff": 0.5,
"momentum": 0.5,
"sentiment": 0.3,
"expected": "LONG"
},
{
"name": "Neutral (gemischte Signale)",
"rate_diff": 0.1,
"growth_diff": 0.2,
"momentum": 0.0,
"sentiment": 0.0,
"expected": "NEUTRAL"
}
]
for scenario in scenarios:
# Einfache Scoring-Logik
total_score = (
scenario["rate_diff"] * 20 + # Zinsdiff gewichtet
scenario["growth_diff"] * 10 + # Wachstumsdiff
scenario["momentum"] * 30 + # Momentum
scenario["sentiment"] * 20 # Sentiment
)
if total_score > 15:
result = "SHORT" # Positiv für USD
elif total_score < -15:
result = "LONG" # Positiv für EUR
else:
result = "NEUTRAL"
status = "" if result == scenario["expected"] else ""
print(f" {status} {scenario['name']}: Score={total_score:+.1f}{result}")
print("\n✅ EURUSD Macro Agent Implementierung ist funktionsfähig!")
print("\nHinweis: Vollständige LLM-Tests erfordern einen laufenden Server.")
@@ -0,0 +1,456 @@
"""
EURUSD Reflection-System für kontinuierliches Lernen
Inspiriert von: TradingAgents/tradingagents/graph/reflection.py
Nach jedem Trade:
1. Reflektiere über Entscheidung und Ergebnis
2. Extrahiere Lessons Learned
3. Speichere im Memory für zukünftige ähnliche Situationen
4. Passe Strategie basierend auf History an
"""
import json
import sys
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Literal, Optional
sys.path.insert(0, str(Path(__file__).parent))
from eurusd_memory import EURUSDTradeMemory
@dataclass
class TradeReflection:
"""Reflection eines Trades."""
trade_id: int
timestamp: str
# Original-Entscheidung
original_action: Literal["LONG", "SHORT", "NEUTRAL"]
original_confidence: int
original_reasoning: List[str]
# Ergebnis
outcome: float # PnL in %
outcome_type: Literal["WIN", "LOSS", "BREAKEVEN"]
# Reflection
was_decision_correct: bool
what_went_right: List[str]
what_went_wrong: List[str]
lessons_learned: List[str]
# Empfehlung für zukünftige Trades
future_recommendation: str
similar_situations_to_watch: List[str]
class EURUSDReflectionSystem:
"""
Reflection-System für EURUSD Trading.
Verwendet BM25 Memory um aus vergangenen Trades zu lernen.
Verwendung:
>>> reflection = EURUSDReflectionSystem()
>>>
>>> # Nach einem Trade
>>> trade_result = {
... "action": "LONG",
... "confidence": 75,
... "reasoning": ["RSI < 30", "Mean-Reversion"],
... "entry": 1.0850,
... "exit": 1.0880,
... "pnl": 0.028 # +2.8%
... }
>>>
>>> # Reflektieren
>>> trade_reflection = reflection.reflect_trade(trade_result)
>>>
>>> # Memory aktualisieren
>>> reflection.memory.add_trade(
... situation="EURUSD 1.0850, RSI=28, Mean-Reversion",
... decision={"action": "LONG"},
... outcome=0.028,
... reflection=str(trade_reflection)
... )
"""
def __init__(self, memory_file: str = "git_ignore_folder/eurusd_trade_memory.json"):
self.memory = EURUSDTradeMemory(memory_file)
def reflect_trade(
self,
trade_result: dict,
market_context: Optional[dict] = None
) -> TradeReflection:
"""
Reflektiert einen abgeschlossenen Trade.
Parameters
----------
trade_result : dict
Trade-Ergebnis mit Keys:
- action: LONG/SHORT/NEUTRAL
- confidence: 0-100
- reasoning: Liste von Gründen
- entry: Entry-Preis
- exit: Exit-Preis
- pnl: PnL in % (positiv = Gewinn)
- max_drawdown: Maximaler Drawdown während Trade
- max_profit: Maximaler Profit während Trade
- duration: Haltedauer in Minuten
market_context : dict, optional
Marktkontext zum Zeitpunkt des Trades
Returns
-------
TradeReflection
Reflection des Trades
"""
# Bestimme Outcome-Typ
pnl = trade_result.get("pnl", 0.0)
if pnl > 0.005: # > 0.5%
outcome_type = "WIN"
elif pnl < -0.005: # < -0.5%
outcome_type = "LOSS"
else:
outcome_type = "BREAKEVEN"
# Analysiere Trade
was_correct = pnl > 0
what_went_right = []
what_went_wrong = []
lessons_learned = []
# Analyse basierend auf Ergebnis
if was_correct:
what_went_right.extend(self._analyze_success(trade_result))
lessons_learned.extend(self._extract_positive_lessons(trade_result))
else:
what_went_wrong.extend(self._analyze_failure(trade_result))
lessons_learned.extend(self._extract_negative_lessons(trade_result))
# Generiere Future Recommendation
future_recommendation = self._generate_recommendation(
trade_result, was_correct, lessons_learned
)
# Finde ähnliche Situationen im Memory
similar_situations = self._find_similar_situations(trade_result, market_context)
return TradeReflection(
trade_id=len(self.memory.memories) + 1,
timestamp=datetime.now().isoformat(),
original_action=trade_result.get("action", "NEUTRAL"),
original_confidence=trade_result.get("confidence", 50),
original_reasoning=trade_result.get("reasoning", []),
outcome=pnl,
outcome_type=outcome_type,
was_decision_correct=was_correct,
what_went_right=what_went_right,
what_went_wrong=what_went_wrong,
lessons_learned=lessons_learned,
future_recommendation=future_recommendation,
similar_situations_to_watch=similar_situations
)
def _analyze_success(self, trade_result: dict) -> List[str]:
"""Analysiert was bei einem erfolgreichen Trade richtig lief."""
points = []
pnl = trade_result.get("pnl", 0)
if pnl > 0.03: # > 3%
points.append(f"Ausgezeichnete Performance: +{pnl:.1%}")
# Check ob Entry gut war
max_profit = trade_result.get("max_profit", pnl)
max_drawdown = trade_result.get("max_drawdown", 0)
if max_profit > pnl * 1.5:
points.append("Gutes Timing: Trade war zeitweise noch profitabler")
if max_drawdown < abs(pnl) * 0.5:
points.append("Geringer Drawdown während Trade")
# Check ob Confidence gerechtfertigt war
confidence = trade_result.get("confidence", 50)
if confidence > 70 and pnl > 0.02:
points.append(f"Hohe Confidence ({confidence}%) war gerechtfertigt")
# Check Risk/Reward
if trade_result.get("risk_reward_actual", 1) > 2:
points.append("Gutes Risk/Reward umgesetzt")
return points
def _analyze_failure(self, trade_result: dict) -> List[str]:
"""Analysiert was bei einem fehlgeschlagenen Trade falsch lief."""
points = []
pnl = trade_result.get("pnl", 0)
# Check ob Stop-Loss eingehalten wurde
if trade_result.get("stop_loss_hit", False):
points.append("Stop-Loss wurde eingehalten (Disziplin)")
else:
points.append("Stop-Loss nicht eingehalten oder zu eng gesetzt")
# Check ob Confidence gerechtfertigt war
confidence = trade_result.get("confidence", 50)
if confidence > 70 and pnl < -0.02:
points.append(f"Zu hohe Confidence ({confidence}%) für diesen Trade")
# Check Drawdown
max_drawdown = trade_result.get("max_drawdown", abs(pnl))
if max_drawdown > abs(pnl) * 2:
points.append(f"Großer Drawdown ({max_drawdown:.1%}) vor Verlust")
# Check Duration
duration = trade_result.get("duration", 0)
if duration > 480: # > 8 Stunden
points.append("Trade zu lange gehalten")
return points
def _extract_positive_lessons(self, trade_result: dict) -> List[str]:
"""Extrahiert positive Lessons Learned."""
lessons = []
# Extrahiere aus Reasoning was funktioniert hat
reasoning = trade_result.get("reasoning", [])
for reason in reasoning:
if "RSI" in reason and trade_result.get("pnl", 0) > 0:
lessons.append(f"RSI-basierte Signale funktionieren in diesem Setup")
if "Mean-Reversion" in reason and trade_result.get("pnl", 0) > 0:
lessons.append("Mean-Reversion Ansatz war erfolgreich")
if "Trend" in reason and trade_result.get("pnl", 0) > 0:
lessons.append("Trend-Following Ansatz war erfolgreich")
# Füge allgemeine Lessons hinzu
if trade_result.get("pnl", 0) > 0.03:
lessons.append("Bei hoher Conviction größere Positionen möglich")
return lessons
def _extract_negative_lessons(self, trade_result: dict) -> List[str]:
"""Extrahiert negative Lessons Learned."""
lessons = []
# Counter-Trend Warnung
reasoning = trade_result.get("reasoning", [])
for reason in reasoning:
if "Counter-Trend" in reason and trade_result.get("pnl", 0) < 0:
lessons.append("Counter-Trend Trades in diesem Setup vermeiden")
# Confidence-Adjustierung
confidence = trade_result.get("confidence", 50)
if confidence > 70 and trade_result.get("pnl", 0) < -0.02:
lessons.append(f"Confidence bei ähnlichen Setups auf < {confidence}% begrenzen")
# Stop-Loss Lesson
if trade_result.get("max_drawdown", 0) > 0.05:
lessons.append("Stop-Loss früher setzen oder enger gestalten")
return lessons
def _generate_recommendation(
self,
trade_result: dict,
was_correct: bool,
lessons: List[str]
) -> str:
"""Generiert Empfehlung für zukünftige Trades."""
if was_correct:
base = "Ähnliche Setups weiter handeln. "
if trade_result.get("pnl", 0) > 0.03:
base += "Bei hoher Conviction Positionsgröße erhöhen. "
else:
base = "Vorsicht bei ähnlichen Setups. "
if trade_result.get("confidence", 50) > 70:
base += "Confidence-Schwelle für diese Art von Trades senken. "
if lessons:
base += f"Wichtig: {lessons[0]}"
return base
def _find_similar_situations(
self,
trade_result: dict,
market_context: Optional[dict]
) -> List[str]:
"""Findet ähnliche Situationen im Memory."""
if not market_context:
return []
# Baue Query für Similarity Search
situation_parts = [
f"EURUSD {trade_result.get('entry', 'N/A')}",
f"Action: {trade_result.get('action', 'N/A')}",
]
if "hurst_regime" in market_context:
situation_parts.append(f"Regime: {market_context['hurst_regime']}")
if "rsi" in market_context:
situation_parts.append(f"RSI: {market_context['rsi']}")
situation_query = ", ".join(situation_parts)
# Suche ähnliche Situationen
similar = self.memory.get_similar_setups(situation_query, n=3)
if similar.get("historical_win_rate", 0) > 0:
return [
f"Historische Win-Rate bei ähnlichen Setups: {similar['historical_win_rate']:.0%}",
f"Durchschnittliche Rendite: {similar.get('historical_avg_return', 0):.1%}",
similar.get("recommendation_text", "")
]
return []
def get_aggregate_insights(self, last_n_trades: int = 20) -> dict:
"""
Gibt aggregierte Insights aus letzten Trades.
Parameters
----------
last_n_trades : int, default 20
Anzahl der Trades für Analyse
Returns
-------
dict
Aggregierte Insights
"""
if len(self.memory.memories) == 0:
return {"message": "Keine Trades im Memory"}
# Hole letzte N Trades
recent_trades = self.memory.memories[-last_n_trades:]
# Berechne Statistiken
outcomes = [t.get("outcome", 0) for t in recent_trades]
win_rate = sum(1 for o in outcomes if o > 0) / len(outcomes)
avg_return = sum(outcomes) / len(outcomes)
# Finde häufigste Reasoning-Patterns in Winners vs Losers
winner_reasons = []
loser_reasons = []
for trade in recent_trades:
outcome = trade.get("outcome", 0)
reflection = trade.get("reflection", "")
if outcome > 0:
winner_reasons.append(reflection)
else:
loser_reasons.append(reflection)
return {
"total_trades": len(recent_trades),
"win_rate": win_rate,
"avg_return": avg_return,
"total_pnl": sum(outcomes),
"best_trade": max(outcomes),
"worst_trade": min(outcomes),
"n_winner_reasons": len(winner_reasons),
"n_loser_reasons": len(loser_reasons)
}
# Test-Funktion für lokale Validierung
if __name__ == "__main__":
print("=== EURUSD Reflection System Test ===\n")
# Erstelle Reflection System
reflection = EURUSDReflectionSystem(memory_file="git_ignore_folder/test_reflection_memory.json")
# Test 1: Reflektiere erfolgreichen Trade
print("=== Test 1: Erfolgreicher Trade ===")
winning_trade = {
"action": "LONG",
"confidence": 75,
"reasoning": ["RSI < 30 in Mean-Reversion Regime", "EZB hawkish"],
"entry": 1.0850,
"exit": 1.0890,
"pnl": 0.037, # +3.7%
"max_profit": 0.045,
"max_drawdown": 0.008,
"duration": 180 # 3 Stunden
}
ref_win = reflection.reflect_trade(winning_trade)
print(f"Trade ID: {ref_win.trade_id}")
print(f"Outcome: {ref_win.outcome:.1%} ({ref_win.outcome_type})")
print(f"Was Decision Correct: {'Ja ✓' if ref_win.was_decision_correct else 'Nein'}")
print(f"What Went Right:")
for point in ref_win.what_went_right[:3]:
print(f"{point}")
print(f"Lessons Learned:")
for lesson in ref_win.lessons_learned[:2]:
print(f"{lesson}")
print(f"Recommendation: {ref_win.future_recommendation[:80]}...")
# Test 2: Reflektiere verlorenen Trade
print("\n=== Test 2: Verlorener Trade ===")
losing_trade = {
"action": "SHORT",
"confidence": 80,
"reasoning": ["DXY breakout", "US NFP beat"],
"entry": 1.0880,
"exit": 1.0850,
"pnl": -0.028, # -2.8%
"max_profit": 0.005,
"max_drawdown": 0.045,
"duration": 420, # 7 Stunden
"stop_loss_hit": True
}
ref_loss = reflection.reflect_trade(losing_trade)
print(f"Trade ID: {ref_loss.trade_id}")
print(f"Outcome: {ref_loss.outcome:.1%} ({ref_loss.outcome_type})")
print(f"Was Decision Correct: {'Ja' if ref_loss.was_decision_correct else 'Nein ✗'}")
print(f"What Went Wrong:")
for point in ref_loss.what_went_wrong[:3]:
print(f"{point}")
print(f"Lessons Learned:")
for lesson in ref_loss.lessons_learned[:2]:
print(f"{lesson}")
# Test 3: Speichere im Memory
print("\n=== Test 3: Memory Update ===")
reflection.memory.add_trade(
situation="EURUSD 1.0850, RSI=28, Mean-Reversion, EZB hawkish",
decision={"action": "LONG", "confidence": 75},
outcome=0.037,
reflection=str(ref_win)
)
reflection.memory.add_trade(
situation="EURUSD 1.0880, DXY breakout, US NFP beat",
decision={"action": "SHORT", "confidence": 80},
outcome=-0.028,
reflection=str(ref_loss)
)
print(f"Trades im Memory: {len(reflection.memory.memories)}")
# Test 4: Aggregierte Insights
print("\n=== Test 4: Aggregierte Insights ===")
insights = reflection.get_aggregate_insights()
print(f"Anzahl Trades: {insights.get('total_trades', 0)}")
print(f"Win-Rate: {insights.get('win_rate', 0):.1%}")
print(f"Durchschnittliche Rendite: {insights.get('avg_return', 0):.2%}")
print(f"Gesamt-PnL: {insights.get('total_pnl', 0):.1%}")
# Cleanup
import os
if os.path.exists("git_ignore_folder/test_reflection_memory.json"):
os.remove("git_ignore_folder/test_reflection_memory.json")
print("\n✅ EURUSD Reflection System Implementierung ist funktionsfähig!")