CFTC-Datenanalyse in Python und Erstellung eines KI-Modells
Der Devisenmarkt ist der größte Markt der Welt, doch seine hohe Volatilität erschwert Prognosen. COT/TFF-Berichte geben Aufschluss über die Aktivitäten der „Smart Money“-Akteure und helfen dabei, verborgene Markttrends aufzudecken.
Der vorgeschlagene Ansatz vereint COT/TFF-Daten und Marktnotierungen in einem einzigen Python-Modell mit automatisiertem Handel über MetaTrader 5. So können wir ohne Verzögerungen und ohne menschliches Eingreifen von der Analyse zur Umsetzung übergehen.
Theoretische Grundlagen
Was sind COT- und TFF-Berichte?
Stellen Sie sich vor, Sie hätten die Möglichkeit, einen Blick in die Portfolios der größten Akteure auf dem Devisenmarkt zu werfen – Hedgefonds mit einem Vermögen in Milliardenhöhe, Pensionsfonds, Investmentbanken. Genau das leisten die COT- und TFF-Berichte, die jeden Freitag von der US-amerikanischen Commodity Futures Trading Commission (CFTC) veröffentlicht werden.

Diese Berichte entstanden nach den Marktkrisen der 1970er und 1980er Jahre, als die Aufsichtsbehörden erkannten, dass die Marktteilnehmer Informationen darüber benötigten, was die wichtigsten Akteure taten. Nun ist jeder, der Positionen über einer bestimmten Schwelle hält, verpflichtet, diese offenzulegen. Die CFTC erhebt diese Daten und veröffentlicht sie in aggregierter Form, wobei die Positionen zum Ende des Dienstags ausgewiesen werden.
Die wichtigsten Akteure auf dem Markt: Beteiligte und ihre Beweggründe
Kommerzielle Marktteilnehmer – echte Unternehmen, die Terminkontrakte nicht zu Spekulationszwecken, sondern zur Absicherung gegen Risiken nutzen. Eine Fluggesellschaft kauft Öl-Futures, um sich den Treibstoffpreis zu sichern. Ein Exporteur verkauft Devisenterminkontrakte, um sich gegen einen Wechselkursrückgang abzusichern. Ein Landwirt verkauft Weizen-Terminkontrakte im Voraus, um zu wissen, wie viel er für seine Ernte erhalten wird.
Nicht-kommerzielle Marktteilnehmer – Spekulanten, die handeln, um von Kursschwankungen zu profitieren. Hedgefonds, Investmentbanken, große Vermögensverwaltungsgesellschaften. Sie werden oft als „Smart Money“ bezeichnet, da sie über die Mittel verfügen, die Märkte eingehend zu analysieren.
Kleinanleger – alle anderen Marktteilnehmer mit Positionen unterhalb der Meldeschwellen. Privatanleger, kleine Fonds, einzelne Spekulanten.
Was geht aus den COT-Berichten hervor?
COT-Berichte vermitteln einen Überblick über alle Terminmärkte. Für jede Teilnehmergruppe werden Long-Positionen (Wetten auf einen Kursanstieg), Short-Positionen (Wetten auf einen Kursrückgang) und Netto-Positionen (die Differenz zwischen Long- und Short-Positionen) angezeigt. Das Open Interest gibt die Gesamtzahl der aktiven Kontrakte auf dem Markt an.
Wenn beispielsweise nicht-kommerzielle Marktteilnehmer eine Netto-Long-Position im EUR von +120.000 Kontrakten halten, bedeutet dies, dass Spekulanten im Allgemeinen auf einen Anstieg des EUR/USD-Kurses setzen. Wenn die kommerziellen Händler -115.000 Kontrakte ausweisen, dann rechnen die Hedger entweder mit einer Abschwächung des Euro oder sichern sich lediglich gegen Währungsrisiken ab.
Was bringen TFF-Berichte?
Die TFF-Berichte konzentrieren sich ausschließlich auf Finanz-Futures und vermitteln ein detaillierteres Bild der Positionen institutioneller Anleger. Hier werden nicht-kommerzielle Marktteilnehmer in Unterkategorien unterteilt: Hebelfonds (aggressive Hedgefonds, die in hohem Maße Fremdkapital einsetzen) und Vermögensverwalter (konservative Pensionsfonds und Versicherungsgesellschaften). Außerdem gibt es Händler und Intermediäre – Banken, die für Marktliquidität sorgen.
Dieser Punkt ist entscheidend. Wenn gehebelte Fonds ihre Long-Positionen im US-Dollar stark ausbauen, ist dies ein Zeichen für kurzfristiges spekulatives Interesse. Wenn Vermögensverwalter dasselbe tun, deutet dies auf eine langfristige Veränderung der Stimmung unter institutionellen Anlegern hin.
Warum brauchen Händler das?
Der Hauptnutzen dieser Berichte besteht darin, dass sie aufzeigen, wohin das „Smart Money“ fließt, noch bevor sich dies in den Kursen niederschlägt. Große Akteure handeln oft auf der Grundlage von Daten, die gewöhnlichen Marktteilnehmern nicht zur Verfügung stehen.
Ermittlung von Extremwerten. Wenn Spekulanten Rekord-Long-Positionen eingehen, ist der Markt oft überkauft und steht vor einer Korrektur. Die umgekehrte Situation deutet auf eine mögliche Erholung hin. Es funktioniert nach dem Prinzip des Contrarian Trading – also dem Handeln gegen den Strom in Zeiten extremer Marktbewegungen.
Bestätigung von Trends. Wenn der Kurs steigt und nicht-kommerzielle Marktteilnehmer ihre Long-Positionen weiter ausbauen, ist der Trend stark. Wenn sie bei steigenden Kursen beginnen, ihre Positionen abzubauen, schwächt sich der Trend ab.
Frühzeitige Erkennung von Trendwenden. Abweichungen zwischen Kurs und Positionen gehen oft einer Trendwende voraus. Der Kurs mag zwar weiter steigen, doch wenn die großen Akteure bereits ihre bullischen Positionen abbauen, steht eine Trendwende bevor.
Praktisches Beispiel
Nehmen wir einmal an, der EURUSD-Bericht zeigt, dass Hebelfonds +85.000 Kontrakte halten, Vermögensverwalter +25.000 und Händler -95.000. Das bedeutet, dass sowohl aggressive Spekulanten als auch konservative institutionelle Anleger auf einen Anstieg des Euro setzen. Händler nehmen die Gegenseite ein, etwa um Kundenaufträge auszuführen oder ihre eigenen Risiken abzusichern. Das Gesamtsignal ist für den Euro bullisch.
Wichtige Feinheiten
Die Daten werden mit einer Verzögerung von drei Tagen veröffentlicht, was in sich schnell verändernden Märkten entscheidend ist. Nicht alle kommerziellen Positionen dienen ausschließlich der Absicherung – manche Banken spekulieren unter dem Deckmantel der Geschäftstätigkeit. Der algorithmische Handel und maschinelles Lernen verändern die traditionellen Verhaltensmuster der Marktteilnehmer.
Moderne Algorithmen können die COT-/TFF-Berichte selbst zur Entscheidungsfindung heranziehen, was zu sich selbst erfüllenden Prophezeiungen führt und die Datenauswertung erschwert.
Warum funktioniert das?
Die COT- und TFF-Berichte sind aussagekräftig, weil sie reale Geldpositionen widerspiegeln und keine Meinungen oder Prognosen. Wenn ein Hedgefonds Milliarden von Dollar auf eine bestimmte Marktrichtung setzt, ist das ein weitaus deutlicheres Signal als jede öffentliche Stellungnahme. Diese Daten spiegeln das kollektive Wissen der am besten informierten und am besten ausgestatteten Marktteilnehmer wider.
In Verbindung mit maschinellem Lernen und automatisiertem Handel wird die Analyse institutioneller Positionen zu einem leistungsstarken Instrument für die Entwicklung von Handelsstrategien, die auf dem Verhalten derjenigen basieren, die die Märkte tatsächlich bewegen.
Preisprognosen anhand von COT-/TFF-Daten
Preisprognosen basieren auf der Annahme, dass die Positionen der wichtigsten Marktteilnehmer mit künftigen Kursbewegungen korrelieren. So kann beispielsweise ein Anstieg der Long-Positionen bei nicht-kommerziellen Händlern auf einen bullischen Markt hindeuten, während ein Anstieg der Short-Positionen auf eine bärische Stimmung hindeuten kann. Diese Daten werden als Merkmale für ein Modell des maschinellen Lernens verwendet und durch historische Kursdaten aus MetaTrader 5 sowie technische Indikatoren wie Volatilität und gleitende Durchschnitte ergänzt. Dieser Ansatz ermöglicht es uns, komplexe Zusammenhänge zwischen der Marktstimmung und den Kursentwicklungen zu erfassen.
Vorbereitung der Daten
Die COT- und TFF-Berichte werden im Excel-Format auf der Website der CFTC veröffentlicht. Zum Laden der Daten wird die Requests-Bibliothek verwendet, und zur Verarbeitung kommt Pandas zum Einsatz. Der folgende Code zeigt, wie COT-Daten geladen und vorverarbeitet werden, wobei zur Leistungssteigerung Caching zum Einsatz kommt:
import requests import zipfile import pandas as pd import os import logging import MetaTrader5 as mt5 from datetime import datetime, timedelta import matplotlib.pyplot as plt import seaborn as sns from sklearn.ensemble import RandomForestRegressor from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split import importlib.util import glob import asyncio logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) plt.style.use('ggplot') plt.rcParams['figure.figsize'] = [10, 6] COT_URL = "https://www.cftc.gov/files/dea/history/dea_fut_xls_2024.zip" TFF_URL = "https://www.cftc.gov/files/dea/history/fut_fin_xls_2024.zip" OUTPUT_DIR = "data" os.makedirs(OUTPUT_DIR, exist_ok=True) def load_cot_reports() -> pd.DataFrame: cache_path = os.path.join(OUTPUT_DIR, "cot_report.csv") if os.path.exists(cache_path): logger.info(f"Loading COT data from cache: {cache_path}") return pd.read_csv(cache_path) try: response = requests.get(COT_URL) response.raise_for_status() zip_path = os.path.join(OUTPUT_DIR, "cot_data.zip") with open(zip_path, "wb") as f: f.write(response.content) with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(OUTPUT_DIR) excel_file = [f for f in zip_ref.namelist() if f.endswith('.xls') or f.endswith('.xlsx')][0] cot_data = pd.read_excel(os.path.join(OUTPUT_DIR, excel_file)) relevant_columns = [ "Market_and_Exchange_Names", "NonComm_Positions_Long_All", "NonComm_Positions_Short_All", "Comm_Positions_Long_All", "Comm_Positions_Short_All", "Open_Interest_All" ] cot_data = cot_data[relevant_columns] cot_data["Net_NonComm"] = cot_data["NonComm_Positions_Long_All"] - cot_data["NonComm_Positions_Short_All"] cot_data["Net_Comm"] = cot_data["Comm_Positions_Long_All"] - cot_data["Comm_Positions_Short_All"] cot_data.to_csv(cache_path, index=False) logger.info(f"COT report saved in {cache_path}") return cot_data except Exception as e: logger.error(f"Error loading COT data: {e}") return pd.DataFrame()
Ein ähnliches Verfahren wird für TFF-Berichte verwendet, bei denen nach Währungsfutures gefiltert und die Nettopositionen für gehebelte Fonds und Vermögensverwalter berechnet werden. Durch Daten-Caching werden Netzwerkanfragen minimiert, wodurch die Neuverarbeitung beschleunigt wird.
Integration mit MetaTrader 5
Die historischen Kurse werden über die MetaTrader 5-Bibliothek abgerufen, die Zugriff auf Marktdaten bietet. Der folgende Code ruft die Stundenkurse der letzten 30 Tage ab:
def get_historical_prices(pair: str, days_history: int = 30) -> pd.DataFrame: if not mt5.initialize(): logger.error("MT5 initialization failed") return pd.DataFrame() timeframe = mt5.TIMEFRAME_H1 utc_from = datetime.now() - timedelta(days=days_history) rates = mt5.copy_rates_from(pair, timeframe, utc_from, 24 * days_history) if rates is None or len(rates) == 0: logger.warning(f"No historical data for {pair}") return pd.DataFrame() df = pd.DataFrame(rates) df['time'] = pd.to_datetime(df['time'], unit='s') df.set_index('time', inplace=True) df['price_change_24h'] = df['close'].shift(-24) / df['close'] - 1 df.dropna(inplace=True) return df[['open', 'high', 'low', 'close', 'tick_volume', 'price_change_24h']]
Datenverarbeitung und -zusammenführung
Die Daten von COT, TFF und der historischen Kurse werden kombiniert und um abgeleitete Merkmale ergänzt: Volatilität (die Differenz zwischen Höchst- und Tiefstkurs, normiert auf den Schlusskurs), gleitende 24-Stunden-Durchschnitte für Volumen und Kurs sowie Verzögerungen und prozentuale Veränderungen bei den COT- und TFF-Positionen.
Code zur Merkmalsaufbereitung:
def prepare_features(pair: str, cot_data: pd.DataFrame, tff_data: pd.DataFrame) -> pd.DataFrame: df_prices = get_historical_prices(pair) if df_prices.empty: logger.warning(f"No price data available for {pair}") df = pd.DataFrame(index=[datetime.now()], columns=['close', 'price_change_24h']) df['close'] = 1.0 df['price_change_24h'] = 0.0 else: df = df_prices.copy() df['volatility'] = (df['high'] - df['low']) / df['close'] df['volume_sma_24'] = df['tick_volume'].rolling(window=24).mean() df['price_sma_24'] = df['close'].rolling(window=24).mean() df['price_change_1h'] = df['close'].pct_change() market = map_pair_to_cot_tff(pair) if market and not cot_data.empty: cot_subset = cot_data[cot_data["Market_and_Exchange_Names"].str.contains(market, case=False, na=False)] if not cot_subset.empty: cot_features = cot_subset[['Net_NonComm', 'Net_Comm']].mean().to_frame().T for col in cot_features.columns: df[col] = cot_features[col].iloc[0] if market and not tff_data.empty: tff_subset = tff_data[tff_data["Market_and_Exchange_Names"].str.contains(market, case=False, na=False)] if not tff_subset.empty: tff_features = tff_subset[['Net_Lev_Money', 'Net_Asset_Mgr']].mean().to_frame().T for col in tff_features.columns: df[col] = tff_features[col].iloc[0] for col in ['Net_NonComm', 'Net_Comm', 'Net_Lev_Money', 'Net_Asset_Mgr']: if col in df.columns: df[f'{col}_lag1'] = df[col].shift(1) df[f'{col}_change'] = df[col].pct_change().fillna(0) df.dropna(inplace=True) return df def map_pair_to_cot_tff(pair: str) -> str: mapping = { 'EURUSD': 'EURO FX', 'GBPUSD': 'BRITISH POUND', 'USDJPY': 'JAPANESE YEN', 'AUDUSD': 'AUSTRALIAN DOLLAR', 'USDCAD': 'CANADIAN DOLLAR', 'USDCHF': 'SWISS FRANC', 'NZDUSD': 'NEW ZEALAND DOLLAR' } base_pair = pair.replace('.ecn', '')[:6] return mapping.get(base_pair, '')
Um die Genauigkeit zu verbessern, können Hyperparameter wie die Anzahl der Bäume oder die maximale Tiefe optimiert werden, und zur Beurteilung der Robustheit des Modells kann eine Kreuzvalidierung herangezogen werden. Die Merkmalsbedeutung wird in einer CSV-Datei gespeichert, um deren Einfluss auf die Prognosen zu analysieren.
Prognosen und Visualisierung
Preisprognosen
Die Prognose basiert auf den aktuellsten Daten und sagt die prozentuale Preisänderung innerhalb von 24 Stunden voraus, die auf den aktuellen Marktpreis angewendet wird. Vorhersagecode:
async def get_price_forecast(pair: str, model, scaler) -> dict: df = prepare_features(pair, cot_data, tff_data) if df.empty: logger.warning(f"No data to forecast for {pair}") return {'pair': pair, 'forecast_price': None, 'confidence': 0.0} X_latest = df.drop(columns=['price_change_24h']).iloc[-1:] X_scaled = scaler.transform(X_latest) price_change_pred = model.predict(X_scaled)[0] confidence = model.score(X_scaled, df['price_change_24h'].iloc[-1:]) if len(df) > 1 else 0.6 tick = mt5.symbol_info_tick(pair) if not tick: logger.warning(f"No current data for {pair}") return {'pair': pair, 'forecast_price': None, 'confidence': 0.0} current_price = (tick.bid + tick.ask) / 2 forecast_price = current_price * (1 + price_change_pred) forecast_df = pd.DataFrame([{ 'forecast_price': forecast_price, 'confidence': confidence, 'current_price': current_price, 'price_change_pred': price_change_pred, 'timestamp': datetime.now() }]) output_path = os.path.join(OUTPUT_DIR, f"forecast_{pair}.csv") forecast_df.to_csv(output_path, index=False) logger.info(f"Forecast for {pair} saved in {output_path}") visualize_forecast(pair, current_price, forecast_price, confidence) return { 'pair': pair, 'forecast_price': forecast_price, 'confidence': max(0.0, min(1.0, confidence)) }
Darstellung der Ergebnisse
Zur Analyse werden Diagramme des aktuellen und des prognostizierten Kurses sowie der Netto-COT- und TFF-Positionen erstellt. Visualisierungscode:
def visualize_cot_data(cot_data: pd.DataFrame): if cot_data.empty or "Net_NonComm" not in cot_data.columns: logger.warning("No COT data available for visualization") return plt.figure(figsize=(14, 8)) for market in cot_data["Market_and_Exchange_Names"].unique(): market_data = cot_data[cot_data["Market_and_Exchange_Names"] == market] plt.plot(range(len(market_data)), market_data["Net_NonComm"], label=market, alpha=0.7) plt.title("Net Non-Commercial positions for currency futures") plt.xlabel("Entry") plt.ylabel("Net positions") plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() output_path = os.path.join(OUTPUT_DIR, "cot_net_positions.png") plt.savefig(output_path, dpi=150) plt.close() logger.info(f"Chart of net COT positions saved in {output_path}") def visualize_tff_data(tff_data: pd.DataFrame): if tff_data.empty or "Net_Lev_Money" not in tff_data.columns: logger.warning("No TFF data available for visualization") return plt.figure(figsize=(14, 8)) for market in tff_data["Market_and_Exchange_Names"].unique(): market_data = tff_data[tff_data["Market_and_Exchange_Names"] == market] plt.plot(range(len(market_data)), market_data["Net_Lev_Money"], label=market, alpha=0.7) plt.title("Leveraged Funds net positions for currency futures (TFF)") plt.xlabel("Entry") plt.ylabel("Net positions") plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() output_path = os.path.join(OUTPUT_DIR, "tff_net_positions.png") plt.savefig(output_path, dpi=150) plt.close() logger.info(f"Chart of net TFF positions saved in {output_path}") def visualize_forecast(pair: str, current_price: float, forecast_price: float, confidence: float): plt.figure(figsize=(8, 5)) plt.bar(['Current Price', 'Forecast Price'], [current_price, forecast_price], color=['blue', 'green'], alpha=0.7) plt.title(f"Price forecast in 24 hours for {pair} (Confidence: {confidence:.2f})") plt.ylabel('Price') plt.tight_layout() output_path = os.path.join(OUTPUT_DIR, f"forecast_{pair}_plot.png") plt.savefig(output_path, dpi=150) plt.close() logger.info(f"Forecast graph saved to {output_path}")
Diagramme helfen dabei, die Marktstimmung und die Prognosegenauigkeit visuell einzuschätzen, indem sie den Händlern ein klares Verständnis der Daten vermitteln.
Optimierung und Fehlerbehandlung
Datenzwischenspeicherung
Um die Anzahl der Netzwerkanfragen zu minimieren, werden COT- und TFF-Daten in CSV-Dateien zwischengespeichert, was die Wiederverwendung aktueller Daten und eine schnellere Verarbeitung ermöglicht. Vor dem Laden neuer Daten wird der Cache überprüft, und nur wenn die Daten fehlen oder veraltet sind, wird eine neue Anfrage gestellt.
Abhängigkeiten prüfen
Vor der Ausführung prüft der Code, ob die Bibliotheken xlrd und openpyxl installiert sind:
def check_dependencies(): dependencies = ['xlrd', 'openpyxl'] for dep in dependencies: if not importlib.util.find_spec(dep): logger.error(f"Missing dependency: {dep}. Install it using 'pip install {dep}'.") raise ImportError(f"Missing dependency: {dep}")
Fehlerbehandlung
Der Code umfasst eine Ausnahmebehandlung für alle kritischen Vorgänge: das Laden von Daten, die Verbindung zu MetaTrader 5 und das Trainieren des Modells. Dadurch wird sichergestellt, dass das System gegenüber Störungen wie fehlenden Daten oder Verbindungsproblemen widerstandsfähig ist.
Praktische Anwendung
Testen des Modells
Zur Bewertung des Modells wird empfohlen, es anhand historischer Daten für das Jahr 2024 zu testen. R²-Werte und die Bedeutung der Merkmale werden zur Analyse in CSV-Dateien gespeichert. Durch Tests können wir die Genauigkeit von Prognosen bewerten und die wichtigsten Merkmale ermitteln, wie beispielsweise die Nettopositionen nicht-kommerzieller Händler oder die Volatilität.
Einbindung in eine Handelsstrategie
Die Prognosen können über die MetaTrader 5-Bibliothek für den automatisierten Handel genutzt werden. Wenn beispielsweise die prognostizierte Kursänderung mehr als 0,5 % beträgt und das Modell eine hohe Konfidenz aufweist (über 0,7), können Sie Long- oder Short-Positionen eröffnen. Code für den automatischen Handel:
def execute_trade(pair: str, forecast_price: float, confidence: float): if not mt5.initialize(): logger.error("MT5 initialization failed") return symbol_info = mt5.symbol_info(pair) if not symbol_info: logger.warning(f"{pair} symbol not found") return current_price = (mt5.symbol_info_tick(pair).bid + mt5.symbol_info_tick(pair).ask) / 2 if confidence > 0.7 and forecast_price > current_price * 1.005: request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": pair, "volume": 0.1, "type": mt5.ORDER_TYPE_BUY, "price": mt5.symbol_info_tick(pair).ask, "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(request) logger.info(f"Opened long position for {pair}: {result}") elif confidence > 0.7 and forecast_price < current_price * 0.995: request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": pair, "volume": 0.1, "type": mt5.ORDER_TYPE_SELL, "price": mt5.symbol_info_tick(pair).bid, "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(request) logger.info(f"Opened short position for {pair}: {result}")
Erweiterung der Funktionalität
Um das Modell zu verbessern, können wir technische Indikatoren wie RSI oder MACD hinzufügen, um zusätzliche Marktsignale zu berücksichtigen. Alternative Algorithmen wie Gradient Boosting (XGBoost) oder neuronale Netze können die Prognosegenauigkeit verbessern. Die dynamische Aktualisierung von COT- und TFF-Daten kann über einen Task-Scheduler, wie beispielsweise die „schedule“-Bibliothek, implementiert werden, um neue Berichte automatisch abzurufen, sobald sie veröffentlicht werden. Das Verfahren lässt sich durch entsprechende Anpassung der Merkmale auch auf die Analyse anderer Vermögenswerte, wie beispielsweise Rohstoffe oder Indizes, ausweiten.
Vollständige Implementierung: Modul zur Währungsprognose
Um die Integration zu vereinfachen, sind alle Funktionen in der Klasse „CurrencyForecastModule“ zusammengefasst, die das Laden von Daten, das Trainieren des Modells, die Prognoseerstellung und die Visualisierung umfasst:
class CurrencyForecastModule: def __init__(self, pairs: list, days_history: int = 30): self.pairs = pairs self.days_history = days_history self.models = {} self.scalers = {} self.forecasts = {} check_dependencies() if not mt5.initialize(): logger.error("MT5 initialization failed. Ensure MT5 terminal is running and connected.") raise RuntimeError("MT5 initialization failed") self._validate_symbols() self._initialize_data() def _validate_symbols(self): available_symbols = [s.name for s in mt5.symbols_get()] logger.info(f"Available symbols in MT5: {available_symbols}") self.symbol_mapping = {} for pair in self.pairs[:]: if pair in available_symbols: self.symbol_mapping[pair] = pair else: base_pair = pair.split('.')[0] if base_pair in available_symbols: self.symbol_mapping[pair] = base_pair logger.info(f"Matched: {pair} -> {base_pair}") else: logger.warning(f"{pair} symbol not found in MT5. Skipped.") self.pairs.remove(pair) def _initialize_data(self): logger.info("Initializing data for CurrencyForecastModule...") self.cot_data = load_cot_reports() self.tff_data = self._load_tff_reports() for pair in self.pairs: self._train_model(pair) def _load_tff_reports(self) -> pd.DataFrame: cache_path = os.path.join(OUTPUT_DIR, "tff_report.csv") if os.path.exists(cache_path): logger.info(f"Loading TFF data from cache: {cache_path}") return pd.read_csv(cache_path) try: response = requests.get(TFF_URL) response.raise_for_status() zip_path = os.path.join(OUTPUT_DIR, "tff_data.zip") with open(zip_path, "wb") as f: f.write(response.content) with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(OUTPUT_DIR) logger.info(f"TFF archive contents: {zip_ref.namelist()}") excel_files = glob.glob(os.path.join(OUTPUT_DIR, "**", "*.xls*"), recursive=True) tff_files = [f for f in excel_files if 'FinFut' in f or 'fin' in f.lower()] if not tff_files: logger.error("TFF Excel file not found in extracted files") return pd.DataFrame() excel_file = tff_files[0] logger.info(f"Handling TFF file: {excel_file}") relevant_columns = [ "Market_and_Exchange_Names", "Lev_Money_Positions_Long_All", "Lev_Money_Positions_Short_All", "Asset_Mgr_Positions_Long_All", "Asset_Mgr_Positions_Short_All", "Open_Interest_All" ] tff_data = pd.read_excel(excel_file, engine='xlrd' if excel_file.endswith('.xls') else 'openpyxl') available_columns = [col for col in relevant_columns if col in tff_data.columns] if not available_columns: logger.error("Expected columns in TFF data not found") return pd.DataFrame() tff_data = tff_data[available_columns] forex_markets = ["EURO FX", "JAPANESE YEN", "BRITISH POUND", "AUSTRALIAN DOLLAR", "CANADIAN DOLLAR", "SWISS FRANC", "MEXICAN PESO", "NEW ZEALAND DOLLAR"] tff_data = tff_data[tff_data["Market_and_Exchange_Names"].str.contains('|'.join(forex_markets), case=False, na=False)] if "Lev_Money_Positions_Long_All" in tff_data.columns: tff_data["Net_Lev_Money"] = tff_data["Lev_Money_Positions_Long_All"] - tff_data["Lev_Money_Positions_Short_All"] if "Asset_Mgr_Positions_Long_All" in tff_data.columns: tff_data["Net_Asset_Mgr"] = tff_data["Asset_Mgr_Positions_Long_All"] - tff_data["Asset_Mgr_Positions_Short_All"] tff_data.to_csv(cache_path, index=False) logger.info(f"TFF report saved in {cache_path}") visualize_tff_data(tff_data) return tff_data except Exception as e: logger.error(f"Error loading TFF data: {e}") return pd.DataFrame() def _train_model(self, pair: str): df = prepare_features(pair, self.cot_data, self.tff_data) model, scaler = train_model(pair, df) if model and scaler: self.models[pair] = model self.scalers[pair] = scaler async def update_forecasts(self): logger.info("Updating price forecasts...") for pair in self.pairs: forecast = await get_price_forecast(pair, self.models.get(pair), self.scalers.get(pair)) logger.info(f"Forecast for {pair}: Price={forecast['forecast_price']}, Confidence={forecast['confidence']:.2f}") def __del__(self): mt5.shutdown()
Diese Klasse bietet eine modulare Struktur zum Laden von Daten, Trainieren von Modellen und Durchführen von Prognosen und vereinfacht so die Integration in Handelssysteme.
Als Ergebnis erhalten wir Prognosen und verschiedene Diagramme. Hier ist zum Beispiel ein Diagramm, das die COT- und TFF-Positionen gegenüberstellt:

Der Code erstellt letztendlich 24-Stunden-Kursprognosen für eine Gruppe von Symbolen:

Allerdings wäre es natürlich logischer, den Schlusskurs vom Freitagabend als Prognose heranzuziehen – dann würde dies mit dem Veröffentlichungsrhythmus der COT- und TFF-Berichte übereinstimmen.
Schlussfolgerung
Durch die Nutzung von COT- und TFF-Daten in Verbindung mit historischen Kursen über die Python-Bibliothek von MetaTrader 5 können wir effiziente Kursprognosemodelle erstellen, die in Handelsstrategien integriert werden können. Die implementierte Lösung automatisiert das Laden von Daten, das Trainieren von Modellen und die Handelsausführung und bietet Händlern damit eine stabile Grundlage für Analysen und Entscheidungsfindungen auf den Finanzmärkten. Der Code kann durch das Hinzufügen neuer Indikatoren oder Algorithmen erweitert werden; außerdem lassen sich Datenaktualisierungen automatisieren, um sicherzustellen, dass die Prognosen stets auf dem neuesten Stand sind.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/18303
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
| Net_NonComm,0.0,0.0 | |||
| Net_Comm,0.0,0.0 | |||
| Net_Lev_Money,0.0,0.0 | |||
| Net_Asset_Mgr,0.0,0.0 | |||
| Net_NonComm_lag1,0.0,0.0 | |||
| Net_NonComm_change,0.0,0.0 | |||
| Net_Comm_lag1,0.0,0.0 | |||
| Net_Comm_change,0.0,0.0 | |||
| Net_Lev_Money_lag1,0.0,0.0 | |||
| Net_Lev_Money_change,0.0,0.0 | |||
| Net_Asset_Mgr_lag1,0.0,0.0 | |||
| Net_Asset_Mgr_change,0.0,0.0 | |||
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Marktsimulation (Teil 23): Erste Schritte mit SQL (VI)
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Evolutionäre Strategie zur Anpassung der Kovarianzmatrix (CMA-ES)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.