English Русский 中文 Español Deutsch 日本語
preview
Otimização de Portfólio em Python e MQL5

Otimização de Portfólio em Python e MQL5

MetaTrader 5Estatística e análise |
193 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Introdução

Apresentando dois programas inovadores de otimização de portfólio projetados para revolucionar as estratégias de negociação e maximizar os retornos, enquanto minimizam o risco. O primeiro, uma solução baseada em Python, aproveita o poder da integração com o MetaTrader 5, juntamente com bibliotecas avançadas como pandas, Numpy e cvxpy, para analisar dados históricos, otimizar a alocação de ativos e visualizar os resultados com Matplotlib. O segundo, uma implementação similar criada em MQL5, aproveita as capacidades nativas da plataforma MetaTrader 5, oferecendo aos traders uma experiência integrada diretamente em seu ambiente de negociação preferido. Ambos os programas exemplificam a interseção de ponta entre finanças quantitativas e tecnologia, capacitando os traders com ferramentas sofisticadas para tomar decisões baseadas em dados em um cenário de mercado em constante evolução.


Por que precisamos da Otimização de Portfólio?

Programas de otimização de portfólio são ferramentas essenciais na gestão financeira moderna, atendendo à necessidade crítica de retornos ajustados ao risco de maneira eficiente, em um cenário de investimentos cada vez mais complexo e volátil. Ao utilizar modelos matemáticos avançados e poder computacional, esses programas permitem que investidores e profissionais financeiros tomem decisões baseadas em dados, adaptadas às suas tolerâncias de risco e objetivos de investimento específicos. Esses programas analisam sistematicamente grandes volumes de dados históricos, tendências de mercado e correlações entre ativos para determinar alocações ótimas de ativos que maximizem os retornos potenciais, enquanto minimizam o risco geral do portfólio.

Essa abordagem científica para a construção de portfólios ajuda a mitigar os vieses humanos e as decisões emocionais frequentemente associadas às estratégias tradicionais de investimento. Além disso, programas de otimização de portfólio facilitam o reequilíbrio dinâmico, permitindo que os investidores se adaptem rapidamente às mudanças nas condições de mercado e mantenham a conformidade com seus objetivos financeiros de longo prazo. Em uma era de interconectividade econômica global e fluxo rápido de informações, essas ferramentas sofisticadas oferecem uma vantagem competitiva, permitindo que os investidores naveguem por incertezas e capitalizem oportunidades em diversas classes de ativos, promovendo, por fim, estratégias de investimento mais robustas e resilientes.


Por que devemos usar Python?

Python é uma boa maneira de testar rapidamente estratégias ou ideias; tem uma grande comunidade e é rápido. Além disso, conta com a biblioteca MetaTrader5, para baixar dados ou até realizar operações. Portanto, vamos usar primeiro o Python para ver se a ideia é consistente, e devemos usar diferentes % da conta com diferentes símbolos.

Este é o script em Python que vamos usar:

# Import necessary libraries
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import cvxpy as cp
import matplotlib.pyplot as plt
from datetime import datetime

# Function to obtain historical data from MT5
def get_mt5_data(symbols, from_date, to_date):
    # Establish connection with MetaTrader 5
    if not mt5.initialize():
        print("Error: Could not connect to MetaTrader 5")
        mt5.shutdown()
        return None
    
    data = {}
    
    for symbol in symbols:
        # Get historical price data
        rates = mt5.copy_rates_range(symbol, mt5.TIMEFRAME_D1, from_date, to_date)
        
        if rates is not None:
            # Convert to Pandas DataFrame
            df = pd.DataFrame(rates)
            df['time'] = pd.to_datetime(df['time'], unit='s')
            df.set_index('time', inplace=True)
            df.drop(['tick_volume', 'spread', 'real_volume'], axis=1, inplace=True)
            
            # Calculate daily returns
            df['return'] = df['close'].pct_change().fillna(0)
            
            # Save in the data dictionary
            data[symbol] = df
    
    # Close the connection with MetaTrader 5
    mt5.shutdown()
    
    return data

# Function to optimize the portfolio
def optimize_portfolio(data):
    symbols = list(data.keys())
    n_assets = len(symbols)
    
    # Find the minimum data length among all assets
    min_length = min(len(data[symbol]) for symbol in symbols)
    
    # Adjust and normalize returns
    returns = np.zeros((min_length, n_assets))
    for i, symbol in enumerate(symbols):
        # Adjust data length
        df = data[symbol].iloc[:min_length]
        returns[:, i] = df['return'].values
    
    # Calculate covariance matrix and expected returns
    cov_matrix = np.cov(returns, rowvar=False)
    expected_returns = np.mean(returns, axis=0)
    
    # Optimization variables
    weights = cp.Variable(n_assets)
    risk = cp.quad_form(weights, cov_matrix)
    objective = cp.Maximize(expected_returns @ weights - 0.5 * risk)
    
    # Constraints
    constraints = [cp.sum(weights) == 1, weights >= 0]
    
    # Solve the optimization problem
    prob = cp.Problem(objective, constraints)
    prob.solve()
    
    # Display optimization results
    print("\nOptimization Results:")
    for i, symbol in enumerate(symbols):
        print(f"{symbol}: {weights.value[i]}")
    
    # Calculate minimum variance and expected return for the portfolio
    min_variance = cp.sqrt(cp.quad_form(weights.value, cov_matrix)).value
    expected_return_portfolio = expected_returns @ weights.value
    
    print(f"\nExpected portfolio return: {expected_return_portfolio:.4f}")
    print(f"Minimum portfolio variance: {min_variance:.4f}")
    
    return symbols, weights.value

# Function to visualize results
def visualize_results(symbols, weights):
    # Plot weights of each asset in the portfolio
    plt.figure(figsize=(10, 6))
    plt.bar(symbols, weights, color='blue')
    plt.xlabel('Assets')
    plt.ylabel('Weights')
    plt.title('Asset Weights in Optimized Portfolio')
    plt.show()

# Execute the main script
if __name__ == "__main__":
    # Define parameters
    symbols = ["EURUSD", "GBPUSD", "#AMZN", "#AAPL"]  # Asset symbols
    from_date = datetime(2023, 1, 1)  # Start date
    to_date = datetime(2023, 12, 31)  # End date
    
    # Get historical data from MT5
    print(f"Obtaining historical data from {from_date} to {to_date}...")
    data = get_mt5_data(symbols, from_date, to_date)
    
    if data:
        # Optimize the portfolio
        symbols, weights = optimize_portfolio(data)
        
        # Visualize the results
        visualize_results(symbols, weights)

Os resultados ficam assim:

Obtaining historical data from 2023-01-01 00:00:00 to 2023-12-31 00:00:00...

Optimization Results:
EURUSD: 1.9303305369616842e-23
GBPUSD: 1.9417113191106993e-23
#AMZN: 1.0
#AAPL: -1.3370355361690525e-23

Expected portfolio return: 0.0025
Minimum portfolio variance: 0.0205

E este é o gráfico:

Gráfico 1

Esses resultados nos dizem para investir apenas na Amazon, mas vamos adicionar uma estratégia ao script, para ver se os valores mudam, e os resultados nos pedem para investir em outros símbolos.

Podemos fazer isso adicionando o seguinte ao script (vamos usar uma estratégia simples de cruzamento de duas médias móveis), você pode modificar essa estratégia para usar a que precisar:

# Function to apply the moving average crossover strategy
def apply_sma_strategy(data, short_window=12, long_window=26):
    for symbol, df in data.items():
        df['SMA_50'] = df['close'].rolling(window=short_window).mean()
        df['SMA_200'] = df['close'].rolling(window=long_window).mean()
        df['signal'] = 0
        df.loc[df.index[short_window:], 'signal'] = np.where(
            df.loc[df.index[short_window:], 'SMA_50'] > df.loc[df.index[short_window:], 'SMA_200'], 1, 0
        )
        df['position'] = df['signal'].shift(1).fillna(0)
    return data

# Function to adjust returns according to the strategy
def adjust_returns(data):
    for symbol, df in data.items():
        df['adjusted_return'] = df['return'] * df['position']
    return data

E também adicionando isso no principal:

        # Apply the moving average crossover strategy
        data = apply_sma_strategy(data)
        
        # Adjust returns according to the strategy
        data = adjust_returns(data)

Os resultados são apresentados assim:

Obtaining historical data from 2023-01-01 00:00:00 to 2023-12-31 00:00:00...

Optimization Results:
EURUSD: -5.669275045708089e-25
GBPUSD: 5.494697501444607e-23
#AMZN: 1.0
#AAPL: -5.59465620602481e-23

Expected portfolio return: 0.0006
Minimum portfolio variance: 0.0151

Figura 2.

Houve algumas pequenas mudanças, mas, no geral, os resultados permanecem os mesmos.

Isso ocorre porque a AMZN teve uma tendência gigante durante todo esse período.

AMZN

Você deve estar ciente disso e observar quando a tendência parar, mas pode entender por que a gestão de risco é tão importante.


Script MQL5

Acabamos de ver como desenvolver a gestão de risco em Python, agora vamos reproduzir o mesmo script em MQL5, pois o MQL5 é mais preciso.

Aqui está o script:

//+------------------------------------------------------------------+
//|                                        optimizacion_carteras.mq5 |
//|       Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
// Define the assets to consider
string symbols[] = {"EURUSD", "GBPUSD", "#AAPL", "#AMZN"};

// Date parameters to obtain historical data
datetime from_date = D'2023.01.01 00:00';
datetime to_date = D'2024.01.01 00:00';

//+------------------------------------------------------------------+
//| Function to obtain historical data from MetaTrader 5             |
//+------------------------------------------------------------------+
void obtenerDatosHistoricos(string symbol, datetime from, datetime to, double &out[][6])
  {
   // Declare an array to store the historical rates
   MqlRates rates[];
   
   // Copy historical data for the specified symbol and date range
   int copied = CopyRates(symbol, PERIOD_D1, from, to, rates);

   // Check if data copying was successful
   if(copied <= 0)
      Print("Failed to copy price data ", GetLastError());
   else
      Print("Copied ", ArraySize(rates), " bars");

   // Resize the output array to match the size of copied data
   ArrayResize(out, copied);
   Print("Copied ", copied, " data points for ", symbol);

   // Transfer data to the output array
   for(int i = 0; i < copied; i++)
     {
      out[i][0] = (double)rates[i].time;
      out[i][1] = rates[i].open;
      out[i][2] = rates[i].high;
      out[i][3] = rates[i].low;
      out[i][4] = rates[i].close;
      out[i][5] = (double)rates[i].tick_volume;
     }
  }
//+------------------------------------------------------------------+
//| Function to calculate daily returns                              |
//+------------------------------------------------------------------+
void calcularRendimientos(double &data[][6], double &returns[])
  {
   // Determine the number of data points
   int total = ArrayRange(data, 0);
   
   // Resize the returns array to accommodate the calculated returns
   ArrayResize(returns, total - 1);
   Print("Calculating returns for ", total, " data points");

   // Initialize variables to track maximum and minimum returns
   double max_return = -DBL_MAX;
   double min_return = DBL_MAX;
   int problematic_index = -1;
   int valid_returns_count = 0;

   // Iterate through the data points to calculate returns
   for(int i = 1; i < total; i++)
     {
      // Ensure the previous closing price is not zero to avoid division by zero
      if(data[i - 1][4] != 0.0)
        {
         // Calculate the return as the percentage change in closing prices
         double retorno = (data[i][4] - data[i - 1][4]) / data[i - 1][4];
         returns[i - 1] = retorno;
         valid_returns_count++;

         // Update maximum and minimum returns if applicable
         if(retorno > max_return)
            max_return = retorno;
         if(retorno < min_return)
            min_return = retorno;

         // Identify and log suspicious returns
         if(MathAbs(retorno) > 1.0)
           {
            Print("Suspicious return at index ", i, ": ", retorno);
            Print("Data[", i - 1, "][4] = ", data[i - 1][4], ", Data[", i, "][4] = ", data[i][4]);
            problematic_index = i;
           }

         // Periodically print return values for verification
         if(i % 50 == 0 || i == total - 1)
           {
            Print("Return for index ", i - 1, ": ", retorno);
           }
        }
      else
        {
         // If the previous closing price is zero, set the return to zero
         returns[i - 1] = 0.0;
         Print("Zero price found at index ", i - 1);
        }
     }

   // Print the maximum and minimum returns
   Print("Max return: ", max_return, ", Min return: ", min_return);
   
   // Log the index of any problematic returns
   if(problematic_index != -1)
     {
      Print("Problematic return found at index: ", problematic_index);
     }
  }
//+------------------------------------------------------------------+
//| Main function                                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   // Declare arrays to store historical data and returns
   double data[][6];
   double returns[];

   // Loop through each symbol to obtain historical data and calculate returns
   for(int i = 0; i < ArraySize(symbols); i++)
     {
      obtenerDatosHistoricos(symbols[i], from_date, to_date, data);

      // Determine the size of the data array
      int data_size = ArraySize(data);
      Print("Data size for ", symbols[i], ": ", data_size);

      // Ensure there is enough data to calculate returns
      if(data_size > 1 && ArrayRange(data, 1) == 6)
        {
         calcularRendimientos(data, returns);
         int returns_size = ArraySize(returns);
         Print("Returns size for ", symbols[i], ": ", returns_size);

         // Initialize variables to calculate the expected return and variance
         double sum_returns = 0;
         int valid_returns = 0;

         // Sum the valid returns and count them
         for(int j = 0; j < returns_size; j++)
           {
            if(MathIsValidNumber(returns[j]) && MathAbs(returns[j]) <= 1.0)
              {
               sum_returns += returns[j];
               valid_returns++;
              }
            else
              {
               Print("Invalid or extreme return at index ", j, ": ", returns[j]);
              }
           }

         // Calculate the mean return
         double mean_return = (valid_returns > 0) ? sum_returns / valid_returns : 0;

         // Calculate the variance of the returns
         double variance = 0;
         for(int j = 0; j < valid_returns; j++)
           {
            if(MathIsValidNumber(returns[j]) && MathAbs(returns[j]) <= 1.0)
              {
               variance += MathPow(returns[j] - mean_return, 2);
              }
           }
         variance = (valid_returns > 0) ? variance / valid_returns : 0;

         // Display the results in the console
         Print("Results for ", symbols[i]);
         Print("Expected return: ", mean_return);
         Print("Variance: ", variance);
         Print("Sum of returns: ", sum_returns);
         Print("Valid returns: ", valid_returns, " out of ", returns_size);
         Print("-----------------------");
        }
      else
        {
         // Log if there were insufficient data or an incorrect data format
         Print("Could not obtain enough data for ", symbols[i], " or the data format is incorrect");
         Print("-----------------------");
        }
     }
  }

Primeiramente, o script define uma lista de ativos a serem considerados, representados pelos seus símbolos. Também define o intervalo de datas para obter os dados históricos, especificando uma data de início e uma data de término.

A função obtenerDatosHistoricos é responsável por buscar os dados históricos de um determinado ativo dentro do intervalo de datas especificado. Ela utiliza a função CopyRates para recuperar os dados e armazená-los em um array de estruturas MqlRates. A função então copia esses dados para um array de saída, garantindo o formato e tamanho corretos. Se a recuperação de dados falhar, uma mensagem de erro é impressa, enquanto uma recuperação bem-sucedida resulta em uma mensagem de confirmação indicando o número de pontos de dados copiados.

A função calcularRendimientos calcula os retornos diários a partir dos dados históricos. Ela percorre os pontos de dados, calculando o retorno como a mudança percentual nos preços de fechamento entre os dias consecutivos. A função lida com erros potenciais, como preços de fechamento zero, e registra retornos suspeitos que excedem um limite pré-definido. Ela rastreia os retornos máximos e mínimos encontrados durante os cálculos e imprime atualizações periódicas para verificar os retornos calculados.

A função principal OnStart inicializa arrays para armazenar dados históricos e retornos. Ela percorre cada símbolo de ativo, chamando obtenerDatosHistoricos para buscar os dados e, em seguida, calcularRendimientos para calcular os retornos. Após calcular os retornos, a função prossegue para calcular o retorno esperado e a variância. Ela soma os retornos válidos, calcula o retorno médio e, em seguida, calcula a variância dos retornos. Os resultados, incluindo o retorno esperado, a variância, a soma dos retornos e a contagem dos retornos válidos, são impressos no console para cada ativo. Se os dados forem insuficientes ou o formato dos dados for incorreto, uma mensagem apropriada é registrada.

Ao longo do script, um extenso registro de log é implementado para garantir transparência e facilitar a depuração. Mensagens indicam o progresso e os resultados da recuperação de dados, cálculo de retornos e análise estatística, permitindo que o usuário acompanhe o fluxo de execução e identifique quaisquer problemas que surgirem.

Resultados

Para rodar este script, basta carregá-lo em uma janela, e você verá os seguintes resultados:

2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 259 bars
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 259 data points for EURUSD
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Data size for EURUSD: 1554
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Calculating returns for 259 data points
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 49: 0.008422556659553942
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 99: 0.0005552522233225886
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 149: -0.0016251305097825213
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 199: -0.0018138190337636214
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 249: 0.002726296367691935
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 257: -0.0023503674709141444
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Max return: 0.016843640170492922, Min return: -0.014629419109562279
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Returns size for EURUSD: 258
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Results for EURUSD
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Expected return: 0.00014629557982735741
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Variance: 0.000021906221916670055
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Sum of returns: 0.03774425959545821
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Valid returns: 258 out of 258
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     -----------------------
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 259 bars
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 259 data points for GBPUSD
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Data size for GBPUSD: 1554
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Calculating returns for 259 data points
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 49: 0.01253428642673093
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 99: -0.00020901161622245828
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 149: -0.0009419054513750523
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 199: 0.00011442115156718484
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 249: -0.0024846582214581455
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 257: 0.000015710672259594492
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Max return: 0.01795095252445456, Min return: -0.016589470883191758
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Returns size for GBPUSD: 258
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Results for GBPUSD
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Expected return: 0.0002283507472210021
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Variance: 0.000026680765574142948
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Sum of returns: 0.058914492783018545
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Valid returns: 258 out of 258
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     -----------------------
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 250 bars
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 250 data points for #AAPL
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Data size for #AAPL: 1500
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Calculating returns for 250 data points
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 49: 0.026341719766143464
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 99: 0.010473614547965662
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 149: -0.006613315549627641
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 199: -0.0011390170283046702
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 248: -0.006298074441174946
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Max return: 0.047845736667670974, Min return: -0.04621826746924895
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Returns size for #AAPL: 249
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Results for #AAPL
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Expected return: 0.0018199882676706617
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Variance: 0.00016500191971009266
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Sum of returns: 0.4531770786499948
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Valid returns: 249 out of 249
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     -----------------------
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 250 bars
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Copied 250 data points for #AMZN
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Data size for #AMZN: 1500
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Calculating returns for 250 data points
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 49: 0.04365079365079357
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 99: 0.04105902777777781
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 149: -0.00952790314492451
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 199: -0.0033604251328539594
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Return for index 248: -0.009568443663346995
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Max return: 0.08595143898844165, Min return: -0.07525053686471019
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Returns size for #AMZN: 249
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Results for #AMZN
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Expected return: 0.002502188742255484
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Variance: 0.0004212375364322232
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Sum of returns: 0.6230449968216155
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     Valid returns: 249 out of 249
2024.07.11 21:46:42.458 optimizacion_carteras_v2 english (#AMZN,W1)     -----------------------

Como pode ser visto nos resultados, a AAPL deve ter cerca de 40% de investimento, a AMZN 60%, EURUSD 3% e GBPUSD 6%. Esses valores são orientativos, e nenhuma estratégia foi utilizada. 


Adicionando uma Estratégia ao Script MQL5

Você deve adicionar isto ao primeiro script:

Função de Cálculo da Média Móvel

Esta função calcula a média móvel para um conjunto de dados dado, durante um período especificado. Ela percorre os pontos de dados, somando os preços de fechamento ao longo do período definido, e então divide pelo período para obter a média. Se não houver dados suficientes para calcular a média móvel, a função define o valor como zero.

//+------------------------------------------------------------------+
//| Function to calculate moving average                             |
//+------------------------------------------------------------------+
void calcularMediaMovil(double &data[][6], int period, double &ma[])
  {
   int total = ArrayRange(data, 0);
   ArrayResize(ma, total);

   for(int i = 0; i < total; i++)
     {
      if(i >= period - 1)
        {
         double sum = 0;
         for(int j = i; j > i - period; j--)
           {
            sum += data[j][4]; // Closing price
           }
         ma[i] = sum / period;
        }
      else
        {
         ma[i] = 0.0; // Not enough data for moving average
        }
     }
  }
//+------------------------------------------------------------------+
//| Function to generate trading signals based on moving average cross |
//+------------------------------------------------------------------+
void generarSenales(double &data[][6], double &ma_rapida[], double &ma_lenta[], double &senales[])
  {
   int total = ArrayRange(data, 0);
   ArrayResize(senales, total);

   for(int i = 1; i < total; i++)
     {
      if(ma_rapida[i - 1] <= ma_lenta[i - 1] && ma_rapida[i] > ma_lenta[i])
        {
         senales[i] = 1; // Buy signal
        }
      else if(ma_rapida[i - 1] >= ma_lenta[i - 1] && ma_rapida[i] < ma_lenta[i])
        {
         senales[i] = -1; // Sell signal
        }
      else
        {
         senales[i] = 0; // No signal
        }
     }
  }

E integrar isso ao OnStart:

void OnStart()
  {
   double data[][6];
   double returns[];

   for(int i = 0; i < ArraySize(symbols); i++)
     {
      obtenerDatosHistoricos(symbols[i], from_date, to_date, data);
      int data_size = ArraySize(data);

      if(data_size > 1 && ArrayRange(data, 1) == 6)
        {
         calcularRendimientos(data, returns);
         int returns_size = ArraySize(returns);

         double sum_returns = 0;
         int valid_returns = 0;

         for(int j = 0; j < returns_size; j++)
           {
            if(MathIsValidNumber(returns[j]) && MathAbs(returns[j]) <= 1.0)
              {
               sum_returns += returns[j];
               valid_returns++;
              }
           }

         double mean_return = (valid_returns > 0) ? sum_returns / valid_returns : 0;
         double variance = 0;
         for(int j = 0; j < valid_returns; j++)
           {
            if(MathIsValidNumber(returns[j]) && MathAbs(returns[j]) <= 1.0)
              {
               variance += MathPow(returns[j] - mean_return, 2);
              }
           }
         variance = (valid_returns > 0) ? variance / valid_returns : 0;

         Print("Results for ", symbols[i]);
         Print("Expected return: ", mean_return);
         Print("Variance: ", variance);
         Print("Sum of returns: ", sum_returns);
         Print("Valid returns: ", valid_returns, " out of ", returns_size);
         Print("-----------------------");

         // Calculate moving averages and trading signals
         double ma_rapida[];
         double ma_lenta[];
         double senales[];

         int periodo_rapido = 10; // Short period moving average
         int periodo_lento = 50;  // Long period moving average

         calcularMediaMovil(data, periodo_rapido, ma_rapida);
         calcularMediaMovil(data, periodo_lento, ma_lenta);
         generarSenales(data, ma_rapida, ma_lenta, senales);

         // Log trading signals
         for(int k = 0; k < ArraySize(senales); k++)
           {
            if(senales[k] != 0)
              {
               string tipo_senal = (senales[k] == 1) ? "Compra" : "Venta";
               Print("Signal for ", symbols[i], " on ", TimeToString((datetime)data[k][0]), ": ", tipo_senal);
              }
           }
        }
      else
        {
         Print("Could not obtain enough data for ", symbols[i], " or the data format is incorrect");
         Print("-----------------------");
        }
     }
  }

Esta função gera sinais de negociação com base no cruzamento de duas médias móveis (um período curto e um longo). Ela percorre os dados, verificando instâncias onde a média móvel de curto período cruza acima ou abaixo da média móvel de longo período. Um cruzamento para cima gera um sinal de compra, enquanto um cruzamento para baixo gera um sinal de venda. Se não houver cruzamento, nenhum sinal é gerado.


Integração na Função Principal OnStart

Na função principal, os dados históricos são obtidos para cada símbolo e os retornos são calculados. Em seguida, as médias móveis e os sinais de negociação são calculados para cada símbolo. As médias móveis são obtidas utilizando a função calcularMediaMovil para ambos os períodos, curto e longo. A função generarSenales é usada para gerar sinais de compra e venda com base nos cruzamentos das médias móveis. Os resultados, incluindo os sinais calculados, são impressos no console para revisão.

Este código agora inclui uma estratégia simples de cruzamento de média móvel que gera sinais de compra e venda. Os sinais de negociação são impressos no console para revisão, permitindo ajustes nos períodos das médias móveis conforme necessário.

Os resultados ficam assim:

2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 259 bars
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 259 data points for EURUSD
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Calculating returns for 259 data points
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 49: 0.008422556659553942
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 99: 0.0005552522233225886
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 149: -0.0016251305097825213
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 199: -0.0018138190337636214
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 249: 0.002726296367691935
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 257: -0.0023503674709141444
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Max return: 0.016843640170492922, Min return: -0.014629419109562279
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Results for EURUSD
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Expected return: 0.00014629557982735741
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Variance: 0.000021906221916670055
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Sum of returns: 0.03774425959545821
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Valid returns: 258 out of 258
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     -----------------------
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.01.13 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.03.10 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.03.27 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.05.19 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.06.22 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.08.14 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for EURUSD on 2023.11.08 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 259 bars
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 259 data points for GBPUSD
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Calculating returns for 259 data points
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 49: 0.01253428642673093
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 99: -0.00020901161622245828
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 149: -0.0009419054513750523
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 199: 0.00011442115156718484
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 249: -0.0024846582214581455
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 257: 0.000015710672259594492
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Max return: 0.01795095252445456, Min return: -0.016589470883191758
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Results for GBPUSD
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Expected return: 0.0002283507472210021
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Variance: 0.000026680765574142948
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Sum of returns: 0.058914492783018545
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Valid returns: 258 out of 258
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     -----------------------
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.01.13 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.03.10 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.03.23 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.05.26 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.06.12 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.08.10 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for GBPUSD on 2023.11.14 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 250 bars
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 250 data points for #AAPL
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Calculating returns for 250 data points
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 49: 0.026341719766143464
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 99: 0.010473614547965662
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 149: -0.006613315549627641
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 199: -0.0011390170283046702
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 248: -0.006298074441174946
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Max return: 0.047845736667670974, Min return: -0.04621826746924895
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Results for #AAPL
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Expected return: 0.0018199882676706617
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Variance: 0.00016500191971009266
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Sum of returns: 0.4531770786499948
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Valid returns: 249 out of 249
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     -----------------------
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AAPL on 2023.01.17 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AAPL on 2023.08.10 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AAPL on 2023.10.18 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AAPL on 2023.10.20 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AAPL on 2023.11.10 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 250 bars
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Copied 250 data points for #AMZN
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Calculating returns for 250 data points
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 49: 0.04365079365079357
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 99: 0.04105902777777781
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 149: -0.00952790314492451
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 199: -0.0033604251328539594
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Return for index 248: -0.009568443663346995
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Max return: 0.08595143898844165, Min return: -0.07525053686471019
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Results for #AMZN
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Expected return: 0.002502188742255484
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Variance: 0.0004212375364322232
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Sum of returns: 0.6230449968216155
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Valid returns: 249 out of 249
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     -----------------------
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AMZN on 2023.01.17 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AMZN on 2023.03.15 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AMZN on 2023.03.24 00:00: Compra
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AMZN on 2023.09.27 00:00: Venta
2024.07.11 22:02:03.328 optimizacion_carteras_v3 english (#AMZN,W1)     Signal for #AMZN on 2023.11.07 00:00: Compra

O artigo apresenta uma exploração abrangente das técnicas de otimização de portfólio utilizando as linguagens de programação Python e MQL5 com a plataforma MetaTrader 5, enfatizando o papel crítico da tomada de decisões orientada por dados na gestão financeira moderna. Ele esclarece o processo de desenvolvimento e implementação de algoritmos sofisticados que analisam dados históricos, otimizam a alocação de ativos e geram sinais de negociação com base em cruzamentos de médias móveis.

Os autores destacam a importância da otimização de portfólio como uma ferramenta essencial para alcançar retornos ajustados ao risco de maneira eficiente em um cenário de investimentos cada vez mais complexo e volátil. Ao aproveitar modelos matemáticos avançados e o poder computacional, esses programas permitem que os investidores tomem decisões informadas, adaptadas às suas tolerâncias de risco e objetivos de investimento específicos. O artigo demonstra como tais técnicas de otimização podem analisar sistematicamente grandes volumes de dados históricos, tendências de mercado e correlações entre ativos para determinar alocações ótimas de ativos que maximizem os retornos potenciais, enquanto minimizam o risco geral do portfólio.

A abordagem dual de usar Python para testes iniciais de estratégias e MQL5 para integração sem costura com o MetaTrader 5 mostra a versatilidade e o poder de combinar diferentes ambientes de programação. Essa metodologia permite que os traders se beneficiem das bibliotecas extensivas e das capacidades analíticas do Python, enquanto aproveitam as funcionalidades nativas da plataforma MetaTrader 5.

A necessidade de empregar a otimização de portfólio na negociação não pode ser exagerada, pois ela oferece uma abordagem científica para a construção do portfólio, ajudando a mitigar os vieses humanos e a tomada de decisões emocionais frequentemente associadas às estratégias tradicionais de investimento. Em uma era de interconectividade econômica global e fluxo rápido de informações, essas ferramentas sofisticadas oferecem uma vantagem competitiva, permitindo que os investidores naveguem por incertezas e capitalizem oportunidades em diversas classes de ativos.

O artigo fornece um passo a passo detalhado do processo de implementação, incluindo trechos de código tanto para Python quanto para MQL5, ilustrando como obter dados históricos, calcular retornos, gerar sinais de negociação com base em cruzamentos de médias móveis e otimizar a alocação de ativos. Ele também demonstra como visualizar os resultados, o que é crucial para interpretar e comunicar as descobertas de forma eficaz.

Em resumo, o artigo serve como um recurso valioso para traders e profissionais financeiros que buscam aprimorar suas estratégias de investimento por meio de técnicas avançadas de otimização de portfólio. Ele destaca a sinergia entre finanças quantitativas e tecnologia, oferecendo insights práticos sobre o desenvolvimento de sistemas de negociação robustos e adaptáveis. A conclusão dos autores enfatiza a natureza indispensável de tais ferramentas para alcançar retornos ajustados ao risco de maneira eficiente e construir estratégias de investimento resilientes nos mercados financeiros dinâmicos de hoje.


Conclusão

Em conclusão, a integração de Python e MQL5 para otimização de portfólio representa um avanço significativo no desenvolvimento de estratégias de negociação, combinando o poder analítico do Python com as capacidades de negociação sem costura do MetaTrader 5. Esses programas inovadores são projetados para capacitar os traders com a capacidade de analisar dados históricos, otimizar a alocação de ativos e visualizar resultados de maneira eficaz, melhorando assim a tomada de decisões orientada por dados nos mercados financeiros.

Ao utilizar as bibliotecas extensivas do Python, incluindo Pandas, Numpy e cvxpy, juntamente com a programação nativa em MQL5 do MetaTrader 5, os traders podem gerenciar e adaptar seus portfólios de maneira eficiente às condições de mercado em mudança. Essa abordagem dual não só facilita os testes iniciais de estratégias em Python, mas também garante sua aplicação prática e precisão dentro do ambiente MetaTrader 5. À medida que o cenário financeiro se torna cada vez mais complexo e volátil, tais ferramentas sofisticadas são indispensáveis para alcançar retornos ajustados ao risco de maneira eficiente. Ao mitigar os vieses humanos e aproveitar modelos matemáticos avançados, esses programas de otimização de portfólio oferecem uma estrutura robusta para construir estratégias de investimento resilientes.

Agradecemos seu interesse neste artigo e incentivamos você a explorar mais essas ferramentas para melhorar o desempenho de suas negociações e a gestão financeira estratégica. Obrigado e melhores cumprimentos.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15288

Estratégia de Negociação do SP500 em MQL5 para Iniciantes Estratégia de Negociação do SP500 em MQL5 para Iniciantes
Descubra como aproveitar o MQL5 para prever o S&P 500 com precisão, misturando a análise técnica clássica para maior estabilidade e combinando algoritmos com princípios testados pelo tempo para obter insights robustos do mercado.
Estratégia de Trading Cascade Order Baseada em Cruzamentos de EMA para MetaTrader 5 Estratégia de Trading Cascade Order Baseada em Cruzamentos de EMA para MetaTrader 5
Este artigo orienta sobre como demonstrar um algoritmo automatizado baseado em cruzamentos de EMA para MetaTrader 5. Informações detalhadas sobre todos os aspectos de demonstrar um Expert Advisor em MQL5 e testá-lo no MetaTrader 5 – desde a análise de comportamentos de faixa de preços até o gerenciamento de risco.
Integre Seu Próprio LLM no EA (Parte 4): Treinando Seu Próprio LLM com GPU Integre Seu Próprio LLM no EA (Parte 4): Treinando Seu Próprio LLM com GPU
Com o rápido desenvolvimento da inteligência artificial hoje em dia, os modelos de linguagem (LLMs) são uma parte importante da IA, então devemos pensar em como integrar LLMs poderosos ao nosso trading algorítmico. Para a maioria das pessoas, é difícil ajustar esses modelos poderosos de acordo com suas necessidades, implantá-los localmente e depois aplicá-los ao trading algorítmico. Esta série de artigos adotará uma abordagem passo a passo para alcançar esse objetivo.
Criando uma Interface Gráfica de Usuário Interativa em MQL5 (Parte 2): Adicionando Controles e Responsividade Criando uma Interface Gráfica de Usuário Interativa em MQL5 (Parte 2): Adicionando Controles e Responsividade
Melhorar o painel GUI do MQL5 com recursos dinâmicos pode melhorar significativamente a experiência de negociação para os usuários. Ao incorporar elementos interativos, efeitos de hover e atualizações de dados em tempo real, o painel se torna uma ferramenta poderosa para os traders modernos.