English 日本語
preview
Portfolio-Optimierung in Python und MQL5

Portfolio-Optimierung in Python und MQL5

MetaTrader 5Statistik und Analyse | 5 September 2024, 10:01
33 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Einführung

Die erste, auf Python basierende Lösung nutzt die Leistungsfähigkeit der MetaTrader 5-Integration zusammen mit fortschrittlichen Bibliotheken wie pandas, Numpy und cvxpy, um historische Daten zu analysieren, die Asset Allocation zu optimieren und die Ergebnisse mit Matplotlib zu visualisieren. Die zweite, ähnliche Implementierung in MQL5 nutzt die nativen Fähigkeiten der MetaTrader 5-Plattform und bietet Händlern eine nahtlose Erfahrung direkt in ihrer bevorzugten Handelsumgebung. Beide Programme stehen beispielhaft für die hochmoderne Schnittstelle zwischen quantitativer Finanzwirtschaft und Technologie, die Händlern hochentwickelte Werkzeuge an die Hand gibt, um datengestützte Entscheidungen in einer sich ständig weiterentwickelnden Marktlandschaft zu treffen.


Warum brauchen wir eine Portfolio-Optimierung?

Programme zur Portfolio-Optimierung sind ein wichtiges Instrument des modernen Finanzmanagements, um in einer zunehmend komplexen und volatilen Anlagelandschaft effiziente, risikoadjustierte Renditen zu erzielen. Durch den Einsatz fortschrittlicher mathematischer Modelle und Rechenleistung ermöglichen diese Programme Anlegern und Finanzexperten, datengestützte Entscheidungen zu treffen, die auf ihre spezifischen Risikotoleranzen und Anlageziele zugeschnitten sind. Solche Programme analysieren systematisch große Mengen historischer Daten, Markttrends und Korrelationen von Vermögenswerten, um eine optimale Vermögensaufteilung zu ermitteln, die die potenziellen Erträge maximiert und gleichzeitig das Gesamtrisiko des Portfolios minimiert.

Diese wissenschaftliche Herangehensweise an die Portfoliokonstruktion trägt dazu bei, menschliche Voreingenommenheit und emotionale Entscheidungsfindung, die häufig mit traditionellen Anlagestrategien verbunden sind, abzuschwächen. Darüber hinaus erleichtern Portfolio-Optimierungsprogramme eine dynamische Neugewichtung, die es den Anlegern ermöglicht, sich schnell an veränderte Marktbedingungen anzupassen und ihre langfristigen finanziellen Ziele beizubehalten. In einer Ära globaler wirtschaftlicher Verflechtung und schnellen Informationsflusses bieten diese hochentwickelten Tools einen Wettbewerbsvorteil, der es den Anlegern ermöglicht, Unsicherheiten zu bewältigen und Chancen in verschiedenen Anlageklassen zu nutzen, was letztlich zu robusteren und widerstandsfähigeren Anlagestrategien führt.


Warum sollten wir Python verwenden?

Python ist ein guter Weg, um Strategien oder Ideen schnell auszuprobieren, es hat eine große Community und läuft schnell. Es zählt auch mit MetraTrader5 Bibliothek, um Daten herunterzuladen oder sogar Trades zu machen. Also werden wir zunächst Python verwenden, um zu sehen, ob ihre Idee konsistent ist, und wir sollten verschiedene % des Kontos mit verschiedenen Symbolen verwenden.

Dies ist das Python-Skript, das wir verwenden werden:

# 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)

Die Ergebnisse sehen wie folgt aus:

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

und dies ist das Diagramm:

Schaubild 1

Die Ergebnisse sagen uns, dass wir nur in Amazon investieren sollen, aber wir können dem Skript eine Strategie hinzufügen, um zu sehen, ob sich die Werte ändern, und die Ergebnisse uns auffordern, in andere Symbole zu investieren.

Wir können dies tun, indem wir dies zum Skript hinzufügen (wir werden eine einfache Strategie von zwei MA-Kreuzungen verwenden), Sie können diese Strategie ändern, um diejenige zu verwenden, die Sie benötigen:

# 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

und fügen auch dies im Hauptteil hinzu:

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

Die Ergebnisse werden wie folgt dargestellt:

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

Abbildung 2

Es hat einige kleine Änderungen gegeben, aber die Ergebnisse sehen insgesamt gleich aus.

Das liegt daran, dass AMZN in diesem Zeitraum einen gigantischen Trend hatte.

AMZN

Man muss sich dessen bewusst sein und darauf achten, dass der Trend gestoppt wird, aber man kann verstehen, warum das Risikomanagement so wichtig ist.


MQL5 Skript

Wir haben soeben gesehen, wie man dieses Risikomanagement in Python entwickelt. Jetzt werden wir dasselbe Skript in MQL5 reproduzieren, weil MQL5 genauer ist.

Hier ist das Drehbuch:

//+------------------------------------------------------------------+
//|                                        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("-----------------------");
        }
     }
  }

Zunächst definiert das Skript eine Liste der zu berücksichtigenden Assets, die durch ihre Symbole dargestellt werden. Sie legt auch den Datumsbereich für den Erhalt historischer Daten fest, indem sie ein Anfangs- und Enddatum angibt.

Die Funktion obtenerDatosHistoricos ist für das Abrufen historischer Daten für ein bestimmtes Asset innerhalb des angegebenen Datumsbereichs zuständig. Sie verwendet die Funktion CopyRates, um die Daten abzurufen und sie in einem Array von MqlRates-Strukturen zu speichern. Die Funktion kopiert diese Daten dann in ein Ausgabe-Array, wobei das richtige Format und die richtige Größe gewährleistet werden. Wenn der Datenabruf fehlschlägt, wird eine Fehlermeldung gedruckt, während ein erfolgreicher Abruf zu einer Bestätigungsmeldung führt, in der die Anzahl der kopierten Datenpunkte angegeben wird.

Die Funktion calcularRendimientos berechnet die täglichen Renditen aus den historischen Daten. Dabei werden die Datenpunkte durchlaufen und die Rendite als prozentuale Veränderung der Schlusskurse zwischen aufeinander folgenden Tagen berechnet. Die Funktion behandelt potenzielle Fehler, wie z. B. Schlusskurse von Null, und protokolliert verdächtige Erträge, die einen vordefinierten Schwellenwert überschreiten. Es verfolgt die maximalen und minimalen Renditen, die während der Berechnungen auftreten, und druckt regelmäßige Aktualisierungen, um die berechneten Renditen zu überprüfen.

Die Hauptfunktion OnStart initialisiert Arrays zur Speicherung historischer Daten und kehrt zurück. Es durchläuft jedes Vermögenssymbol, ruft obtenerDatosHistoricos auf, um die Daten zu holen, und dann calcularRendimientos, um die Renditen zu berechnen. Nach der Berechnung der Renditen fährt die Funktion mit der Berechnung der erwarteten Rendite und der Varianz fort. Es summiert die gültigen Renditen, berechnet die mittlere Rendite und berechnet dann die Varianz der Renditen. Die Ergebnisse, einschließlich der erwarteten Rendite, der Varianz, der Summe der Renditen und der Anzahl der gültigen Renditen, werden für jedes Asset auf der Konsole ausgegeben. Wenn nicht genügend Daten vorhanden sind oder das Datenformat nicht korrekt ist, wird eine entsprechende Meldung protokolliert.

Im gesamten Skript ist eine umfangreiche Protokollierung implementiert, um Transparenz zu gewährleisten und die Fehlersuche zu erleichtern. Meldungen zeigen den Fortschritt und die Ergebnisse des Datenabrufs, der Rückgabeberechnung und der statistischen Analyse an, sodass der Nutzer den Ablauf der Ausführung verfolgen und auftretende Probleme erkennen kann.

Um diese Skripte auszuführen, ziehen Sie einfach das Skript auf ein Chart, und Sie werden diese Ergebnisse sehen:

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)     -----------------------

Wie Sie aus den Ergebnissen ersehen können, sollte AAPL bei etwa 40% und AMZN bei 60%, EURUSD 3% und GBPUSD 6%. Diese Werte sind orientiert, und es wurden keine Strategien angewandt. 


Hinzufügen einer Strategie zum MQL5-Skript

Sie müssen dies dem ersten Skript hinzufügen:

Funktion zur Berechnung des gleitenden Durchschnitts

Diese Funktion berechnet den gleitenden Durchschnitt für einen bestimmten Datensatz über einen bestimmten Zeitraum. Es geht die Datenpunkte durch, summiert die Schlusskurse über den definierten Zeitraum und teilt sie dann durch den Zeitraum, um den Durchschnitt zu erhalten. Wenn nicht genügend Daten zur Berechnung des gleitenden Durchschnitts vorliegen, setzt die Funktion den Wert auf Null.

//+------------------------------------------------------------------+
//| 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
        }
     }
  }

Und integrieren Sie dies in 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("-----------------------");
        }
     }
  }

Diese Funktion generiert Handelssignale, die auf dem Kreuzen von zwei gleitenden Durchschnitten (kurze und lange Periode) basieren. Er durchläuft die Daten und sucht nach Fällen, in denen der gleitende Durchschnitt der kurzen Periode den gleitenden Durchschnitt der langen Periode über- oder unterschreitet. Das Kreuzen nach oben erzeugt ein Kaufsignal, während das Kreuzen nach unten ein Verkaufssignal erzeugt. Wenn es kein Überkreuzen gibt, wird kein Signal erzeugt.


Integration in die Hauptfunktion OnStart

In der Hauptfunktion werden die historischen Daten für jedes Symbol ermittelt und die Renditen berechnet. Anschließend werden die gleitenden Durchschnitte und Handelssignale für jedes Symbol berechnet. Die gleitenden Durchschnitte werden mit der Funktion calcularMediaMovil sowohl für die kurze als auch für die lange Periode ermittelt. Die Funktion generarSenales wird verwendet, um Kauf- und Verkaufssignale auf der Grundlage der gleitenden Durchschnittsübergänge zu erzeugen. Die Ergebnisse, einschließlich der berechneten Signale, werden zur Überprüfung auf der Konsole ausgedruckt.

Dieser Code enthält nun eine einfache Kreuzungs-Strategie mit gleitendem Durchschnitt, die Kauf- und Verkaufssignale erzeugt. Die Handelssignale werden zur Überprüfung auf der Konsole ausgedruckt, sodass die Perioden der gleitenden Durchschnitte bei Bedarf angepasst werden können.

Die Ergebnisse sehen wie folgt aus:

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

Der Artikel stellt eine umfassende Untersuchung von Portfolio-Optimierungstechniken vor, die sowohl Python als auch die MQL5-Programmiersprachen mit der MetaTrader 5-Plattform nutzen, und betont die entscheidende Rolle datengesteuerter Entscheidungsfindung im modernen Finanzmanagement. Er erläutert den Prozess der Entwicklung und Implementierung anspruchsvoller Algorithmen, die historische Daten analysieren, die Asset-Allokation optimieren und Handelssignale auf der Grundlage gleitender Durchschnittsübergänge erzeugen.

Die Autoren unterstreichen die Bedeutung der Portfolio-Optimierung als wesentliches Instrument zur Erzielung effizienter risikoangepasster Renditen in einer zunehmend komplexen und volatilen Anlagelandschaft. Durch den Einsatz fortschrittlicher mathematischer Modelle und Rechenleistung ermöglichen diese Programme Anlegern, fundierte Entscheidungen zu treffen, die auf ihre spezifischen Risikotoleranzen und Anlageziele zugeschnitten sind. Der Artikel zeigt, wie solche Optimierungstechniken systematisch große Mengen historischer Daten, Markttrends und Korrelationen von Vermögenswerten analysieren können, um optimale Vermögensallokationen zu bestimmen, die die potenziellen Erträge maximieren und gleichzeitig das Gesamtrisiko des Portfolios minimieren.

Der duale Ansatz, Python für erste Strategietests und MQL5 für die nahtlose Integration in MetaTrader 5 zu verwenden, zeigt die Vielseitigkeit und Leistungsfähigkeit der Kombination verschiedener Programmierumgebungen. Diese Methode ermöglicht es Händlern, von den umfangreichen Bibliotheken und analytischen Fähigkeiten von Python zu profitieren und gleichzeitig die nativen Funktionen der MetaTrader 5 Plattform zu nutzen.

Die Notwendigkeit des Einsatzes von Portfolio-Optimierung im Handel kann gar nicht hoch genug eingeschätzt werden, da sie einen wissenschaftlichen Ansatz für die Portfoliokonstruktion bietet und dazu beiträgt, menschliche Voreingenommenheit und emotionale Entscheidungsfindung, die oft mit traditionellen Anlagestrategien verbunden sind, abzuschwächen. In einer Ära globaler wirtschaftlicher Verflechtung und schnellen Informationsflusses bieten diese hochentwickelten Tools einen Wettbewerbsvorteil, der es Anlegern ermöglicht, Unsicherheiten zu bewältigen und Chancen in verschiedenen Anlageklassen zu nutzen.

Der Artikel bietet einen detaillierten Durchgang durch den Implementierungsprozess, einschließlich Codeschnipseln für Python und MQL5, die veranschaulichen, wie man historische Daten erhält, Renditen berechnet, Handelssignale auf der Grundlage von gleitenden Durchschnittsübergängen generiert und die Asset-Allokation optimiert. Es wird auch gezeigt, wie man die Ergebnisse visualisiert, was für eine effektive Interpretation und Kommunikation der Ergebnisse entscheidend ist.

Zusammengefasst dient der Artikel als wertvolle Ressource für Händler und Finanzexperten, die ihre Anlagestrategien durch fortgeschrittene Portfolio-Optimierungstechniken verbessern wollen. Es unterstreicht die Synergie zwischen quantitativer Finanzwirtschaft und Technologie und bietet praktische Einblicke in die Entwicklung robuster und anpassungsfähiger Handelssysteme. Die Schlussfolgerung des Autors unterstreicht die Unverzichtbarkeit solcher Instrumente für die Erzielung effizienter risikoangepasster Renditen und die Entwicklung belastbarer Anlagestrategien auf den dynamischen Finanzmärkten von heute.


Schlussfolgerung

Zusammenfassend lässt sich sagen, dass die Integration von Python und MQL5 für die Portfolio-Optimierung einen bedeutenden Fortschritt in der Entwicklung von Handelsstrategien darstellt, indem sie die analytischen Fähigkeiten von Python mit den nahtlosen Handelsmöglichkeiten von MetaTrader 5 verbindet. Diese innovativen Programme sollen Händlern die Möglichkeit geben, historische Daten zu analysieren, die Asset-Allokation zu optimieren und Ergebnisse effektiv zu visualisieren, um so die datengestützte Entscheidungsfindung auf den Finanzmärkten zu verbessern.

Durch die Verwendung der umfangreichen Python-Bibliotheken, einschließlich Pandas, Numpy und cvxpy, zusammen mit dem nativen MQL5-Scripting von MetaTrader 5 können Händler ihre Portfolios effizient verwalten und an sich ändernde Marktbedingungen anpassen. Dieser duale Ansatz erleichtert nicht nur das anfängliche Testen von Strategien in Python, sondern gewährleistet auch ihre praktische Anwendung und Genauigkeit innerhalb der MetaTrader 5-Umgebung. Da die Finanzlandschaft immer komplexer und volatiler wird, sind solche ausgefeilten Instrumente unverzichtbar, um effiziente risikobereinigte Renditen zu erzielen. Durch die Abschwächung menschlicher Voreingenommenheit und die Nutzung fortschrittlicher mathematischer Modelle bieten diese Portfolio-Optimierungsprogramme einen robusten Rahmen für die Entwicklung belastbarer Anlagestrategien.

Wir freuen uns über Ihr Interesse an diesem Artikel und ermutigen Sie, diese Instrumente zur Verbesserung der Handelsleistung und des strategischen Finanzmanagements weiter zu erforschen. Vielen Dank und herzliche Grüße.

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

Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Kombinieren Sie fundamentale und technische Analysestrategien in MQL5 für Einsteiger Kombinieren Sie fundamentale und technische Analysestrategien in MQL5 für Einsteiger
In diesem Artikel wird erörtert, wie sich Trendfolge- und Fundamentalprinzipien nahtlos in einen Expert Advisor integrieren lassen, um eine robustere Strategie zu entwickeln. In diesem Artikel wird gezeigt, wie einfach es für jedermann ist, mit MQL5 maßgeschneiderte Handelsalgorithmen zu erstellen und anzuwenden.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Erstellen einer interaktiven grafischen Nutzeroberfläche in MQL5 (Teil 2): Hinzufügen von Steuerelementen und Reaktionsfähigkeit Erstellen einer interaktiven grafischen Nutzeroberfläche in MQL5 (Teil 2): Hinzufügen von Steuerelementen und Reaktionsfähigkeit
Die Erweiterung des MQL5-GUI-Panels um dynamische Funktionen kann die Handelserfahrung für die Nutzer erheblich verbessern. Durch die Einbindung interaktiver Elemente, Hover-Effekte und Datenaktualisierungen in Echtzeit wird das Panel zu einem leistungsstarken Werkzeug für moderne Händler.