English Русский 中文 Deutsch 日本語 Português
preview
Análisis del impacto del clima en las divisas de los países agrícolas usando Python

Análisis del impacto del clima en las divisas de los países agrícolas usando Python

MetaTrader 5Integración |
230 1
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Introducción al tema: la conexión entre el clima y los mercados financieros

La teoría económica clásica no ha reconocido durante mucho tiempo la influencia de los factores meteorológicos en el comportamiento del mercado. Pero las investigaciones de las últimas décadas han modificado por completo nuestra forma de ver esta situación. El profesor Edward Saikin, de la Universidad de Michigan, que realizó un estudio al respecto en 2023, demostró que los tráders toman decisiones un 27% más comedidas cuando hace mal tiempo que en los días soleados.

Esto resulta especialmente notable en los mayores centros financieros. Los días en que las temperaturas superan los 30°C, el volumen comercial la Bolsa de Nueva York desciende aproximadamente un 15% de media. En las bolsas asiáticas, cuando la presión atmosférica exterior es inferior a 740 mmHg, este hecho se correlaciona con un aumento de la volatilidad. Y los largos periodos de inclemencias meteorológicas en Londres provocan un notable aumento de la demanda de activos defensivos.

En este artículo, partiremos de la recopilación de datos meteorológicos para finalmente crear un sistema comercial completo que analizará los factores meteorológicos. Nuestro trabajo se basará en datos comerciales reales de los últimos cinco años en los principales centros financieros del mundo: Nueva York, Londres, Tokio, Hong Kong y Fráncfort. Aplicando herramientas reales de análisis de datos y aprendizaje automático, obtendremos señales comerciales procesables a partir de las observaciones meteorológicas.


Recopilación de datos meteorológicos

Uno de los factores más importantes del sistema será el módulo de adquisición y preprocesamiento de datos. Para trabajar con datos meteorológicos, usaremos la API Meteostat, que permite acceder a datos meteorológicos archivados en todo el planeta. Veamos cómo se implementa la función de obtención de datos:

def fetch_agriculture_weather():
    """
    Fetching weather data for important agricultural regions
    """
    key_regions = {
        "AU_WheatBelt": {
            "lat": -31.95, 
            "lon": 116.85,
            "description": "Key wheat production region in Australia"
        },
        "NZ_Canterbury": {
            "lat": -43.53,
            "lon": 172.63,
            "description": "Main dairy production region in New Zealand"
        },
        "CA_Prairies": {
            "lat": 50.45, 
            "lon": -104.61,
            "description": "Canada's breadbasket, wheat and canola production"
        }
    }

En esta función, identificaremos las regiones agrícolas más importantes con sus coordenadas de localización. Las coordenadas elegidas para el cinturón de cultivo de trigo de Australia serán las de la parte central de la región, para Nueva Zelanda las del emplazamiento de Canterbury y para Canadá las de la zona central de la pradera.

Una vez obtenidos los datos brutos, deberemos someterlos a un riguroso procesamiento. Para ello, implementaremos la funciónProcess_weather_data:

def process_weather_data(raw_data):
    if not isinstance(raw_data.index, pd.DatetimeIndex):
        raw_data.index = pd.to_datetime(raw_data.index)
    
    processed_data = pd.DataFrame(index=raw_data.index)
    
    processed_data['temperature'] = raw_data['tavg']
    processed_data['temp_min'] = raw_data['tmin']
    processed_data['temp_max'] = raw_data['tmax']
    processed_data['precipitation'] = raw_data['prcp']
    processed_data['wind_speed'] = raw_data['wspd']
    
    processed_data['growing_degree_days'] = calculate_gdd(
        processed_data['temp_max'], 
        base_temp=10
    )
    
    return processed_data

También deberemos prestar atención al cálculo del indicador GrowingDegreeDays (GDD), que supondrá una métrica necesaria para evaluar la posibilidad de crecimiento de los cultivos. Esta cifra se basará en la temperatura máxima durante el día, considerando la temperatura normal de crecimiento de las plantas.

def analyze_and_visualize_correlations(merged_data):
   plt.style.use('default')
   plt.rcParams['figure.figsize'] = [15, 10]
   plt.rcParams['axes.grid'] = True
   
   # Weather-price correlation analysis for each region
   for region, data in merged_data.items():
       if data.empty:
           continue
           
       weather_cols = ['temperature', 'precipitation', 'wind_speed', 'growing_degree_days']
       price_cols = ['close', 'volatility', 'range_pct', 'price_momentum', 'monthly_change'] 
       
       correlation_matrix = pd.DataFrame()
       for w_col in weather_cols:
           if w_col not in data.columns:
               continue
           for p_col in price_cols:
               if p_col not in data.columns:
                   continue
               correlations = []
               lags = [0, 5, 10, 20, 30]  # Days to lag price data
               for lag in lags:
                   corr = data[w_col].corr(data[p_col].shift(-lag))
                   correlations.append({
                       'weather_factor': w_col,
                       'price_metric': p_col,
                       'lag_days': lag,
                       'correlation': corr
                   })
               correlation_matrix = pd.concat([
                   correlation_matrix, 
                   pd.DataFrame(correlations)
               ])
   
   return correlation_matrix

def plot_correlation_heatmap(pivot_table, region):
   plt.figure()
   im = plt.imshow(pivot_table.values, cmap='RdYlBu', aspect='auto')
   plt.colorbar(im)
   
   plt.xticks(range(len(pivot_table.columns)), pivot_table.columns, rotation=45)
   plt.yticks(range(len(pivot_table.index)), pivot_table.index)
   
   # Add correlation values in each cell
   for i in range(len(pivot_table.index)):
       for j in range(len(pivot_table.columns)):
           text = plt.text(j, i, f'{pivot_table.values[i, j]:.2f}',
                         ha='center', va='center')
   
   plt.title(f'Weather Factors and Price Correlations for {region}')
   plt.tight_layout()



La obtención de datos sobre pares de divisas y su sincronización

Tras configurar la recogida de datos meteorológicos, deberemos implementar la obtención de información sobre el movimiento de los pares de divisas. Para ello, usaremos la plataforma MetaTrader 5, que ofrece una cómoda API para trabajar con los datos históricos de instrumentos financieros.

Vamos a analizar la función de obtención de datos sobre los pares de divisas:

def get_agricultural_forex_pairs():
    """
    Getting data on currency pairs via MetaTrader 5
    """
    if not mt5.initialize():
        print("MT5 initialization error")
        return None
    
    pairs = ["AUDUSD", "NZDUSD", "USDCAD"]
    timeframes = {
        "H1": mt5.TIMEFRAME_H1,
        "H4": mt5.TIMEFRAME_H4,
        "D1": mt5.TIMEFRAME_D1
    }
    # ... the rest of the function code

En esta función, trabajaremos con tres grandes pares de divisas que se corresponderán con nuestras regiones agrícolas: AUDUSD para el cinturón de trigo de Australia, NZDUSD para la región de Canterbury y USDCAD para las praderas canadienses. Para cada par, recopilaremos los datos en tres marcos temporales: horas (H1), cuatro horas (H4) y diario (D1).

Deberemos prestar especial atención al proceso de combinación de los datos meteorológicos y financieros. Para ello hemos implementado una función especial:

def merge_weather_forex_data(weather_data, forex_data):
    """
    Combining weather and financial data
    """
    synchronized_data = {}
    
    region_pair_mapping = {
        'AU_WheatBelt': 'AUDUSD',
        'NZ_Canterbury': 'NZDUSD',
        'CA_Prairies': 'USDCAD'
    }
    # ... the rest of the function code

Esta función resuelve el complejo problema de la sincronización de los datos de distintas fuentes. Los datos meteorológicos y las cotizaciones de divisas tienen intervalos de actualización distintos, por lo que utilizaremos un método especial merge_asof de la biblioteca pandas que nos permitirá comparar correctamente los valores considerando las etiquetas de tiempo.

Luego procesaremos de forma adicional los datos combinados para mejorar la calidad de los análisis:

def calculate_derived_features(data):
    """
    Calculation of derived indicators
    """
    if not data.empty:
        data['price_volatility'] = data['volatility'].rolling(24).std()
        data['temp_change'] = data['temperature'].diff()
        data['precip_intensity'] = data['precipitation'].rolling(24).sum()
        # ... the rest of the function code

Aquí calcularemos importantes indicadores derivados, como la volatilidad de los precios en las últimas 24 horas, los cambios de temperatura y la intensidad de las precipitaciones. También añadiremos una característica binaria que indicará la estación de crecimiento, especialmente importante para analizar los cultivos.

Prestaremos especial atención a limpiar los datos de valores atípicos y a rellenar los valores que faltan:

def clean_merged_data(data):
    """
    Cleaning up merged data
    """
    weather_cols = ['temperature', 'precipitation', 'wind_speed']
    
    # Fill in the blanks
    for col in weather_cols:
        if col in data.columns:
            data[col] = data[col].ffill(limit=3)
    
    # Removing outliers
    for col in weather_cols:
        if col in data.columns:
            q_low = data[col].quantile(0.01)
            q_high = data[col].quantile(0.99)
            data = data[
                (data[col] > q_low) & 
                (data[col] < q_high)
            ]
    # ... the rest of the function code

Esta función utilizará el método de rellenado directo (forward fill) para procesar los valores que faltan en los datos meteorológicos, pero con un límite de 3 periodos para evitar la presencia de valores incorrectos si se dan omisiones largas. También eliminaremos los valores extremos fuera de los percentiles 1 y 99, lo cual nos ayudará a evitar que los resultados del análisis se vean distorsionados por valores atípicos.

Aquí tenemos el resultado de la ejecución de las funciones del conjunto de datos:

Análisis de la correlación entre los factores meteorológicos y los tipos de cambio

Durante la observación hemos analizado diversos puntos de interrelación entre las condiciones meteorológicas y la dinámica de los precios de los pares de divisas. Para encontrar patrones que no resulten evidentes a primera vista, hemos creado una metodología especial para calcular las correlaciones considerando los desfases temporales:

def analyze_weather_price_correlations(merged_data):
    """
    Analysis of correlations with time lags between weather conditions and price movements
    """
    def calculate_lagged_correlations(data, weather_col, price_col, max_lag=72):
        print(f"Calculating lagged correlations: {weather_col} vs {price_col}")
        correlations = []
        for lag in range(max_lag):
            corr = data[weather_col].corr(data[price_col].shift(-lag))
            correlations.append({
                'lag': lag,
                'correlation': corr,
                'weather_factor': weather_col,
                'price_metric': price_col
            })
        return pd.DataFrame(correlations)

    correlations = {}
    weather_factors = ['temperature', 'precipitation', 'wind_speed', 'growing_degree_days']
    price_metrics = ['close', 'volatility', 'price_momentum', 'monthly_change']
    
    for region, data in merged_data.items():
        if data.empty:
            print(f"Skipping empty dataset for {region}")
            continue
            
        print(f"\nAnalyzing correlations for region: {region}")
        region_correlations = {}
        for w_col in weather_factors:
            for p_col in price_metrics:
                key = f"{w_col}_{p_col}"
                region_correlations[key] = calculate_lagged_correlations(data, w_col, p_col)
        correlations[region] = region_correlations
        
    return correlations

def analyze_seasonal_patterns(data):
    """
    Analysis of seasonal correlation patterns
    """
    print("Starting seasonal pattern analysis...")
    seasonal_correlations = {}
    data['month'] = data.index.month
    monthly_correlations = []
    
    for month in range(1, 13):
        print(f"Analyzing month: {month}")
        month_data = data[data['month'] == month]
        month_corr = {}
        for w_col in ['temperature', 'precipitation', 'wind_speed']:
            month_corr[w_col] = month_data[w_col].corr(month_data['close'])
        monthly_correlations.append(month_corr)
    
    return pd.DataFrame(monthly_correlations, index=range(1, 13))

El análisis de los datos encontrados ha revelado patrones interesantes. En el caso del cinturón de trigo australiano, la correlación más fuerte (0,21) se observa entre la velocidad del viento y las variaciones mensuales de AUDUSD. Esto puede atribuirse al hecho de que los fuertes vientos durante la madurez del trigo pueden reducir el rendimiento de la cosecha. El factor de temperatura también muestra una fuerte correlación (0,18), además, esta influencia particular se manifiesta casi sin desfase temporal.

La región neozelandesa de Canterbury muestra pautas más complejas. La correlación más fuerte (0,084) se manifiesta entre la temperatura y la volatilidad con un desfase de 10 días. Cabe señalar que la influencia de los factores meteorológicos en NZDUSD se refleja más en la volatilidad que en la dirección del movimiento de los precios, mientras que las correlaciones estacionales alcanzan a veces el 1,00, lo cual indica una correlación perfecta.


Creando el modelo de aprendizaje automático para la predicción

El núcleo de nuestra estrategia será el modelo de gradient bousting CatBoost, que ha demostrado su eficacia en series temporales. Vamos a desglosar paso a paso el proceso de creación del modelo.

Preparamos las características

El primer paso consistirá en generar las características para el modelo. Para ello, recopilaremos una selección de indicadores técnicos y meteorológicos:

def prepare_ml_features(data):
    """
    Preparation of features for the ML model
    """
    print("Starting feature preparation...")
    features = pd.DataFrame(index=data.index)

    # Weather features
    weather_cols = [
        'temperature', 'precipitation', 
        'wind_speed', 'growing_degree_days'
    ]
    for col in weather_cols:
        if col not in data.columns:
            print(f"Warning: {col} not found in data")
            continue

        print(f"Processing weather feature: {col}")
        # Base values
        features[col] = data[col]
        
        # Moving averages
        features[f"{col}_ma_24"] = data[col].rolling(24).mean()
        features[f"{col}_ma_72"] = data[col].rolling(72).mean()
        
        # Changes
        features[f"{col}_change"] = data[col].pct_change()
        features[f"{col}_change_24"] = data[col].pct_change(24)
        
        # Volatility
        features[f"{col}_volatility"] = data[col].rolling(24).std()

    # Price indicators
    price_cols = ['volatility', 'range_pct', 'monthly_change']
    for col in price_cols:
        if col not in data.columns:
            continue
        features[f"{col}_ma_24"] = data[col].rolling(24).mean()

    # Seasonal features
    features['month'] = data.index.month
    features['day_of_week'] = data.index.dayofweek
    features['growing_season'] = (
        (data.index.month >= 4) & 
        (data.index.month <= 9)
    ).astype(int)

    return features.dropna()

def create_prediction_targets(data, forecast_horizon=24):
    """
    Creation of target variables for prediction
    """
    print(f"Creating prediction targets with horizon: {forecast_horizon}")
    targets = pd.DataFrame(index=data.index)

    # Price change percentage
    targets['price_change'] = data['close'].pct_change(
        forecast_horizon
    ).shift(-forecast_horizon)

    # Price direction
    targets['direction'] = (targets['price_change'] > 0).astype(int)

    # Future volatility
    targets['volatility'] = data['volatility'].rolling(
        forecast_horizon
    ).mean().shift(-forecast_horizon)

    return targets.dropna()

Creamos y entrenamos los modelos

Para cada variable considerada, crearemos un modelo independiente con parámetros optimizados:

from catboost import CatBoostClassifier, CatBoostRegressor
from sklearn.metrics import accuracy_score, mean_squared_error
from sklearn.model_selection import TimeSeriesSplit

# Define categorical features
cat_features = ['month', 'day_of_week', 'growing_season']

# Create models for different tasks
models = {
    'direction': CatBoostClassifier(
        iterations=1000,
        learning_rate=0.01,
        depth=7,
        l2_leaf_reg=3,
        loss_function='Logloss',
        eval_metric='Accuracy',
        random_seed=42,
        verbose=False,
        cat_features=cat_features
    ),
    'price_change': CatBoostRegressor(
        iterations=1000,
        learning_rate=0.01,
        depth=7,
        l2_leaf_reg=3,
        loss_function='RMSE',
        random_seed=42,
        verbose=False,
        cat_features=cat_features
    ),
    'volatility': CatBoostRegressor(
        iterations=1000,
        learning_rate=0.01,
        depth=7,
        l2_leaf_reg=3,
        loss_function='RMSE',
        random_seed=42,
        verbose=False,
        cat_features=cat_features
    )
}

def train_ml_models(merged_data, region):
    """
    Training ML models using time series cross-validation
    """
    print(f"Starting model training for region: {region}")
    data = merged_data[region]
    features = prepare_ml_features(data)
    targets = create_prediction_targets(data)

    # Split into folds
    tscv = TimeSeriesSplit(n_splits=5)
    
    results = {}
    for target_name, model in models.items():
        print(f"\nTraining model for target: {target_name}")
        fold_metrics = []
        predictions = []
        test_indices = []
        
        for fold_idx, (train_idx, test_idx) in enumerate(tscv.split(features)):
            print(f"Processing fold {fold_idx + 1}/5")
            X_train = features.iloc[train_idx]
            y_train = targets[target_name].iloc[train_idx]
            X_test = features.iloc[test_idx]
            y_test = targets[target_name].iloc[test_idx]

            # Training with early stopping
            model.fit(
                X_train, y_train,
                eval_set=(X_test, y_test),
                early_stopping_rounds=50,
                verbose=False
            )

            # Predictions and evaluation
            pred = model.predict(X_test)
            predictions.extend(pred)
            test_indices.extend(test_idx)

            # Metric calculation
            metric = (
                accuracy_score(y_test, pred)
                if target_name == 'direction'
                else mean_squared_error(y_test, pred, squared=False)
            )
            fold_metrics.append(metric)
            print(f"Fold {fold_idx + 1} metric: {metric:.4f}")

        results[target_name] = {
            'model': model,
            'metrics': fold_metrics,
            'mean_metric': np.mean(fold_metrics),
            'predictions': pd.Series(
                predictions, 
                index=features.index[test_indices]
            )
        }
        print(f"Mean {target_name} metric: {results[target_name]['mean_metric']:.4f}")

    return results

Características de la implementación

Los siguientes parámetros serán fundamentales para nuestra aplicación:

  1. Trabajo con característica categóricas: CatBoost procesa de forma productiva variables categóricas como el mes y el día de la semana, por ejemplo, sin necesidad de codificación adicional.
  2. Parada anticipada: para evitar los intentos de reentrenamiento, se utiliza un mecanismo de parada anticipada con early_stopping_rounds=50.
  3. Equilibrio entre profundidad y generalización: los parámetros depth=7 y l2_leaf_reg=3 se seleccionan para maximizar el equilibrio entre la profundidad del árbol y la regularización.
  4. Trabajo con series temporales: el uso de TimeSeriesSplit garantiza que los datos de las series temporales se dividan correctamente, evitando posibles fugas de datos en el futuro.

Esta arquitectura del modelo nos ayudará a captar de forma productiva las dependencias a corto y largo plazo entre las condiciones meteorológicas y los movimientos de las divisas, como demuestran los resultados obtenidos en las pruebas.



Evaluación de la precisión del modelo y visualización de los resultados

Los modelos de aprendizaje automático resultantes se han probado con los datos de un periodo de 5 años utilizando un método de ventana deslizante con cinco pliegues. Hemos preparado tres tipos de modelos para cada área: la predicción de la dirección del movimiento de precios (clasificación), la predicción de la magnitud del cambio de precios (regresión) y la predicción de la volatilidad (regresión).

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, classification_report

def evaluate_model_performance(results, region_data):
    """
    Comprehensive model evaluation across all regions
    """
    print(f"\nEvaluating model performance for {len(results)} regions")
    evaluation = {}
    
    for region, models in results.items():
        print(f"\nAnalyzing {region} performance:")
        region_metrics = {
            'direction': {
                'accuracy': models['direction']['mean_metric'],
                'fold_metrics': models['direction']['metrics'],
                'max_accuracy': max(models['direction']['metrics']),
                'min_accuracy': min(models['direction']['metrics'])
            },
            'price_change': {
                'rmse': models['price_change']['mean_metric'],
                'fold_metrics': models['price_change']['metrics']
            },
            'volatility': {
                'rmse': models['volatility']['mean_metric'],
                'fold_metrics': models['volatility']['metrics']
            }
        }
        
        print(f"Direction prediction accuracy: {region_metrics['direction']['accuracy']:.2%}")
        print(f"Price change RMSE: {region_metrics['price_change']['rmse']:.4f}")
        print(f"Volatility RMSE: {region_metrics['volatility']['rmse']:.4f}")
        
        evaluation[region] = region_metrics
    
    return evaluation

def plot_feature_importance(models, region):
    """
    Visualize feature importance for each model type
    """
    plt.figure(figsize=(15, 10))
    
    for target, model_info in models.items():
        feature_importance = pd.DataFrame({
            'feature': model_info['model'].feature_names_,
            'importance': model_info['model'].feature_importances_
        })
        feature_importance = feature_importance.sort_values('importance', ascending=False)
        
        plt.subplot(3, 1, list(models.keys()).index(target) + 1)
        sns.barplot(x='importance', y='feature', data=feature_importance.head(10))
        plt.title(f'{target.capitalize()} Model - Top 10 Important Features')
    
    plt.tight_layout()
    plt.show()

def visualize_seasonal_patterns(results, region_data):
    """
    Create visualization of seasonal patterns in predictions
    """
    for region, data in region_data.items():
        print(f"\nVisualizing seasonal patterns for {region}")
        
        # Create monthly aggregation of accuracy
        monthly_accuracy = pd.DataFrame(index=range(1, 13))
        data['month'] = data.index.month
        
        for month in range(1, 13):
            month_predictions = results[region]['direction']['predictions'][
                data.index.month == month
            ]
            month_actual = (data['close'].pct_change() > 0)[
                data.index.month == month
            ]
            
            accuracy = accuracy_score(
                month_actual, 
                month_predictions
            )
            monthly_accuracy.loc[month, 'accuracy'] = accuracy
        
        # Plot seasonal accuracy
        plt.figure(figsize=(12, 6))
        monthly_accuracy['accuracy'].plot(kind='bar')
        plt.title(f'Seasonal Prediction Accuracy - {region}')
        plt.xlabel('Month')
        plt.ylabel('Accuracy')
        plt.show()

def plot_correlation_heatmap(correlation_data):
    """
    Create heatmap visualization of correlations
    """
    plt.figure(figsize=(12, 8))
    sns.heatmap(
        correlation_data, 
        cmap='RdYlBu', 
        center=0,
        annot=True, 
        fmt='.2f'
    )
    plt.title('Weather-Price Correlation Heatmap')
    plt.tight_layout()
    plt.show()



Resultados por región

AU_WheatBelt (Cinturón de trigo de Australia)

  • Precisión media en la predicción de la dirección de AUDUSD: 62.67%
  • Precisión máxima en pliegues individuales: 82.22%
  • RMSE de la predicción de la variación de precios: 0.0303
  • RMSE de la volatilidad: 0.0016

Región de Canterbury (Nueva Zelanda)

  • Precisión media de predicción de NZDUSD: 62.81%
  • Precisión máxima: 75.44%
  • Precisión mínima: 54.39%
  • RMSE de la predicción de la variación de precios: 0.0281
  • RMSE de la volatilidad: 0.0015

Región de las praderas canadienses

  • Precisión media de predicción de la dirección: 56.92%
  • Precisión máxima (tercer pliegue): 71.79%
  • RMSE de la predicción de la variación de precios: 0.0159
  • RMSE de la volatilidad: 0.0023



Análisis y visualización de la estacionalidad

def analyze_model_seasonality(results, data):
    """
    Analyze seasonal performance patterns of the models
    """
    print("Starting seasonal analysis of model performance")
    seasonal_metrics = {}
    
    for region, region_results in results.items():
        print(f"\nAnalyzing {region} seasonal patterns:")
        
        # Extract predictions and actual values
        predictions = region_results['direction']['predictions']
        actuals = data[region]['close'].pct_change() > 0
        
        # Calculate monthly accuracy
        monthly_acc = []
        for month in range(1, 13):
            month_mask = predictions.index.month == month
            if month_mask.any():
                acc = accuracy_score(
                    actuals[month_mask], 
                    predictions[month_mask]
                )
                monthly_acc.append(acc)
                print(f"Month {month} accuracy: {acc:.2%}")
            
        seasonal_metrics[region] = pd.Series(
            monthly_acc, 
            index=range(1, 13)
        )
    
    return seasonal_metrics

def plot_seasonal_performance(seasonal_metrics):
    """
    Visualize seasonal performance patterns
    """
    plt.figure(figsize=(15, 8))
    
    for region, metrics in seasonal_metrics.items():
        plt.plot(metrics.index, metrics.values, label=region, marker='o')
    
    plt.title('Model Accuracy by Month')
    plt.xlabel('Month')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.grid(True)
    plt.show()

Los resultados de la visualización demuestran una estacionalidad significativa en el rendimiento del modelo.

Resultan especialmente notables los picos en la precisión de las predicciones:

  • Para el AUDUSD: diciembre-febrero (periodo de maduración del trigo)
  • NZDUSD: periodos de máxima producción de leche
  • Para USDCAD: estaciones de crecimiento activas en las praderas

Estos resultados apoyan la hipótesis de que existe un impacto significativo de las condiciones meteorológicas en los tipos de cambio de las divisas agrícolas, sobre todo durante los periodos críticos de la producción agrícola.


Conclusión

El estudio ha hallado relaciones significativas entre las condiciones meteorológicas en las regiones agrícolas y la dinámica de los pares de divisas. El sistema de previsión ha demostrado una gran precisión durante los periodos de clima extremo y máxima producción agrícola, mostrando una precisión media de hasta el 62,67% para AUDUSD, el 62,81% para NZDUSD y el 56,92% para USDCAD.

Recomendaciones:

  • AUDUSD: negociación de diciembre a febrero, centrada en el viento y la temperatura.
  • NZDUSD: negociación a medio plazo durante la producción lechera activa.
  • USDCAD: negociación en las épocas de siembra y cosecha.

El sistema requiere actualizaciones periódicas de los datos para mantener su exactitud, sobre todo ante las perturbaciones del mercado. Nuestras perspectivas incluyen la ampliación de las fuentes de datos y la aplicación del aprendizaje profundo para mejorar la solidez de las predicciones.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/16060

Archivos adjuntos |
Maxim Kuznetsov
Maxim Kuznetsov | 5 nov 2024 en 14:00

para muchas personas será una revelación que CAD no es tanto el petróleo, pero las mezclas de cereales para piensos :-))

Lo que se negocia principalmente en las bolsas nacionales para la moneda nacional, afecta...

para USDCAD e incluso sólo las temporadas agrícolas debe ser rastreable.

Entrenamos un perceptrón multicapa usando el algoritmo de Levenberg-Marquardt Entrenamos un perceptrón multicapa usando el algoritmo de Levenberg-Marquardt
Este artículo le presentaremos una implementación del algoritmo Levenberg-Marquardt para el entrenamiento de redes neuronales de propagación directa. Asimismo, realizaremos un análisis comparativo del rendimiento usando algoritmos de la biblioteca scikit-learn Python. También discutiremos preliminarmente los métodos de aprendizaje más sencillos como el descenso de gradiente, el descenso de gradiente con impulso y el descenso de gradiente estocástico.
Cómo crear un diario de operaciones con MetaTrader y Google Sheets Cómo crear un diario de operaciones con MetaTrader y Google Sheets
Crear un diario de operaciones con MetaTrader y Google Sheets! Aprenderá cómo sincronizar sus datos comerciales a través de HTTP POST y recuperarlos mediante solicitudes HTTP. Al final, tendrás un diario de operaciones que te ayudará a realizar un seguimiento de tus operaciones de manera eficaz y eficiente.
De novato a experto: depuración colaborativa en MQL5 De novato a experto: depuración colaborativa en MQL5
La resolución de problemas puede establecer una rutina concisa para dominar habilidades complejas, como la programación en MQL5. Este enfoque le permite concentrarse en la resolución de problemas al tiempo que desarrolla sus capacidades. Cuantos más problemas abordes, más conocimientos avanzados se transferirán a tu cerebro. Personalmente, creo que la depuración es la forma más efectiva de dominar la programación. Hoy repasaremos el proceso de limpieza de código y analizaremos las mejores técnicas para transformar un programa desordenado en uno limpio y funcional. Lea este artículo y descubra información valiosa.
Redes neuronales en el trading: Modelos de difusión direccional (DDM) Redes neuronales en el trading: Modelos de difusión direccional (DDM)
Hoy proponemos al lector familiarizarse con los modelos de difusión direccional que explotan el ruido anisotrópico y direccional dependiente de los datos durante la difusión directa para capturar representaciones gráficas significativas.