English
preview
MQL5 und Datenverarbeitungspakete integrieren (Teil 7): Entwicklung von Multi-Agenten-Umgebungen für die symbolübergreifende Zusammenarbeit

MQL5 und Datenverarbeitungspakete integrieren (Teil 7): Entwicklung von Multi-Agenten-Umgebungen für die symbolübergreifende Zusammenarbeit

MetaTrader 5Beispiele |
16 1
Hlomohang John Borotho
Hlomohang John Borotho

Inhaltsverzeichnis:

  1. Einführung
  2. Überblick und Verständnis des Systems
  3. Die ersten Schritte
  4. Alles zusammen auf MQL5
  5. Live-Demo
  6. Schlussfolgerung


Einführung

In Teil 6, „Zusammenführung von Markt-Feedback und Modellanpassung“, haben wir uns darauf konzentriert, den Kreislauf zwischen Marktverhalten und Entscheidungslogik zu schließen. Anstatt uns auf statische Signale zu verlassen, haben wir Mechanismen eingeführt, die es dem Handelssystem ermöglichen, seine eigene Leistung zu beobachten, auf sich ändernde Marktbedingungen zu reagieren und seine internen Parameter entsprechend anzupassen. Dazu gehörte die Nutzung von Echtzeit-Feedback wie Handelsergebnissen, Volatilitätsveränderungen und strukturellen Marktveränderungen, um die Interpretation und Ausführung von Signalen innerhalb der MQL5–Python-Hybridarchitektur kontinuierlich zu verfeinern.

In diesem Teil erweitern wir diese Integration, um Multi-Agenten-Umgebungen zu entwickeln, die eine symbolübergreifende Zusammenarbeit ermöglichen. Das Ziel besteht darin, ein Framework zu entwickeln, in dem unabhängige Agenten verschiedene Märkte oder Symbole analysieren, Erkenntnisse austauschen und gemeinsam auf koordinierte Weise Handelsentscheidungen beeinflussen. Dieser Ansatz zielt darauf ab, die symbolübergreifenden Zusammenhänge oder Interdependenzen zwischen Symbolen (wie Währungskorrelationen oder der Risikostimmung) zu nutzen, um die Signalqualität zu verbessern, Fehlsignale zu reduzieren und ein robusteres Handelssystem zu schaffen, das sich an den breiteren Marktkontext anpasst und nicht nur an isolierte Kursbewegungen.


Überblick und Verständnis des Systems

Für den Aufbau von Multi-Agenten-Umgebungen, die eine symbolübergreifende Zusammenarbeit ermöglichen, verlagert sich das Kernparadigma von isolierten, symbolbezogenen Strategien hin zu einer Architektur vernetzter Intelligenz, in der Agenten als spezialisierte Knoten innerhalb eines kollektiven Entscheidungsgraphen agieren. Jeder Agent verkörpert Expertise in einem bestimmten Symbol oder Marktsegment – sei es EURUSD, Gold oder Indizes – und unterhält zugleich dynamische Kommunikationskanäle zu anderen Agenten. Diese Struktur ermöglicht es dem System, die Beziehungen zwischen den Märkten nicht als statische Korrelationen, sondern als dynamische, unmittelbar nutzbare Wege zu erfassen.

Die Funktionslogik der Umgebung basiert auf koordinierter Autonomie: Die Agenten verfügen über lokale Ausführungsbefugnisse, sind jedoch an eine globale Koordinierungsebene angebunden, die systemische Einschränkungen und Synergien verwaltet. Diese Ebene sorgt für die Einhaltung von Zielen auf Portfolioebene – wie beispielsweise das maximale korrelierte Engagement oder Volatilitätsziele über verschiedene Symbole hinweg –, indem sie die Handlungen einzelner Agenten durch gemeinsame Kontextpuffer, gezielte gezieltes Reward Shaping und einfache Konsensmechanismen steuert. Wenn beispielsweise mehrere Agenten widersprüchliche Signale erkennen (z. B. ein Agent, der bei GBP/USD auf steigende Kurse setzt, während ein anderer beim Dollar-Index auf fallende Kurse setzt), kann die Koordinationsschicht eine strukturierte Inferenzsitzung einleiten, bei der Evidenzhierarchien und historische Interaktionsmuster abgewogen werden, bevor eine Richtungstendenz festgelegt wird.



Die ersten Schritte

import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import json
import time
import schedule
from datetime import datetime, timedelta
from flask import Flask, jsonify, request
import threading
import warnings
warnings.filterwarnings('ignore')

account = '123456'
password = 'YourPass@MT5'
server = 'YourBrokersServer-Demo'

print("=" * 80)
print(" MULTI-AGENT TRADING SYSTEM - LIVE DEPLOYMENT")
print("=" * 80)

Zu Beginn richten wir die grundlegende Umgebung ein, die erforderlich ist, um Python mit MetaTrader 5 zu verbinden und Daten, Zeitabläufe sowie die externe Kommunikation zu verwalten. Wir importieren MetaTrader 5 für den Marktzugang, pandas und NumPy für die Datenverarbeitung sowie Flask, um Signale und den Systemstatus über eine schlanke API bereitzustellen. Zusätzliche Module übernehmen die Aufgaben der Zeitplanung, Thread-Verwaltung, Zeitstempelung und JSON-Serialisierung, sodass das Handelssystem kontinuierlich laufen und in Echtzeit sicher mit MQL5 interagieren kann. Schließlich legen die Variablen für Konto, Passwort und Server die Anmeldedaten fest, die zum Herstellen einer Live- oder Demo-Verbindung zu MetaTrader 5 erforderlich sind.

class LiveMultiAgentSystem:
    def __init__(self, account_number, password, server):
        self.account_number = account_number
        self.password = password
        self.server = server
        self.symbols = ["XAUUSD", "EURUSD", "GBPUSD", "USDJPY"]
        self.agents = {}
        self.positions = {}
        self.decision_log = []
        
        # Initialize MT5
        self.init_mt5()
        
        # Initialize agents
        self.init_agents()
        
        print(":/ Live Multi-Agent System Initialized")
    
    def init_mt5(self):
        """Initialize connection to MT5"""
        if not mt5.initialize():
            print("X MT5 initialization failed")
            print(f"   Error: {mt5.last_error()}")
            return False
        
        # Login to account
        authorized = mt5.login(
            login=self.account_number,
            password=self.password,
            server=self.server
        )
        
        if authorized:
            print(f":/ Connected to MT5 Account: {self.account_number}")
            account_info = mt5.account_info()
            print(f"   Balance: ${account_info.balance:.2f}")
            print(f"   Equity: ${account_info.equity:.2f}")
            return True
        else:
            print(f"X Login failed: {mt5.last_error()}")
            return False

In dieser Klasse definieren wir die Kernstruktur, die für die Verwaltung einer Live-Handelsumgebung mit mehreren Agenten zuständig ist. Der Konstruktor richtet die Anmeldedaten für das Konto ein, weist eine vordefinierte Liste von Symbolen zu und bereitet Container für Agenten, offene Positionen und den Entscheidungsverlauf vor. Anschließend wird eine Verbindung zu MetaTrader 5 hergestellt, indem das Terminal initialisiert, die Anmeldung beim angegebenen Handelskonto durchgeführt, die Verbindung überprüft und grundlegende Kontoinformationen abgerufen werden. Diese Konfiguration stellt sicher, dass alle Agenten innerhalb einer gemeinsamen, authentifizierten MetaTrader 5-Sitzung arbeiten, und bildet damit die Grundlage für eine koordinierte, in Echtzeit erfolgende und symbolübergreifende Entscheidungsfindung.

    def init_agents(self):
        """Initialize trading agents"""
        print("\n Initializing Live Agents...")
             
        from collections import defaultdict
        
        self.agents = {
            "XAUUSD": {
                "name": "Gold Agent",
                "weights": {
                    "trend": 1.5,
                    "momentum": 1.2,
                    "volatility": 1.0
                },
                "params": {
                    "ema_period": 20,
                    "rsi_period": 14,
                    "atr_period": 14
                }
            },
            "CONTEXT": {
                "name": "Context Agent",
                "weights": {
                    "usd_strength": 1.3,
                    "risk_sentiment": 1.1
                }
            },
            "LIQUIDITY": {
                "name": "Liquidity Agent",
                "weights": {
                    "volatility": 1.2,
                    "volume": 1.0
                }
            }
        }
        
        print(f":/ Created {len(self.agents)} agents")
    
    def get_live_data(self, symbol, timeframe=mt5.TIMEFRAME_M5, bars=100):
        """Get live data from MT5"""
        try:
            rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, bars)
            if rates is None or len(rates) == 0:
                print(f"❌ No data for {symbol}")
                return None
            
            df = pd.DataFrame(rates)
            df['time'] = pd.to_datetime(df['time'], unit='s')
            df.set_index('time', inplace=True)
            
            # Calculate features
            df['returns'] = df['close'].pct_change()
            df['ema_20'] = df['close'].ewm(span=20).mean()
            df['ema_50'] = df['close'].ewm(span=50).mean()
            df['rsi'] = self.calculate_rsi(df['close'])
            df['atr'] = self.calculate_atr(df)
            
            return df
        except Exception as e:
            print(f"X Error getting data for {symbol}: {e}")
            return None
    
    def calculate_rsi(self, prices, period=14):
        """Calculate RSI"""
        delta = prices.diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
        rs = gain / loss
        rsi = 100 - (100 / (1 + rs))
        return rsi
    
    def calculate_atr(self, df, period=14):
        """Calculate ATR"""
        high = df['high']
        low = df['low']
        close = df['close']
        
        tr1 = high - low
        tr2 = abs(high - close.shift())
        tr3 = abs(low - close.shift())
        
        tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
        atr = tr.rolling(period).mean()
        return atr
    
    def analyze_symbol(self, symbol):
        """Agent analysis for a symbol"""
        data = self.get_live_data(symbol)
        if data is None or len(data) < 50:
            return {"action": 0, "confidence": 0.0, "reason": "Insufficient data"}
        
        current_price = data['close'].iloc[-1]
        ema_20 = data['ema_20'].iloc[-1]
        ema_50 = data['ema_50'].iloc[-1]
        rsi = data['rsi'].iloc[-1]
        atr = data['atr'].iloc[-1]
        
        # Decision logic
        bullish = 0
        bearish = 0
        
        # Trend
        if current_price > ema_20 > ema_50:
            bullish += 2
        elif current_price < ema_20 < ema_50:
            bearish += 2
        
        # Momentum
        if 40 < rsi < 70:
            bullish += 1
        elif 30 < rsi < 60:
            bearish += 1
        
        # Volatility (using ATR)
        if atr / current_price < 0.002:  # Low volatility
            bullish += 0.5
            bearish += 0.5
        
        # Make decision
        if bullish > bearish and bullish >= 2:
            action = 1
            confidence = min(bullish / 4, 0.8)
            reason = f"Bullish: trend={bullish}, RSI={rsi:.1f}"
        elif bearish > bullish and bearish >= 2:
            action = -1
            confidence = min(bearish / 4, 0.8)
            reason = f"Bearish: trend={bearish}, RSI={rsi:.1f}"
        else:
            action = 0
            confidence = 0.1
            reason = f"Neutral: Bull={bullish}, Bear={bearish}"
        
        return {
            "symbol": symbol,
            "action": action,
            "confidence": confidence,
            "reason": reason,
            "price": current_price,
            "timestamp": datetime.now().isoformat()
        }

In diesem Teil initialisieren wir die Live-Handelsagenten, aus denen das Multi-Agenten-System besteht. Jeder Agent ist mit einer bestimmten Rolle und Zuständigkeit definiert, beispielsweise der „Gold-Agent“ für die symbolspezifische Analyse, der „Context-Agent“ für die allgemeinen Marktbedingungen und der „Liquidity-Agent“ für die Erfassung von Volatilität und Handelsvolumen. Diese Agenten sind mit gewichteten Entscheidungsfaktoren und Indikatorparametern konfiguriert, sodass jeder einzelne spezifische Informationen zum Gesamtsystem beitragen kann, anstatt sich auf eine einzige, monolithische Strategie zu verlassen.

Die Methoden zur Datenverarbeitung richten dann eine Echtzeit-Pipeline für Marktdaten aus MetaTrader 5 ein. Die Kursdaten werden direkt aus MetaTrader 5 abgerufen, in einen strukturierten pandas-DataFrame konvertiert und um technische Kennzahlen wie Renditen, exponentielle gleitende Durchschnitte, RSI und ATR ergänzt. Spezielle Hilfsfunktionen berechnen RSI und ATR manuell und gewährleisten so vollständige Transparenz und Flexibilität hinsichtlich des Verhaltens der Indikatoren, während die gesamte Vorverarbeitungslogik zentralisiert und agentenübergreifend wiederverwendbar bleibt.

Die Methode „analyze_symbol“ stellt die zentrale Entscheidungskomponente für jeden symbolspezifischen Agenten dar. Das System wertet Trendstruktur, Dynamik und Volatilität aus, um bullische und bärische Marktbedingungen unabhängig voneinander zu bewerten, und wandelt so Rohmarktdaten in umsetzbare Signale um. Auf der Grundlage dieser Bewertungen gibt der Agent eine Richtungsentscheidung, einen Konfidenzwert und eine Begründung aus, die später an andere Agenten weitergegeben oder an die Ausführungsebene übermittelt werden können, um koordinierte, symbolübergreifende Handelsentscheidungen zu treffen.

    def analyze_context(self):
        """Context agent analysis"""
        # Get USD strength from major pairs
        eur_data = self.get_live_data("EURUSD", bars=50)
        gbp_data = self.get_live_data("GBPUSD", bars=50)
        jpy_data = self.get_live_data("USDJPY", bars=50)
        
        if not all([eur_data is not None, gbp_data is not None, jpy_data is not None]):
            return {"action": 0, "confidence": 0.0, "reason": "Missing data"}
        
        # Calculate USD strength
        eur_change = (eur_data['close'].iloc[-1] / eur_data['close'].iloc[-20] - 1)
        gbp_change = (gbp_data['close'].iloc[-1] / gbp_data['close'].iloc[-20] - 1)
        jpy_change = (jpy_data['close'].iloc[-1] / jpy_data['close'].iloc[-20] - 1)
        
        # EURUSD and GBPUSD down = USD strong, USDJPY up = USD strong
        usd_strength = (-eur_change - gbp_change + jpy_change) / 3
        
        if usd_strength > 0.01:
            action = -1  # USD strong → bearish for gold
            confidence = min(abs(usd_strength) * 10, 0.7)
            reason = f"USD Strong: {usd_strength:.2%}"
        elif usd_strength < -0.01:
            action = 1  # USD weak → bullish for gold
            confidence = min(abs(usd_strength) * 10, 0.7)
            reason = f"USD Weak: {usd_strength:.2%}"
        else:
            action = 0
            confidence = 0.1
            reason = "USD Neutral"
        
        return {
            "agent": "CONTEXT",
            "action": action,
            "confidence": confidence,
            "reason": reason,
            "usd_strength": usd_strength
        }
    
    def run_decision_pipeline(self, target_symbol="XAUUSD"):
        """Run complete decision pipeline"""
        print(f"\nO- {datetime.now().strftime('%H:%M:%S')} - Analyzing market...")
        
        # Collect agent decisions
        decisions = []
        
        # Symbol agents
        for symbol in self.symbols:
            if symbol == target_symbol:
                decision = self.analyze_symbol(symbol)
                decisions.append(decision)
                print(f"   {symbol}: {decision['action']} ({decision['confidence']:.1%}) - {decision['reason']}")
        
        # Context agent
        context_decision = self.analyze_context()
        decisions.append(context_decision)
        print(f"   CONTEXT: {context_decision['action']} ({context_decision['confidence']:.1%}) - {context_decision['reason']}")
        
        # Calculate consensus
        weighted_sum = 0
        total_weight = 0
        
        weights = {
            "XAUUSD": 1.5,
            "EURUSD": 1.0,
            "GBPUSD": 1.0,
            "USDJPY": 1.0,
            "CONTEXT": 1.3
        }
        
        for decision in decisions:
            symbol = decision.get('symbol', decision.get('agent', 'UNKNOWN'))
            weight = weights.get(symbol, 1.0)
            weighted_sum += decision['action'] * decision['confidence'] * weight
            total_weight += weight * decision['confidence']
        
        # Make final decision
        if total_weight == 0:
            final_action = 0
            confidence = 0.0
            reason = "No consensus"
        else:
            consensus = weighted_sum / total_weight
            
            if consensus > 0.3:
                final_action = 1
                confidence = min(abs(consensus), 0.9)
                reason = f"Bullish consensus: {consensus:.2f}"
            elif consensus < -0.3:
                final_action = -1
                confidence = min(abs(consensus), 0.9)
                reason = f"Bearish consensus: {consensus:.2f}"
            else:
                final_action = 0
                confidence = 0.2
                reason = f"Neutral: {consensus:.2f}"
        
        final_decision = {
            "timestamp": datetime.now().isoformat(),
            "symbol": target_symbol,
            "action": final_action,
            "confidence": confidence,
            "reason": reason,
            "consensus": consensus if total_weight > 0 else 0,
            "agent_decisions": decisions
        }
        
        self.decision_log.append(final_decision)
        
        # Save decision to file for MQL5 to read
        self.save_decision(final_decision)
        
        # Execute trade if confidence is high enough
        if confidence > 0.5:
            self.execute_trade(final_decision)
        
        return final_decision
        
    def write_signal(signal):
        with open("multi_agent_signal.json", "w") as f:
            json.dump(signal, f, indent=2)
    
    def save_decision(self, decision):
        """Save decision to JSON file for MQL5"""
        try:
            with open('multi_agent_signal.json', 'w') as f:
                json.dump(decision, f, indent=2)
            print(f"💾 Signal saved to file")
        except Exception as e:
            print(f"X Error saving signal: {e}")
    
    def execute_trade(self, decision):
        """Execute trade via MT5"""
        symbol = decision['symbol']
        action = decision['action']
        confidence = decision['confidence']
        
        # Check existing positions
        positions = mt5.positions_get(symbol=symbol)
        if positions:
            print(f"!! Existing position found for {symbol}")
            # Check if we should close it
            current_position = positions[0]
            if (action == 1 and current_position.type == 1) or (action == -1 and current_position.type == 0):
                print(f"   Same direction, considering adding to position")
                return
            else:
                print(f"   Opposite direction, closing position first")
                self.close_position(symbol)
        
        # Prepare trade request
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is None:
            print(f"X Symbol {symbol} not found")
            return
        
        point = symbol_info.point
        price = mt5.symbol_info_tick(symbol).ask if action == 1 else mt5.symbol_info_tick(symbol).bid
        
        # Calculate position size based on risk
        account_info = mt5.account_info()
        balance = account_info.balance
        risk_amount = balance * 0.01 * confidence  # 1% risk adjusted by confidence
        
        # Calculate stop loss based on ATR
        data = self.get_live_data(symbol, bars=50)
        if data is not None and 'atr' in data.columns:
            atr = data['atr'].iloc[-1]
            stop_distance = atr * 1.5
        else:
            stop_distance = price * 0.01  # 1% stop
        
        # Calculate volume
        volume = risk_amount / stop_distance
        volume = round(volume, 2)  # Round to 2 decimal places
        
        # Validate volume
        min_volume = symbol_info.volume_min
        max_volume = symbol_info.volume_max
        volume = max(min_volume, min(volume, max_volume))
        
        # Prepare order
        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": volume,
            "type": mt5.ORDER_TYPE_BUY if action == 1 else mt5.ORDER_TYPE_SELL,
            "price": price,
            "sl": price - stop_distance if action == 1 else price + stop_distance,
            "tp": price + stop_distance * 2 if action == 1 else price - stop_distance * 2,
            "deviation": 10,
            "magic": 234000,
            "comment": f"Multi-Agent: {decision['reason'][:30]}",
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        
        # Send order
        result = mt5.order_send(request)
        
        if result.retcode == mt5.TRADE_RETCODE_DONE:
            print(f":/ Trade executed: {'BUY' if action == 1 else 'SELL'} {volume} {symbol} at {price}")
            print(f"   SL: {result.request.sl:.5f}, TP: {result.request.tp:.5f}")
            print(f"   Order ID: {result.order}")
        else:
            print(f"X Trade failed: {result.comment}")
    
    def close_position(self, symbol):
        """Close all positions for a symbol"""
        positions = mt5.positions_get(symbol=symbol)
        if not positions:
            return
        
        for position in positions:
            tick = mt5.symbol_info_tick(symbol)
            
            request = {
                "action": mt5.TRADE_ACTION_DEAL,
                "symbol": symbol,
                "volume": position.volume,
                "type": mt5.ORDER_TYPE_BUY if position.type == 1 else mt5.ORDER_TYPE_SELL,
                "position": position.ticket,
                "price": tick.ask if position.type == 1 else tick.bid,
                "deviation": 10,
                "magic": 234000,
                "comment": "Close by Multi-Agent",
                "type_time": mt5.ORDER_TIME_GTC,
                "type_filling": mt5.ORDER_FILLING_IOC,
            }
            
            result = mt5.order_send(request)
            if result.retcode == mt5.TRADE_RETCODE_DONE:
                print(f":/ Position {position.ticket} closed")
            else:
                print(f"X Failed to close position {position.ticket}: {result.comment}")
    
    def monitor_positions(self):
        """Monitor and manage open positions"""
        positions = mt5.positions_get()
        
        for position in positions:
            symbol = position.symbol
            current_price = mt5.symbol_info_tick(symbol).bid
            
            # Check stop loss and take profit
            # These are managed by MT5 automatically, but we can log them
            unrealized_pnl = position.profit
            
            print(f" {symbol}: {position.type} {position.volume} | P&L: ${unrealized_pnl:.2f}")
    
    def run_continuously(self, interval_minutes=5):
        """Run the system continuously"""
        print(f"\n<=> Starting continuous monitoring every {interval_minutes} minutes...")
        
        def job():
            try:
                # Run analysis
                decision = self.run_decision_pipeline("XAUUSD")
                
                # Monitor positions
                self.monitor_positions()
                
                # Log status
                print(f" Decision: {decision['action']} ({decision['confidence']:.1%}) - {decision['reason']}")
                
            except Exception as e:
                print(f"X Error in scheduled job: {e}")
        
        # Schedule the job
        schedule.every(interval_minutes).minutes.do(job)
        
        # Run immediately first time
        job()
        
        # Keep running
        try:
            while True:
                schedule.run_pending()
                time.sleep(1)
        except KeyboardInterrupt:
            print("\n!!! Stopping system...")
            mt5.shutdown()

In diesem Teil des Codes wird die Kontextanalyse-Ebene vorgestellt, die eher als übergeordneter Intelligenzagent denn als symbolspezifischer Händler fungiert. Die Methode „analyze_context“ bewertet die allgemeine Stärke des US-Dollars anhand der Beobachtung korrelierter Hauptwährungspaare wie EURUSD, GBPUSD und USDJPY. Durch die Messung der jüngsten prozentualen Veränderungen in diesen Märkten und deren Zusammenfassung zu einem einzigen Indikator für die Stärke des US-Dollars leitet das System eine Tendenz auf Makroebene ab, die Entscheidungen in Bezug auf Gold (XAUUSD) beeinflusst. Dadurch kann die Strategie marktübergreifende Zusammenhänge berücksichtigen, anstatt sich ausschließlich auf isolierte Kursbewegungen zu stützen.

Die Methode „run_decision_pipeline“ koordiniert anschließend den gesamten Multi-Agenten-Workflow. Sie sammelt Entscheidungen des symbolspezifischen Agenten (XAUUSD) und des Kontextagenten, protokolliert deren Ausgaben und aggregiert diese mithilfe eines gewichteten Konsensmodells. Jeder Agent trägt auf der Grundlage von Konfidenzwerten und vordefinierten Wichtigkeitsgewichten zur endgültigen Entscheidung bei, wodurch sichergestellt wird, dass stärkere oder zuverlässigere Signale einen größeren Einfluss haben. Dieser Konsensmechanismus wandelt mehrere unabhängige Meinungen in eine einzige, schlüssige Handelsentscheidung mit einem zugehörigen Konfidenzwert um.

Sobald eine endgültige Entscheidung getroffen wurde, wird diese vom System im Sinne der Transparenz und Nachvollziehbarkeit gespeichert. Die Entscheidung wird einem internen Protokoll hinzugefügt und in eine JSON-Datei geschrieben, die extern von einem MQL5-Expert Advisor genutzt werden kann. Überschreitet die Konfidenz einen vordefinierten Schwellenwert, leitet das System die Handelsausführung ein und verbindet so analytische Erkenntnisse mit dem tatsächlichen Marktgeschehen. Dieses Design trennt die Erzeugung, Speicherung und Ausführung von Entscheidungen klar voneinander, sorgt dabei aber für eine enge Synchronisation zwischen diesen Prozessen.

Die übrigen Methoden dienen der direkten Abwicklung von Live-Handelsgeschäften und der Positionsverwaltung über MetaTrader 5. Die Handelsgrößen werden dynamisch auf der Grundlage des Kontostands, des konfidenzadjustierten Risikos und der auf der ATR basierenden Stop-Abstände festgelegt, wodurch eine konsistente Risikokontrolle gewährleistet wird. Das System unterstützt zudem das Schließen gegenläufiger Positionen, die Überwachung offener Trades und den kontinuierlichen Betrieb in festgelegten Intervallen. Zusammen bilden diese Komponenten einen vollständigen adaptiven Handelszyklus, der den Marktkontext analysiert, einen Konsens zwischen mehreren Agenten herstellt, disziplinierte Handelsgeschäfte ausführt und die Systemleistung kontinuierlich in Echtzeit überwacht.

# ================================================
# FLASK API FOR EXTERNAL CONTROL 
# ================================================

from flask import Flask, request, jsonify
import threading
import time
import json
import MetaTrader5 as mt5

app = Flask(__name__)

trading_system = None
system_thread = None
system_running = False
system_lock = threading.Lock()

@app.route('/')
def home():
    return jsonify({
        "status": "Multi-Agent Trading System API",
        "version": "1.1",
        "running": system_running
    })

@app.route('/start', methods=['POST'])
def start_system():
    global trading_system, system_thread, system_running
    global account, password, serve
    
    with system_lock:
        if system_running:
            return jsonify({"error": "System already running"}), 400

        data = request.json or {} 
        account = data.get('account') 
        password = data.get('password')
        server = data.get('server', 'SpaceMarkets-Live')

        if not all([account, password]):
            return jsonify({"error": "Missing account or password"}), 400

        # Create system
        trading_system = LiveMultiAgentSystem(account, password, server)
        system_running = True

        # Background execution loop
        def runner():
            while system_running:
                try:
                    trading_system.run_once()
                    time.sleep(5)
                except Exception as e:
                    print("X System error:", e)
                    time.sleep(5)

        system_thread = threading.Thread(target=runner, daemon=True)
        system_thread.start()

        return jsonify({
            "status": "System started",
            "account": account,
            "server": server
        })

@app.route('/stop', methods=['POST'])
def stop_system():
    global system_running

    with system_lock:
        if not system_running:
            return jsonify({"error": "System not running"}), 400

        system_running = False

    return jsonify({"status": "System stopping"})

@app.route('/status', methods=['GET'])
def get_status():
    if not system_running or trading_system is None:
        return jsonify({"status": "stopped"})

    last_decision = (
        trading_system.decision_log[-1]
        if trading_system.decision_log
        else None
    )

    return jsonify({
        "status": "running",
        "last_decision": last_decision,
        "total_decisions": len(trading_system.decision_log)
    })

Dieser Teil des Codes richtet eine sichere und kontrollierte Ausführungsumgebung für das Handelssystem ein, indem die Flask-Anwendung, gemeinsam genutzte Zustandsvariablen und Synchronisationsmechanismen initialisiert werden. Es werden globale Flags und Sperren eingeführt, um zu verfolgen, ob das System läuft, und um Race-Conditions beim Starten oder Beenden der Handels-Engine zu verhindern. Der Root-Endpunkt (/) dient als einfacher Status-/Health-Check, der die aktuelle API-Version zurückgibt und angibt, ob das Multi-Agenten-System aktiv läuft. Dies ist sowohl für die Fehlersuche als auch für die externe Überwachung nützlich.

Die übrigen Flask-Routen ermöglichen eine externe Steuerung des Lebenszyklus des Handelssystems. Der Endpunkt /start initialisiert die Multi-Agent-Engine sicher anhand der in der Anfrage angegebenen Anmeldedaten und startet sie in einem Hintergrund-Thread für den Dauerbetrieb, während /stop die Ausführung ordnungsgemäß beendet, ohne die API selbst zu beenden. Der Endpunkt /status stellt den Systemstatus in Echtzeit bereit, einschließlich der zuletzt getroffenen Entscheidung und der Gesamtzahl der getroffenen Entscheidungen, sodass MQL5- oder andere Clients auf kontrollierte, nicht blockierende Weise Abfragen durchführen und sich mit der Python-basierten Multi-Agenten-Logik synchronisieren können.



Alles zusammen auf MQL5

//+------------------------------------------------------------------+
//|                                                 Multi-Agents.mq5 |
//|                        GIT under Copyright 2025, MetaQuotes Ltd. |
//|                     https://www.mql5.com/en/users/johnhlomohang/ |
//+------------------------------------------------------------------+
#property copyright "GIT under Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/johnhlomohang/"
#property version   "1.00"

#include <Trade/Trade.mqh>
#include "Json.mqh"  // Include our JSON parser

//--- Input parameters
input string   PythonServer = "http://127.0.0.1:5000";  // Python server address
input double   RiskPercent  = 1.0;                      // Risk percentage
input int      SignalCheckInterval = 30;                // Check signal every N seconds
input bool     EnableTrading = true;                    // Enable trading
input string   CommentText   = "Multi-Agent";           // Order comment

//--- Global variables
CTrade trade;
datetime lastSignalCheck = 0;
string currentSignal = "";
double lastSignalPrice = 0;
int magicNumber = 234000;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Set magic number for order identification
   trade.SetExpertMagicNumber(magicNumber);
   
   // Set asynchronous mode
   trade.SetAsyncMode(true);
   
   // Print initialization message
   Print("Multi-Agent EA Initialized - Simple JSON Version");
   Print("Python Server: ", PythonServer);
   Print("Risk: ", RiskPercent, "%");
   Print("Magic Number: ", magicNumber);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Print("Multi-Agent EA Deinitialized");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Check if it's time to check for new signals
   if(TimeCurrent() - lastSignalCheck >= SignalCheckInterval)
   {
      CheckSignal();
      lastSignalCheck = TimeCurrent();
   }
   
   // Manage existing positions
   ManagePositions();
}

//+------------------------------------------------------------------+
//| Check signal from Python server                                  |
//+------------------------------------------------------------------+
void CheckSignal()
{  
   string url = PythonServer + "/signal";
   
   string payload = "{}";  // empty body is fine
   char data[];
   StringToCharArray(payload, data);
   
   char result[];
   string headers = "Content-Type: application/json\r\n";
   string result_headers;
   
   int res = WebRequest(
      "POST",
      url,
      headers,
      5000,
      data,
      result,
      result_headers
   );
   
   if(res != 200)
   {
      Print("HTTP request failed: ", res);
      return;
   }
   Print("LastError=", GetLastError());
   
   if(res == 200) // HTTP OK
   {
      string jsonStr = CharArrayToString(result);
      Print("Received JSON: ", jsonStr);
      
      // Parse using our simple JSON parser
      string symbol = CJson::ParseString(jsonStr, "symbol", "");
      int action = CJson::ParseInteger(jsonStr, "action", 0);
      double confidence = CJson::ParseNumber(jsonStr, "confidence", 0);
      string reason = CJson::ParseString(jsonStr, "reason", "");
      double price = CJson::ParseNumber(jsonStr, "price", 0);
      
      Print("Parsed Signal: Symbol=", symbol, " Action=", action, 
            " Confidence=", confidence, " Reason=", reason);
      
      // Only trade if confidence is high enough
      if(confidence >= 0.5 && EnableTrading)
      {
         // Check if we should trade this symbol
         if(symbol == _Symbol || symbol == "")
         {
            ExecuteSignal(action, confidence, reason, price);
         }
      }
      
      // Update current signal display
      currentSignal = reason;
   }
   else if(res == -1)
   {
      Print("WebRequest failed. Error: ", GetLastError());
      Print("Make sure to add URL to allowed list: ", url);
      
      // To add URL to allowed list in MT5:
      // 1. Go to Tools -> Options -> Expert Advisors
      // 2. Click "Add" under "Allowed URLs"
      // 3. Add: http://localhost:5000
   }
   else
   {
      Print("HTTP request failed: ", res);
   }
}

Nun definieren wir in MQL5 einen MetaTrader 5-Expert Advisor, der als Brücke zwischen dem Handelsterminal und einem externen, auf Python basierenden Multi-Agenten-System fungiert. Wir initialisieren Handelsparameter wie Risiko, Signalabfragehäufigkeit und eine Magic Number zur Auftragsverfolgung und konfigurieren anschließend das CTrade-Objekt für die asynchrone Ausführung. Bei jedem Markt-Tick sendet der EA in regelmäßigen Abständen eine HTTP-Anfrage an den Python-Server, um ein Handelssignal abzurufen, wertet die zurückgegebene JSON-Nutzlast aus, um Felder wie Symbol, Aktion, Konfidenz und Kurs zu extrahieren, und wendet eine grundlegende Filterlogik an, um sicherzustellen, dass Trades nur dann berücksichtigt werden, wenn die Konfidenz ausreichend hoch ist und der Handel aktiviert ist.

Der verbleibende Teil der Logik konzentriert sich auf das Laufzeitverhalten und die Robustheit des Systems. Der EA verwaltet kontinuierlich bestehende Positionen, während er auf neue Signale wartet, protokolliert wichtige Ereignisse im Sinne der Transparenz und verfügt über Sicherheitsvorkehrungen für fehlgeschlagene Webanfragen oder falsch konfigurierte Berechtigungen. Indem die Signalerzeugung auf den Python-Server ausgelagert und die Ausführungslogik innerhalb von MetaTrader 5 schlank gehalten wird, trennt dieses Design die Entscheidungsfindung sauber von der Handelsausführung, sodass sich die Multi-Agenten-Intelligenz unabhängig vom Handelsterminal weiterentwickeln kann.

//+------------------------------------------------------------------+
//| Execute trading signal                                           |
//+------------------------------------------------------------------+
void ExecuteSignal(int action, double confidence, string reason, double signalPrice = 0)
{
   // Get current price
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double price = (action == 1) ? ask : bid;
   
   // Use signal price if provided and valid
   if(signalPrice > 0 && MathAbs(signalPrice - price) / price < 0.05) // Within 5%
   {
      price = signalPrice;
   }
   
   // Check if price has changed significantly
   if(MathAbs(price - lastSignalPrice) / price < 0.001) // Less than 0.1% change
   {
      Print("Price hasn't changed enough, skipping trade");
      return;
   }
   
   lastSignalPrice = price;
   
   // Close opposite positions first
   if(action == 1) // Buy signal
   {
      CloseSellPositions();
   }
   else if(action == -1) // Sell signal
   {
      CloseBuyPositions();
   }
   
   // Calculate position size
   double volume = CalculateVolume(confidence);
   
   if(volume <= 0)
   {
      Print("Volume too small, skipping trade");
      return;
   }
   
   // Calculate stop loss and take profit based on ATR
   double atr = CalculateATR(14);
   double stopLoss = 0;
   double takeProfit = 0;
   
   if(action == 1) // Buy
   {
      stopLoss = price - (atr * 1.5);
      takeProfit = price + (atr * 3.0);
   }
   else // Sell
   {
      stopLoss = price + (atr * 1.5);
      takeProfit = price - (atr * 3.0);
   }
   
   // Normalize SL/TP to tick size
   stopLoss = NormalizePrice(stopLoss);
   takeProfit = NormalizePrice(takeProfit);
   
   // Place order
   if(action == 1)
   {
      if(trade.Buy(volume, _Symbol, price, stopLoss, takeProfit, reason))
      {
         Print("BUY order placed: ", DoubleToString(volume, 2), " ", _Symbol, 
               " at ", DoubleToString(price, 5));
         Print("SL: ", DoubleToString(stopLoss, 5), 
               " TP: ", DoubleToString(takeProfit, 5));
      }
      else
      {
         Print("Failed to place BUY order: ", trade.ResultRetcodeDescription());
      }
   }
   else if(action == -1)
   {
      if(trade.Sell(volume, _Symbol, price, stopLoss, takeProfit, reason))
      {
         Print("SELL order placed: ", DoubleToString(volume, 2), " ", _Symbol, 
               " at ", DoubleToString(price, 5));
         Print("SL: ", DoubleToString(stopLoss, 5), 
               " TP: ", DoubleToString(takeProfit, 5));
      }
      else
      {
         Print("Failed to place SELL order: ", trade.ResultRetcodeDescription());
      }
   }
}

//+------------------------------------------------------------------+
//| Calculate ATR                                                    |
//+------------------------------------------------------------------+
double CalculateATR(int period)
{
   double atr = 0;
   
   // Try to get ATR from indicator
   int atrHandle = iATR(_Symbol, PERIOD_M5, period);
   if(atrHandle != INVALID_HANDLE)
   {
      double atrArray[];
      if(CopyBuffer(atrHandle, 0, 0, 1, atrArray) > 0)
      {
         atr = atrArray[0];
      }
      IndicatorRelease(atrHandle);
   }
   
   if(atr <= 0)
   {
      // Fallback: use percentage of price
      atr = SymbolInfoDouble(_Symbol, SYMBOL_BID) * 0.002; // 0.2%
   }
   
   return atr;
}

//+------------------------------------------------------------------+
//| Normalize price to tick size                                     |
//+------------------------------------------------------------------+
double NormalizePrice(double price)
{
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tickSize > 0)
   {
      price = MathRound(price / tickSize) * tickSize;
   }
   return NormalizeDouble(price, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
}

Hier implementieren wir eine vollständige Pipeline zur Handelsausführung, die ein Richtungssignal aufnimmt und es in eine kontrollierte, risikobewusste Marktorder umwandelt. Die Funktion „ExecuteSignal“ ermittelt zunächst den korrekten Ausführungspreis anhand des aktuellen Geld- oder Briefkurses, überschreibt diesen optional durch einen gültigen externen Signalkurs und filtert anschließend überflüssige Trades heraus, indem sie sicherstellt, dass sich der Kurs seit dem letzten Signal deutlich bewegt hat. Das System sorgt für eine konsequente Richtungsdisziplin, indem es zunächst alle gegensätzlichen Positionen schließt, die Positionsgröße dynamisch anhand der Signalkonfidenz berechnet und adaptive Stop-Loss- und Take-Profit-Niveaus unter Verwendung des ATR-Werts ableitet, um die aktuelle Marktvolatilität widerzuspiegeln.

Vor der Auftragserteilung werden alle Preiswerte auf die Tick-Größe und die Genauigkeit des Wertpapiers normiert, um die Einhaltung der Broker-Vorgaben sicherzustellen. Anschließend werden Kauf- oder Verkaufsaufträge übermittelt und zur Transparenz vollständig protokolliert. Die unterstützenden Funktionen übernehmen die Volatilitätsmessung mithilfe des ATR-Indikators mit einem sicheren Ausweichmechanismus sowie eine präzise Kursnormalisierung, wodurch die Ausführungslogik robust, anpassungsfähig und widerstandsfähig gegenüber häufigen Handels- und Brokerfehlern wird.

//+------------------------------------------------------------------+
//|                                                         Json.mqh |
//|                        GIT under Copyright 2025, MetaQuotes Ltd. |
//|                     https://www.mql5.com/en/users/johnhlomohang/ |
//+------------------------------------------------------------------+
#property copyright "GIT under Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/johnhlomohang/"

#ifndef JSON_MQH
#define JSON_MQH

class CJson
{
private:
   string m_json;
   
   string ExtractValue(string key)
   {
      int keyPos = StringFind(m_json, "\"" + key + "\"");
      if(keyPos == -1) return "";
      
      int colonPos = StringFind(m_json, ":", keyPos);
      if(colonPos == -1) return "";
      
      // Find the start of the value
      int valueStart = colonPos + 1;
      while(valueStart < StringLen(m_json) && 
            (m_json[valueStart] == ' ' || m_json[valueStart] == '\t' || 
             m_json[valueStart] == '\n' || m_json[valueStart] == '\r'))
      {
         valueStart++;
      }
      
      if(valueStart >= StringLen(m_json)) return "";
      
      char firstChar = m_json[valueStart];
      
      // String value
      if(firstChar == '\"')
      {
         int endQuote = StringFind(m_json, "\"", valueStart + 1);
         if(endQuote == -1) return "";
         return StringSubstr(m_json, valueStart + 1, endQuote - valueStart - 1);
      }
      
      // Number or boolean value
      int valueEnd = valueStart;
      while(valueEnd < StringLen(m_json) && 
            ((m_json[valueEnd] >= '0' && m_json[valueEnd] <= '9') || 
             m_json[valueEnd] == '-' || m_json[valueEnd] == '.' || 
             m_json[valueEnd] == 'e' || m_json[valueEnd] == 'E' ||
             m_json[valueEnd] == 't' || m_json[valueEnd] == 'r' ||
             m_json[valueEnd] == 'u' || m_json[valueEnd] == 'e' ||
             m_json[valueEnd] == 'f' || m_json[valueEnd] == 'a' ||
             m_json[valueEnd] == 'l' || m_json[valueEnd] == 's' ||
             m_json[valueEnd] == 'n' || m_json[valueEnd] == 'u' ||
             m_json[valueEnd] == 'l'))
      {
         valueEnd++;
      }
      
      return StringSubstr(m_json, valueStart, valueEnd - valueStart);
   }
   
public:
   void SetJson(string json)
   {
      m_json = json;
   }
   
   string GetString(string key, string defaultValue = "")
   {
      string value = ExtractValue(key);
      if(value == "") return defaultValue;
      
      // Check if it's actually a string (starts with quote)
      if(StringGetCharacter(value, 0) == '\"')
      {
         return StringSubstr(value, 1, StringLen(value) - 2);
      }
      
      return value;
   }
   
   double GetNumber(string key, double defaultValue = 0)
   {
      string value = ExtractValue(key);
      if(value == "") return defaultValue;
      
      // Check for true/false
      if(value == "true") return 1;
      if(value == "false") return 0;
      
      return StringToDouble(value);
   }
   
   int GetInteger(string key, int defaultValue = 0)
   {
      string value = ExtractValue(key);
      if(value == "") return defaultValue;
      
      // Check for true/false
      if(value == "true") return 1;
      if(value == "false") return 0;
      
      return (int)StringToInteger(value);
   }
   
   bool GetBool(string key, bool defaultValue = false)
   {
      string value = ExtractValue(key);
      if(value == "") return defaultValue;
      
      if(value == "true") return true;
      if(value == "false") return false;
      if(value == "1") return true;
      if(value == "0") return false;
      
      return defaultValue;
   }
   
   // Static helper methods for quick parsing
   static string ParseString(string json, string key, string defaultValue = "")
   {
      CJson parser;
      parser.SetJson(json);
      return parser.GetString(key, defaultValue);
   }
   
   static double ParseNumber(string json, string key, double defaultValue = 0)
   {
      CJson parser;
      parser.SetJson(json);
      return parser.GetNumber(key, defaultValue);
   }
   
   static int ParseInteger(string json, string key, int defaultValue = 0)
   {
      CJson parser;
      parser.SetJson(json);
      return parser.GetInteger(key, defaultValue);
   }
   
   static bool ParseBool(string json, string key, bool defaultValue = false)
   {
      CJson parser;
      parser.SetJson(json);
      return parser.GetBool(key, defaultValue);
   }
};

#endif

In der JSON-Datei definieren wir einen schlanken, eigenständigen JSON-Parser für MQL5, der die sichere Extraktion einfacher Schlüssel-Wert-Paare ermöglicht, ohne auf externe Bibliotheken zurückgreifen zu müssen. Die Klasse „CJson“ speichert eine JSON-Zeichenkette im Rohformat und nutzt einen kontrollierten Ansatz zum Durchsuchen der Zeichenkette, um Schlüssel zu finden, Leerzeichen zu überspringen und Zeichenketten, sowie numerische und boolesche Werte korrekt zu interpretieren. Es stellt typisierte Zugriffsmethoden (GetString, GetNumber, GetInteger und GetBool) bereit, die bei fehlenden oder fehlerhaften Schlüsseln nahtlos auf Standardwerte zurückgreifen und so die Robustheit in Live-Handelsumgebungen gewährleisten. Um die Nutzung noch weiter zu vereinfachen, ermöglichen statische Hilfsmethoden das Parsen direkt aus einer JSON-Nutzlast in nur einer Zeile. Damit eignet sich diese Klasse ideal für die Verarbeitung von API-Antworten, Konfigurationsmeldungen oder die Kommunikation zwischen Prozessen, bei denen Leistung, Sicherheit und ein Minimum an Abhängigkeiten entscheidend sind.


Live-Demo

Unten ist zu sehen, dass der Flask-Server erfolgreich initialisiert wurde und auf dem localhost am Port 5000 läuft und Signale von Jupyter Lab an MetaTrader 5 weiterleitet.

Signale

MT5-Experten-Journal


Schlussfolgerung

Zusammenfassend lässt sich sagen, dass wir eine Multi-Agenten-Handelsumgebung entwickelt haben, in der unabhängige Agenten über einen gemeinsamen Python-Dienst kommunizieren und über mehrere Symbole hinweg zusammenarbeiten, anstatt isoliert voneinander zu agieren. Jeder Agent erzeugt strukturierte Signale, die über JSON übertragen, innerhalb des MQL5 Expert Advisors sicher analysiert und anhand von Konfidenzschwellenwerten, Risikokontrollen und Symbolvalidierung ausgewertet werden. Diese Architektur ermöglicht eine symbolübergreifende Marktwahrnehmung, eine koordinierte Entscheidungsfindung und eine rückkopplungsgesteuerte Anpassung, wodurch Marktinformationen von verschiedenen Symbolen effektiv in einer einzigen, einheitlichen Ausführungsschicht innerhalb von MetaTrader 5 zusammengeführt werden.

Zusammenfassend lässt sich sagen, dass dieser Ansatz den Handel erheblich verbessern kann, indem er den „Tunnelblick“ verringert und es Strategien ermöglicht, vom breiteren Marktkontext und dem kollektiven Verhalten bei miteinander korrelierten Vermögenswerten zu profitieren. Indem sie die Entscheidungsfindung an kooperierende Agenten auslagern und gleichzeitig die Ausführung, das Risikomanagement und die Validierung streng innerhalb der EA kontrollieren, können Händler ein System schaffen, das flexibler, skalierbarer und leichter weiterzuentwickeln ist. Das Ergebnis ist eine klarere Trennung von Logik und Ausführung, schnellere Testmöglichkeiten und ein intelligenterer Handelsworkflow, der sich natürlicher an veränderte Marktbedingungen anpasst.

Dateiname  Beschreibung der Datei 
 Multi Agents.mq5 Der Haupt-Expert-Advisor, der eine Verbindung zum Python-Server herstellt, Multi-Agent-Handelssignale über JSON empfängt, das Risiko verwaltet und Trades in MetaTrader 5 ausführt.
Json.mq5 Ein schlanker, maßgeschneiderter JSON-Parser, der vom EA verwendet wird, um Zeichenfolgen, Zahlen und boolesche Werte sicher aus Python-generierten Signalantworten zu extrahieren.
MultiAgentsLab.ipynb Das Python-Notebook, das die Multi-Agent-Umgebung aufbaut und ausführt, symbolübergreifende Handelssignale generiert und diese über eine lokale API an MetaTrader übermittelt.

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/21115

Beigefügte Dateien |
Multi_Agents.mq5 (13.07 KB)
Json.mqh (4.69 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (1)
saeedsoleimani1371
saeedsoleimani1371 | 31 Mai 2026 in 16:58
Ihr Artikel hat mir sehr gut gefallen. Ich freue mich schon auf die Fortsetzung … Ich nehme an, Sie sind noch nicht ganz fertig damit …Der Begriff „Multi-Agent“ ist hier eher konzeptioneller Natur als dass es sich um ein tatsächliches KI-System handelt. Diese Agenten lernen nicht eigenständig; sie basieren größtenteils nur auf if/else-Logik. Es handelt sich also eher um ein regelbasiertes Ensemble als um eine ausgefeilte agentenbasierte KI. Außerdem wird „LIQUIDITY“, obwohl es definiert ist, bei der eigentlichen Entscheidungsfindung nicht verwendet.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Behebung von Barrierefreiheitsproblemen bei MQL5-Handelswerkzeugen (Teil I): Hinzufügen kontextbezogener Sprachnachrichten zu MQL5-Indikatoren Behebung von Barrierefreiheitsproblemen bei MQL5-Handelswerkzeugen (Teil I): Hinzufügen kontextbezogener Sprachnachrichten zu MQL5-Indikatoren
Dieser Artikel befasst sich mit einer auf Barrierefreiheit ausgerichteten Erweiterung, die über die standardmäßigen Terminal-Warnmeldungen hinausgeht und mithilfe der MQL5-Ressourcenverwaltung kontextbezogenes Sprachfeedback bereitstellt. Anstelle von allgemeinen Signaltönen vermittelt der Indikator, was geschehen ist und warum, sodass Trader die Marktgeschehnisse nachvollziehen können, ohne sich ausschließlich auf visuelle Beobachtungen verlassen zu müssen. Dieser Ansatz ist besonders für sehbehinderte Trader von großem Nutzen, kommt aber auch vielbeschäftigten Nutzern oder Nutzern, die mehrere Aufgaben gleichzeitig erledigen und eine freihändige Bedienung bevorzugen.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
MQL5-Handelswerkzeuge (Teil 17): Vektorbasierte abgerundete Rechtecke und Dreiecke MQL5-Handelswerkzeuge (Teil 17): Vektorbasierte abgerundete Rechtecke und Dreiecke
In diesem Artikel befassen wir uns mit vektorbasierten Methoden zum Zeichnen abgerundeter Rechtecke und Dreiecke in MQL5 mithilfe von Canvas, wobei Supersampling für eine kantenglättete Darstellung zum Einsatz kommt. Wir setzen Scanline-Füllung, geometrische Vorberechnungen für Bögen und Tangenten sowie Rahmen ein, um glatte, anpassbare Formen zu erstellen. Dieser Ansatz schafft die Grundlage für moderne UI-Elemente in zukünftigen Trading-Tools und unterstützt die Eingabe von Größen, Radien, Rahmen und Deckkraftwerten.