Minería de datos de la CFTC en Python y creación de un modelo de IA
El mercado Forex es el más grande del mundo, pero su alta volatilidad dificulta la realización de pronósticos. Los informes COT/TFF ofrecen información sobre los movimientos del dinero inteligente y ayudan a detectar tendencias subyacentes del mercado.
El enfoque propuesto combina datos COT/TFF y cotizaciones del mercado en un único modelo Python, con comercio automatizado a través de MetaTrader 5. Esto permite pasar del análisis a la acción sin demoras ni intervención humana.
Base teórica
¿Qué son los informes COT y TFF?
Imagínese poder analizar las carteras de los participantes más importantes del mercado de divisas: fondos de cobertura con miles de millones de dólares en activos, fondos de pensiones, bancos de inversión, etc. Esto es exactamente lo que hacen los informes COT y TFF, publicados todos los viernes por la Comisión de Comercio de Futuros de Productos Básicos de Estados Unidos (CFTC).

Estos informes surgieron después de las crisis del mercado de los años 1970 y 1980, cuando los reguladores se dieron cuenta de que los participantes del mercado necesitaban información sobre lo que estaban haciendo los principales participantes. A partir de entonces todos aquellos que ocupen posiciones por encima de un determinado umbral deberán revelar sus posiciones. La CFTC recopila esta información y la publica en forma agregada, mostrando las posiciones al final del martes.
Quién es quién en el mercado: los participantes y sus motivaciones
Los traders comerciales son empresas reales que utilizan futuros no para especular, sino para protegerse de riesgos. Las aerolíneas compran futuros de petróleo para fijar el precio del combustible. Los exportadores venden futuros de divisas para protegerse contra una caída del tipo de cambio. Los agricultores venden futuros de trigo por adelantado para saber cuánto recibirá por la cosecha.
Los traders no comerciales son especuladores que negocian para obtener ganancias de los movimientos de precios. Son fondos de cobertura, bancos de inversión y grandes sociedades de gestión. A menudo se les llama "dinero inteligente" porque tienen los recursos para analizar los mercados en profundidad.
Los traders pequeños son todos los demás participantes con posiciones por debajo de los umbrales de informe. Traders minoristas, pequeños fondos y especuladores individuales.
¿Qué muestran los informes del COT?
Los informes COT ofrecen una imagen general de todos los mercados de futuros. Para cada grupo de participantes, se muestran las posiciones largas (apuestas alcistas), las posiciones cortas (apuestas bajistas) y las posiciones netas (la diferencia entre largas y cortas). El interés abierto muestra el número total de contratos activos en el mercado.
Por ejemplo, si los traders no comerciales tienen una posición larga neta en euros de +120.000 contratos, esto significa que los especuladores generalmente apuestan a que el EUR/USD subirá. Si los traders comerciales muestran -115.000 contratos, entonces los coberturistas esperan que el euro se debilite o simplemente se protegen de los riesgos cambiarios.
Qué añaden los informes de TFF
Los informes de TFF se centran únicamente en los futuros financieros y ofrecen una imagen más detallada de las posiciones institucionales. Aquí, los traders no comerciales se dividen en subcategorías: fondos apalancados (fondos de cobertura agresivos que utilizan en gran medida fondos prestados) y gestores de activos (fondos de pensiones y compañías de seguros conservadoras). También hay distribuidores e intermediarios: bancos que ofrecen liquidez al mercado.
Este detalle es de importancia crítica. Si los fondos apalancados aumentan drásticamente sus posiciones largas en dólares, es una señal de interés especulativo a corto plazo. Si los administradores de activos hacen lo mismo, esto indicará un cambio a largo plazo en el sentimiento de los inversores institucionales.
¿Por qué los traders necesitan esto?
El principal valor de los informes es que muestran hacia dónde fluye el dinero inteligente antes de que se refleje en los precios. Los grandes actores a menudo actúan basándose en información que no está disponible para los participantes ordinarios del mercado.
Identificación de extremos. Cuando los especuladores toman posiciones largas récord, el mercado suele mostrar sobrecompra y está listo para una corrección. La situación opuesta señala un posible repunte. Esto funciona según el principio del trading contrario: actuar contra la multitud en momentos extremos.
Confirmación de tendencias. Si el precio sube y los traders no comerciales continúan aumentando sus posiciones largas, la tendencia es fuerte. Si comienzan a reducir posiciones cuando los precios suben, la tendencia se debilita.
Detección temprana de reversiones. Las divergencias entre el precio y las posiciones suelen preceder a las reversiones. El precio puede continuar subiendo, pero si los principales actores ya están reduciendo sus apuestas al crecimiento, se aproxima una reversión.
Ejemplo práctico
Digamos que el informe EUR/USD muestra que los fondos apalancados tienen +85.000 contratos, los gestores de activos +25.000 y los distribuidores -95.000. Esto significa que tanto los especuladores agresivos como los inversores institucionales conservadores están apostando al alza del euro. Los distribuidores adoptan el lado opuesto, tal vez ejecutando órdenes de clientes o cubriendo sus propios riesgos. La señal general es alcista para el euro.
Matices importantes a considerar
Los datos se publican con un retraso de tres días, lo que resulta fundamental en mercados de rápida evolución. No todas las posiciones comerciales son pura cobertura: algunos bancos pueden especular bajo la apariencia de actividad comercial. El trading algorítmico y el aprendizaje automático están cambiando los patrones de comportamiento tradicionales de los participantes.
Los algoritmos modernos pueden usar los propios informes COT/TFF para tomar decisiones, lo que crea profecías autocumplidas y complica la interpretación de los datos.
¿Por qué funciona esto?
Los informes COT y TFF funcionan porque muestran tasas monetarias reales, no opiniones ni pronósticos. Cuando un fondo de cobertura apuesta miles de millones de dólares en una dirección particular del mercado, esto supone una señal mucho más significativa que cualquier comentario público. Los datos reflejan la sabiduría colectiva de los participantes del mercado más informados y con más recursos.
Cuando se combina con el aprendizaje automático y el trading automatizado, el análisis de la posición institucional se convierte en una herramienta poderosa para crear estrategias de trading basadas en el comportamiento de quienes realmente mueven los mercados.
Pronóstico de precios usando los datos de COT/TFF
La previsión de precios se basa en el supuesto de que las posiciones de los principales actores están correlacionadas con los futuros movimientos de precios. Por ejemplo, un aumento en las posiciones largas de los traders no comerciales puede indicar un mercado alcista, mientras que un aumento en las posiciones cortas puede indicar un sentimiento bajista. Estos datos se usan como características para un modelo de aprendizaje automático, complementado con precios históricos de MetaTrader 5 e indicadores técnicos como volatilidad y promedios móviles. Este enfoque nos permite captar relaciones complejas entre el sentimiento del mercado y las tendencias de precios.
Preparación de los datos
Los informes COT y TFF se publican en formato Excel en el sitio web de la CFTC. La biblioteca de solicitudes se usa para cargarlos, mientras que pandas se utiliza para procesarlas. El código siguiente demuestra cómo cargar y preprocesar datos COT con almacenamiento en caché para mejorar el rendimiento:
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"Загрузка COT данных из кэша: {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 сохранен в {cache_path}") return cot_data except Exception as e: logger.error(f"Ошибка при загрузке данных COT: {e}") return pd.DataFrame()
Para los informes TFF, se usa un proceso similar, filtrando por futuros de divisas y calculando posiciones netas para fondos apalancados y gestores de activos. El almacenamiento en caché de datos minimiza las solicitudes de red, lo que acelera el reprocesamiento.
Integración con MetaTrader 5
Los precios históricos se descargan a través de la biblioteca MetaTrader 5, que ofrece acceso a los datos del mercado. El código siguiente obtiene los precios por hora de los últimos 30 días:
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"Нет исторических данных для {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']]
Procesamiento y fusión de datos
Se combinan datos de precios históricos, COT y TFF, y se agregan características derivadas: volatilidad (la diferencia entre los precios máximos y mínimos, normalizada al precio de cierre), promedios móviles de 24 horas para volumen y precio, y retrasos y cambios porcentuales para posiciones COT y TFF.
Código de preparación de características:
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"Нет ценовых данных для {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, '')
Para mejorar la precisión, se pueden optimizar hiperparámetros como el número de árboles o la profundidad máxima, y se puede usar la validación cruzada para evaluar la solidez del modelo. La importancia de las características se guarda en un archivo CSV para analizar su impacto en los pronósticos.
Previsión y visualización
Previsión de precios
El pronóstico se realiza en base a los últimos datos, prediciendo el cambio porcentual del precio en 24 horas, que se aplica al precio actual del mercado. Código de pronóstico:
async def get_price_forecast(pair: str, model, scaler) -> dict: df = prepare_features(pair, cot_data, tff_data) if df.empty: logger.warning(f"Нет данных для прогнозирования для {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"Нет текущих данных для {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"Прогноз для {pair} сохранен в {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)) }
Visualización de resultados
Para el análisis, se crean gráficos de los precios actual y proyectado, así como de las posiciones netas COT y TFF. Código de visualización:
def visualize_cot_data(cot_data: pd.DataFrame): if cot_data.empty or "Net_NonComm" not in cot_data.columns: logger.warning("Нет данных COT для визуализации") 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("Чистые позиции Non-Commercial для валютных фьючерсов") plt.xlabel("Запись") plt.ylabel("Чистые позиции") 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"График чистых позиций COT сохранен в {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("Нет данных TFF для визуализации") 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 для валютных фьючерсов (TFF)") plt.xlabel("Запись") plt.ylabel("Чистые позиции") 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"График чистых позиций TFF сохранен в {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"Прогноз цены через 24 часа для {pair} (Confidence: {confidence:.2f})") plt.ylabel('Цена') 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"График прогноза сохранен в {output_path}")
Los gráficos ayudan a evaluar visualmente el sentimiento del mercado y la precisión del pronóstico ofreciendo a los traders una comprensión clara de los datos.
Optimización y procesamiento de errores
Almacenamiento en caché de datos
Para minimizar las solicitudes de red, los datos COT y TFF se almacenan en caché en archivos CSV, lo cual permite la reutilización de datos actualizados y un procesamiento más rápido. La caché se comprueba antes de cargar datos nuevos y solo si faltan o están desactualizados se realiza una nueva solicitud.
Comprobando dependencias
Antes del lanzamiento, se verifica la presencia de las bibliotecas xlrd y openpyxl necesarias para leer archivos Excel:
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}")
Procesamiento de errores
El código incluye el procesamiento de excepciones para todas las operaciones críticas: carga de datos, conexión a MetaTrader 5 y entrenamiento del modelo. Esto garantiza que el sistema sea resistente a fallas, como datos faltantes o problemas de conexión.
Uso práctico
Pruebas del modelo
Para valorar el modelo, recomendamos realizar pruebas con datos históricos del año 2024. Las métricas de R² y la importancia de las características se guardan en archivos CSV para su análisis. Las pruebas nos permiten estimar la precisión de los pronósticos e identificar las características más significativas, como las posiciones netas de los traders no comerciales o la volatilidad.
Integración en una estrategia comercial
Los pronósticos se pueden usar para el trading automatizado a través de la biblioteca MetaTrader 5. Por ejemplo, si el cambio de precio previsto es superior al 0,5% y el modelo tiene un alto nivel de confianza (por encima del 0,7), podemos abrir posiciones largas o cortas. Código para el trading automático:
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} не найден") 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"Открыта длинная позиция для {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"Открыта короткая позиция для {pair}: {result}")
Ampliación de la funcionalidad
Para mejorar el modelo, podemos agregar indicadores técnicos como RSI o MACD para considerar señales de mercado adicionales. Algoritmos alternativos como el aumento de gradiente (XGBoost) o las redes neuronales pueden mejorar la precisión del pronóstico. La actualización dinámica de los datos COT y TFF se puede implementar a través de un programador de tareas, como la biblioteca schedule, para recuperar automáticamente nuevos informes a medida que se publican. También se puede ampliar para analizar otros activos, como materias primas o índices, con la adaptación adecuada de las características.
Implementación completa: Módulo de pronóstico de divisas
Para facilitar la integración, todas las funciones se combinan en la clase CurrencyForecastModule, que encapsula la carga de datos, el entrenamiento del modelo, la previsión y la visualización:
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"Доступные символы в 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"Сопоставлено: {pair} -> {base_pair}") else: logger.warning(f"Символ {pair} не найден в MT5. Пропускается.") self.pairs.remove(pair) def _initialize_data(self): logger.info("Инициализация данных для 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"Загрузка TFF данных из кэша: {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 архива: {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("Excel-файл TFF не найден в извлеченных файлах") return pd.DataFrame() excel_file = tff_files[0] logger.info(f"Обработка TFF файла: {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("Не найдены ожидаемые столбцы в данных TFF") 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 сохранен в {cache_path}") visualize_tff_data(tff_data) return tff_data except Exception as e: logger.error(f"Ошибка при загрузке данных TFF: {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("Обновление прогнозов цен...") for pair in self.pairs: forecast = await get_price_forecast(pair, self.models.get(pair), self.scalers.get(pair)) logger.info(f"Прогноз для {pair}: Цена={forecast['forecast_price']}, Уверенность={forecast['confidence']:.2f}") def __del__(self): mt5.shutdown()
Esta clase ofrece una estructura modular para cargar datos, entrenar modelos y realizar pronósticos, simplificando la integración en los sistemas comerciales.
Como resultado, obtenemos pronósticos y varios gráficos. Aquí, por ejemplo, tenemos un gráfico con las posiciones COT vs TFF:

El resultado del código es un pronóstico de precios para un grupo de símbolos en 24 horas:

Aunque, obviamente, resultaría más lógico utilizar el cierre del viernes por la noche como pronóstico, entonces sería más coherente con la frecuencia de publicación de los informes COT y TFF.
Conclusión
El uso de datos COT y TFF con precios históricos a través de la biblioteca Python de MetaTrader 5 permite crear modelos de pronóstico de precios efectivos que se pueden integrar en estrategias comerciales. La solución implementada automatiza la carga de datos, el entrenamiento de modelos y la ejecución de operaciones, ofreciendo a los traders una base estable para el análisis y la toma de decisiones en los mercados financieros. El código se puede ampliar agregando nuevos indicadores o algoritmos, además de automatizando las actualizaciones de datos para garantizar que los pronósticos estén siempre actualizados.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/18303
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
| 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 | |||
Utilizando redes neuronales en MetaTrader
Minería de datos de los balances de los bancos centrales y obtención de un panorama de la liquidez global
Particularidades del trabajo con números del tipo double en MQL4
Creación de un Panel de administración de operaciones en MQL5 (Parte X): Interfaz basada en recursos externos
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso