English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
preview
Python, ONNX e MetaTrader 5: Creazione di un modello RandomForest con RobustScaler e preelaborazione dei dati PolynomialFeatures

Python, ONNX e MetaTrader 5: Creazione di un modello RandomForest con RobustScaler e preelaborazione dei dati PolynomialFeatures

MetaTrader 5Tester |
472 14
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Quale base utilizzeremo? Che cos'è la Foresta Casuale?

La storia dello sviluppo del metodo Random Forest (Foresta Casuale) risale a molto tempo fa ed è associata al lavoro di importanti scienziati nel campo dell'apprendimento automatico e della statistica. Per comprendere meglio i principi e l'applicazione di questo metodo, immaginiamo un enorme gruppo di persone (alberi decisionali) che lavorano insieme.

Il metodo random forest ha le sue radici negli alberi decisionali. Gli alberi decisionali sono una rappresentazione grafica di un algoritmo decisionale, in cui ogni nodo rappresenta un test su uno degli attributi, ogni ramo è il risultato di quel test e le foglie sono l'output previsto. Gli alberi decisionali sono stati sviluppati a metà del XX secolo e sono diventati strumenti di classificazione e regressione molto popolari.

Il passo successivo è stato il concetto di bagging (Bootstrap Aggregating), proposto da Leo Breiman nel 1996. Il bagging implica la suddivisione di un set di dati di addestramento in più campioni bootstrap (sottocampioni) e l'addestramento di modelli separati su ciascuno di essi. I risultati dei modelli vengono poi mediati o combinati per produrre previsioni più robuste e accurate. Questo metodo ha permesso di ridurre la varianza dei modelli e di migliorare la loro capacità di generalizzazione.

Il metodo Random Forest è stato proposto da Leo Breiman e Adele Cutler nei primi anni 2000. Si basa sull'idea di combinare più alberi decisionali utilizzando il bagging e una casualità aggiuntiva. Ogni albero è costruito a partire da un sottocampione casuale del set di dati di addestramento e per la costruzione di ogni nodo dell'albero, viene selezionato un insieme casuale di caratteristiche. Questo rende ogni albero unico e riduce la correlazione tra gli alberi, migliorando la capacità di generalizzazione.

Random Forest è diventato rapidamente uno dei metodi più popolari nel campo dell'apprendimento automatico, grazie alle sue elevate prestazioni e alla capacità di gestire problemi di classificazione e regressione. Nei problemi di classificazione, viene utilizzato per prendere decisioni sulla classe di appartenenza di un oggetto, mentre nella regressione viene utilizzato per prevedere valori numerici.

Oggi, Random Forest è ampiamente utilizzato in vari campi, tra cui la finanza, la medicina, l'analisi dei dati e molti altri. È apprezzato per la sua robustezza e la capacità di gestire problemi complessi di apprendimento automatico.

Random Forest è un potente strumento dell'apprendimento automatico. Per capire meglio come funziona, visualizziamolo come un enorme gruppo di persone che si riunisce e prende decisioni collettive. Tuttavia, invece di persone reali, ogni membro di questo gruppo è un classificatore o predittore indipendente della situazione attuale. All'interno di questo gruppo, una persona è un albero decisionale in grado di prendere decisioni in base a determinati attributi. Quando la foresta casuale prende una decisione, utilizza la democrazia e il voto: ogni albero esprime la propria opinione e la decisione viene presa sulla base di più voti.

La foresta casuale è ampiamente utilizzata in diversi campi e la sua flessibilità la rende adatta sia ai problemi di classificazione che di regressione. In un compito di classificazione, il modello decide a quale classe predefinita appartiene lo stato corrente. Ad esempio, nel mercato finanziario, ciò potrebbe significare la decisione di acquistare (classe 1) o vendere (classe 0) un asset sulla base di una serie di indicatori.

Tuttavia, in questo articolo ci concentreremo sui problemi di regressione. La regressione nell'apprendimento automatico è un tentativo di prevedere i valori numerici futuri di una serie temporale sulla base dei suoi valori passati. Invece della classificazione, che assegna gli oggetti a determinate classi, la regressione mira a prevedere numeri specifici. Potrebbe essere, ad esempio, la previsione dei prezzi delle azioni, della previsione della temperatura o di qualsiasi altra variabile numerica.


Creazione di un modello RF di base

Per creare un modello Random Forest di base, utilizzeremo la libreria sklearn (Scikit-learn) in Python. Di seguito è riportato un semplice modello di codice per l'addestramento di un modello di regressione Random Forest. Prima di eseguire questo codice, si devono installare le librerie necessarie per eseguire sklearn utilizzando lo strumento Python Package Installer.

pip install onnx
pip install skl2onnx
pip install MetaTrader5

Successivamente, è necessario importare le librerie e impostare i parametri. Importiamo le librerie necessarie, tra cui "pandas" per lavorare con i dati, "gdown" per caricare i dati da Google Drive, come anche le librerie per l'elaborazione dei dati e la creazione di un modello Random Forest. Si imposta anche il numero di passi temporali (n_steps) nella sequenza di dati, che viene determinato in base ai requisiti specifici:

import pandas as pd
import gdown
import numpy as np
import joblib
import random
import onnx
import os
import shutil
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.utils import shuffle
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import RobustScaler, MinMaxScaler, PolynomialFeatures, PowerTransformer
import MetaTrader5 as mt5
from datetime import datetime

# Set the number of time steps according to requirements
n_steps = 100

Nella fase successiva, carichiamo ed elaboriamo i dati. Nel nostro esempio specifico, carichiamo i dati dei prezzi da MetaTrader 5 e li elaboriamo. Impostiamo l'indice temporale e selezioniamo solo i prezzi di chiusura (è con questi che lavoreremo):

mt5.initialize() SYMBOL = 'EURUSD' TIMEFRAME = mt5.TIMEFRAME_H1 START_DATE = datetime(2000, 1, 1) STOP_DATE = datetime(2023, 1, 1) # Set the number of time steps according to your requirements n_steps = 100 # Process data data = pd.DataFrame(mt5.copy_rates_range(SYMBOL, TIMEFRAME, START_DATE, STOP_DATE), columns=['time', 'close']).set_index('time') data.index = pd.to_datetime(data.index, unit='s') data = data.dropna() data = data[['close']] # Work only with close prices
Ecco la parte di codice responsabile della suddivisione dei nostri dati in set di addestramento e test e dell'etichettatura del set per l'addestramento del modello. Abbiamo diviso i dati in set di allenamento e set di test. Quindi etichettiamo i dati per la regressione, il che significa che ogni etichetta rappresenta l'effettivo valore futuro del prezzo. La funzione labelling_relabeling_regression viene utilizzata per creare dati etichettati. 
# Define train_data_initial
training_size = int(len(data) * 0.70)
train_data_initial = data.iloc[:training_size]
test_data_initial = data.iloc[training_size:]

# Function for creating and assigning labels for regression (changes made for regression, not classification)
def labelling_relabeling_regression(dataset, min_value=1, max_value=1):
    future_prices = []

    for i in range(dataset.shape[0] - max_value):
        rand = random.randint(min_value, max_value)
        future_pr = dataset['<CLOSE>'].iloc[i + rand]
        future_prices.append(future_pr)

    dataset = dataset.iloc[:len(future_prices)].copy()
    dataset['future_price'] = future_prices

    return dataset

# Apply the labelling_relabeling_regression function to raw data to get labeled data
train_data_labeled = labelling_relabeling_regression(train_data_initial)
test_data_labeled = labelling_relabeling_regression(test_data_initial)

Successivamente, creiamo set di dati di addestramento a partire da determinate sequenze. L'importante è che il modello prenda come caratteristiche tutti i prezzi di chiusura della nostra sequenza. La stessa dimensione della sequenza viene utilizzata come dimensione dei dati in ingresso al modello ONNX. In questa fase non è prevista la normalizzazione, che verrà eseguita nella pipeline di addestramento, come parte dell'operazione di pipeline del modello.

# Create datasets of features and target variables for training
x_train = np.array([train_data_labeled['<CLOSE>'].iloc[i - n_steps:i].values[-n_steps:] for i in range(n_steps, len(train_data_labeled))])
y_train = train_data_labeled['future_price'].iloc[n_steps:].values

# Create datasets of features and target variables for testing
x_test = np.array([test_data_labeled['<CLOSE>'].iloc[i - n_steps:i].values[-n_steps:] for i in range(n_steps, len(test_data_labeled))])
y_test = test_data_labeled['future_price'].iloc[n_steps:].values

# After creating x_train and x_test, define n_features as follows:
n_features = x_train.shape[1] 

# Now use n_features to determine the ONNX input data type
initial_type = [('float_input', FloatTensorType([None, n_features]))]


Creazione di una Pipeline per la preelaborazione dei dati

Il passo successivo è la creazione di un modello Random Forest. Questo modello deve essere costruito come una pipeline. 

La Pipeline della libreria scikit-learn (sklearn) è un modo per creare una catena sequenziale di trasformazioni e modelli per l'analisi dei dati e l'apprendimento automatico. Una pipeline consente di combinare più fasi di elaborazione e modellazione dei dati in un unico oggetto che può essere utilizzato per operare con i dati in modo efficiente e sequenziale.

Nel nostro esempio di codice, creiamo la seguente pipeline:

# Create a pipeline with MinMaxScaler, RobustScaler, PolynomialFeatures and RandomForestRegressor
pipeline = Pipeline([
    ('MinMaxScaler', MinMaxScaler()),
    ('robust', RobustScaler()),
    ('poly', PolynomialFeatures()),
    ('rf', RandomForestRegressor(
        n_estimators=20,
        max_depth=20,
        min_samples_split=5000,
        min_samples_leaf=5000,
        random_state=1,
        verbose=2
    ))
])

# Train the pipeline
pipeline.fit(x_train, y_train)

# Make predictions
predictions = pipeline.predict(x_test)

# Evaluate model using R2
r2 = r2_score(y_test, predictions)
print(f'R2 score: {r2}')

Come si può vedere, una pipeline è una sequenza di fasi di elaborazione e modellazione dei dati combinate in un'unica serie. In questo codice, la pipeline viene creata utilizzando la libreria scikit-learn. Comprende le seguenti fasi:

  1. MinMaxScaler ridimensiona i dati in un intervallo da 0 a 1. Questo è utile per garantire che tutte le caratteristiche siano di uguale scala.

  2. Anche RobustScaler esegue il ridimensionamento dei dati, ma è più robusto nei confronti dei valori anomali del set di dati. Utilizza la mediana e lo scarto interquartile per il ridimensionamento.

  3. PolynomialFeatures applica una trasformazione polinomiale alle caratteristiche. Questo aggiunge caratteristiche polinomiali che possono aiutare il modello a tenere conto di relazioni non lineari nei dati.

  4. RandomForestRegressor definisce un modello di foresta casuale con un insieme di iperparametri:

    • n_estimators (numero di alberi nella foresta). Supponiamo di avere un gruppo di esperti, ognuno dei quali è specializzato nella previsione dei prezzi sul mercato finanziario. Il numero di alberi nella foresta casuale (n_estimators) determina il numero di tali esperti nel gruppo. Più alberi ci sono, più opinioni e previsioni diverse saranno prese in considerazione quando il modello prenderà una decisione.
    • max_depth (profondità massima di ogni albero). Questo parametro imposta la profondità con cui ogni esperto (albero) può "immergersi" nell'analisi dei dati. Ad esempio, se si imposta la profondità massima a 20, ogni albero prenderà decisioni basate su non più di 20 caratteristiche.
    • min_samples_split (numero minimo di campioni per dividere un nodo dell'albero). Questo parametro indica quanti campioni (osservazioni) devono essere presenti in un nodo dell'albero affinché l'albero continui a dividerlo in nodi più piccoli. Ad esempio, se si imposta il numero minimo di campioni da dividere a 5000, l'albero dividerà i nodi solo se ci sono più di 5000 osservazioni per nodo.
    • min_samples_leaf (numero minimo di campioni in un nodo foglia). Questo parametro determina quanti campioni devono essere presenti in un nodo foglia dell'albero affinché tale nodo diventi una foglia e non venga ulteriormente suddiviso. Ad esempio, se si imposta il numero minimo di campioni in un nodo foglia a 5000, ogni foglia dell'albero conterrà almeno 5000 osservazioni.
    • random_state (imposta lo stato iniziale per la generazione casuale, garantendo risultati riproducibili). Questo parametro viene utilizzato per controllare i processi casuali all'interno del modello. Se si imposta un valore fisso (ad esempio, 1), i risultati saranno gli stessi ogni volta che si esegue il modello. Questo è utile per la riproducibilità dei risultati.
    • verbose (consente di visualizzare le informazioni sul processo di addestramento del modello). Quando si addestra un modello, può essere utile vedere le informazioni sul processo. Il parametro "verbose" consente di controllare il livello di dettaglio di queste informazioni. Più alto è il valore (ad esempio, 2), più informazioni verranno emesse durante il processo di addestramento.

Dopo aver creato la pipeline, utilizziamo il metodo "fit" per addestrarla sui dati di addestramento. Quindi, utilizzando il metodo "predict", si fanno previsioni sui dati di test. Alla fine, valutiamo la qualità del modello utilizzando la metrica R2, che misura l'adattamento del modello ai dati.

La pipeline viene addestrata e poi valutata rispetto alla metrica R2. Utilizziamo la normalizzazione, la rimozione dei valori anomali dai dati e la creazione di caratteristiche polinomiali. Questi sono i metodi più semplici di pre-elaborazione dei dati. Nei prossimi articoli vedremo come creare la propria funzione di preelaborazione utilizzando Function Transformer.


Esportazione del modello in ONNX, scrittura della funzione di esportazione

Dopo aver addestrato la pipeline, la salviamo nel formato joblib, che viene salvato nel formato ONNX utilizzando la libreria skl2onnx.

# Save the pipeline
joblib.dump(pipeline, 'rf_pipeline.joblib')

# Convert pipeline to ONNX
onnx_model = convert_sklearn(pipeline, initial_types=initial_type)

# Save the model in ONNX format
model_onnx_path = "rf_pipeline.onnx"
onnx.save_model(onnx_model, model_onnx_path)

# Save the model in ONNX format
model_onnx_path = "rf_pipeline.onnx"
onnx.save_model(onnx_model, model_onnx_path)

# Connect Google Drive (if you work in Colab and this is necessary)
from google.colab import drive
drive.mount('/content/drive')

# Specify the path to Google Drive where you want to move the model
drive_path = '/content/drive/My Drive/'  # Make sure the path is correct
rf_pipeline_onnx_drive_path = os.path.join(drive_path, 'rf_pipeline.onnx')

# Move ONNX model to Google Drive
shutil.move(model_onnx_path, rf_pipeline_onnx_drive_path)

print('The rf_pipeline model is saved in the ONNX format on Google Drive:', rf_pipeline_onnx_drive_path)

In questo modo abbiamo addestrato il modello e lo abbiamo salvato in ONNX. Questo è ciò che vedremo dopo aver completato l’addestramento:


Il modello viene salvato in formato ONNX nella directory di base di Google Drive. ONNX può essere considerato una sorta di "floppy disk" per i modelli di apprendimento automatico. Questo formato consente di salvare i modelli addestrati e di convertirli per utilizzarli in varie applicazioni. È simile al modo in cui si salvano i file su un'unità flash per poi leggerli su altri dispositivi. Nel nostro caso, il modello ONNX verrà utilizzato nell'ambiente MetaTrader 5 per prevedere i prezzi dei mercati finanziari. Lo stesso "floppy disk" ONNX può essere letto in un'applicazione di terze parti, per esempio in MetaTrader 5. Questo è ciò che faremo ora.


Verifica del modello nel Tester di MetaTrader 5

Abbiamo precedentemente salvato il modello ONNX su Google Drive. Ora, scarichiamolo da lì. Per utilizzare questo modello in MetaTrader 5, creiamo un Expert Advisor che leggerà e applicherà questo modello per prendere decisioni di trading. Nel codice dell'Expert Advisor presentato, impostare i parametri di trading, come il volume dei lotti, l'uso degli ordini di stop, i livelli di Take Profit e Stop Loss. Ecco il codice dell'EA che "leggerà" il nostro modello ONNX:

//+------------------------------------------------------------------+
//|                                           ONNX Random Forest.mq5 |
//|                                                   Copyright 2023 |
//|                                                Evgeniy Koshtenko |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2023, Evgeniy Koshtenko"
#property link        "https://www.mql5.com"
#property version     "0.90"

static vectorf ExtOutputData(1);
vectorf output_data(1);

#include <Trade\Trade.mqh>
CTrade trade;

input double InpLots       = 1.0;    // Lot volume to open a position
input bool   InpUseStops   = true;   // Trade with stop orders
input int    InpTakeProfit = 500;    // Take Profit level
input int    InpStopLoss   = 500;    // Stop Loss level
#resource "Python/rf_pipeline.onnx" as uchar ExtModel[]

#define SAMPLE_SIZE 100

long     ExtHandle=INVALID_HANDLE;
int      ExtPredictedClass=-1;
datetime ExtNextBar=0;
datetime ExtNextDay=0;
CTrade   ExtTrade;

#define PRICE_UP   1
#define PRICE_SAME 2
#define PRICE_DOWN 0

// Function for closing all positions
void CloseAll(int type=-1)
{
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      if(PositionSelectByTicket(PositionGetTicket(i)))
      {
         if(PositionGetInteger(POSITION_TYPE)==type || type==-1)
         {
            trade.PositionClose(PositionGetTicket(i));
         }
      }
   }
}

// Expert Advisor initialization
int OnInit()
{
   if(_Symbol!="EURUSD" || _Period!=PERIOD_H1)
   {
      Print("The model should work with EURUSD, H1");
      return(INIT_FAILED);
   }

   ExtHandle=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT);
   if(ExtHandle==INVALID_HANDLE)
   {
      Print("Error creating model OnnxCreateFromBuffer ",GetLastError());
      return(INIT_FAILED);
   }

   const long input_shape[] = {1,100};
   if(!OnnxSetInputShape(ExtHandle,ONNX_DEFAULT,input_shape))
   {
      Print("Error setting the input shape OnnxSetInputShape ",GetLastError());
      return(INIT_FAILED);
   }

   const long output_shape[] = {1,1};
   if(!OnnxSetOutputShape(ExtHandle,0,output_shape))
   {
      Print("Error setting the output shape OnnxSetOutputShape ",GetLastError());
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

// Expert Advisor deinitialization
void OnDeinit(const int reason)
{
   if(ExtHandle!=INVALID_HANDLE)
   {
      OnnxRelease(ExtHandle);
      ExtHandle=INVALID_HANDLE;
   }
}

// Process the tick function
void OnTick()
{
   if(TimeCurrent()<ExtNextBar)
      return;

   ExtNextBar=TimeCurrent();
   ExtNextBar-=ExtNextBar%PeriodSeconds();
   ExtNextBar+=PeriodSeconds();

   PredictPrice();

   if(ExtPredictedClass>=0)
      if(PositionSelect(_Symbol))
         CheckForClose();
      else
         CheckForOpen();
}

// Check position opening conditions
void CheckForOpen(void)
{
   ENUM_ORDER_TYPE signal=WRONG_VALUE;

   if(ExtPredictedClass==PRICE_DOWN)
      signal=ORDER_TYPE_SELL;
   else
   {
      if(ExtPredictedClass==PRICE_UP)
         signal=ORDER_TYPE_BUY;
   }

   if(signal!=WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      double price,sl=0,tp=0;
      double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
      double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      if(signal==ORDER_TYPE_SELL)
      {
         price=bid;
         if(InpUseStops)
         {
            sl=NormalizeDouble(bid+InpStopLoss*_Point,_Digits);
            tp=NormalizeDouble(ask-InpTakeProfit*_Point,_Digits);
         }
      }
      else
      {
         price=ask;
         if(InpUseStops)
         {
            sl=NormalizeDouble(ask-InpStopLoss*_Point,_Digits);
            tp=NormalizeDouble(bid+InpTakeProfit*_Point,_Digits);
         }
      }
      ExtTrade.PositionOpen(_Symbol,signal,InpLots,price,sl,tp);
   }
}

// Check position closing conditions
void CheckForClose(void)
{
   if(InpUseStops)
      return;

   bool tsignal=false;
   long type=PositionGetInteger(POSITION_TYPE);

   if(type==POSITION_TYPE_BUY && ExtPredictedClass==PRICE_DOWN)
      tsignal=true;
   if(type==POSITION_TYPE_SELL && ExtPredictedClass==PRICE_UP)
      tsignal=true;

   if(tsignal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      ExtTrade.PositionClose(_Symbol,3);
      CheckForOpen();
   }
}

// Function to get the current spread
double GetSpreadInPips(string symbol)
{
    double spreadPoints = SymbolInfoInteger(symbol, SYMBOL_SPREAD);
    double spreadPips = spreadPoints * _Point / _Digits;
    return spreadPips;
}

// Function to predict prices
void PredictPrice()
{
   static vectorf output_data(1);
   static vectorf x_norm(SAMPLE_SIZE);
   double spread = GetSpreadInPips(_Symbol);

   if (!x_norm.CopyRates(_Symbol, _Period, COPY_RATES_CLOSE, 1, SAMPLE_SIZE))
   {
      ExtPredictedClass = -1;
      return;
   }

   if (!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, x_norm, output_data))
   {
      ExtPredictedClass = -1;
      return;
   }

   float predicted = output_data[0];

   if (spread < 0.000005 && predicted > iClose(Symbol(), PERIOD_CURRENT, 1))
   {
      ExtPredictedClass = PRICE_UP;
   }
   else if (spread < 0.000005 && predicted < iClose(Symbol(), PERIOD_CURRENT, 1))
   {
      ExtPredictedClass = PRICE_DOWN;
   }
   else
   {
      ExtPredictedClass = PRICE_SAME;
   }
}

Prestare attenzione alla seguente dimensione di input:

const long input_shape[] = {1,100};

deve corrispondere alla dimensione del nostro modello Python:

# Set the number of time steps to your requirements
n_steps = 100

Successivamente, iniziamo a testare il modello nell'ambiente MetaTrader 5. Utilizziamo le previsioni del modello per determinare la direzione dei movimenti del prezzo. Se il modello prevede che il prezzo salirà, ci prepariamo ad aprire una posizione long (acquisto) e viceversa, se il modello prevede che il prezzo scenderà, ci prepariamo ad aprire una posizione short (vendita). Testiamo il modello con un take profit di 1000 e uno stop loss di 500:


Conclusioni

In questo articolo abbiamo esaminato come creare e addestrare un modello Random Forest in Python, come pre-elaborare i dati direttamente all'interno del modello e come esportarli nello standard ONNX, per poi aprire e utilizzare il modello in MetaTrader 5.

ONNX è un eccellente sistema di importazione ed esportazione di modelli. È universale e semplice. Salvare un modello in ONNX è molto più semplice di quanto sembri. Anche la pre-elaborazione dei dati è molto facile. 

Naturalmente, il nostro modello di soli 20 alberi decisionali è molto semplice e il modello random forest stesso è già una soluzione abbastanza vecchia. Nei prossimi articoli creeremo modelli più complessi e moderni, utilizzando una pre-elaborazione dei dati più complessa. Vorrei anche sottolineare la possibilità di creare immediatamente un insieme di modelli sotto forma di pipeline sklearn, contemporaneamente alla pre-elaborazione. Questo può ampliare in modo significativo le nostre capacità, comprese quelle per i problemi di classificazione.





Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/13725

File allegati |
RF.zip (111.79 KB)
Ultimi commenti | Vai alla discussione (14)
Aleksey Nikolayev
Aleksey Nikolayev | 19 mag 2024 a 19:12
Yevgeniy Koshtenko #:

Solo la foresta è stata scelta come semplice esempio)Busting nel prossimo articolo, lo sto modificando un po' ora)

Bene)

Aleksey Nikolayev
Aleksey Nikolayev | 21 mag 2024 a 16:06
Yevgeniy Koshtenko #:


Sarebbe interessante sviluppare ulteriormente l'argomento dei trasportatori e della loro conversione in ONNX con il successivo utilizzo in Metatrader. Ad esempio, è possibile aggiungere trasformazioni personalizzate alla pipeline e il modello ONNX ottenuto da tale pipeline sarà aperto in Metatrader? Imho, l'argomento merita diversi articoli.

mytarmailS
mytarmailS | 26 mag 2024 a 17:28
Perché sono necessarie due normalizzazioni?
Perché abbiamo bisogno di una normalizzazione per la foresta?
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 27 mag 2024 a 10:31
Aleksey Nikolayev #:

Sarebbe interessante sviluppare ulteriormente l'argomento dei trasportatori e della loro conversione in ONNX con il successivo utilizzo in Metatrader. Ad esempio, è possibile aggiungere trasformazioni personalizzate alla pipeline e il modello ONNX ottenuto da tale pipeline sarà aperto in Metatrader? Imho, l'argomento merita diversi articoli.

Sì, è una grande idea. Forse sarà possibile effettuare trasformazioni personalizzate con la funzione Trasformazione
TahianaBE
TahianaBE | 21 giu 2025 a 18:50
Ciao. Ho provato a compilare il codice ma mi ha restituito un errore di conversione dei parametri input_shape e output_shape non consentito. Avete forse incontrato lo stesso problema? Se sì, quale potrebbe essere il modo corretto?
Analisi quantitativa in MQL5: Implementazione di un algoritmo promettente Analisi quantitativa in MQL5: Implementazione di un algoritmo promettente
Analizzeremo la questione di cosa sia l'analisi quantitativa e come viene utilizzata dai principali operatori. Creeremo uno degli algoritmi di analisi quantitativa nel linguaggio MQL5.
Template pronti per includere indicatori negli Expert Advisor (Parte 3): Indicatori di trend Template pronti per includere indicatori negli Expert Advisor (Parte 3): Indicatori di trend
In questo articolo di riferimento, esamineremo gli indicatori standard della categoria Indicatori di trend. Creeremo template pronti all'uso per utilizzare gli indicatori negli EA - dichiarazione e impostazione dei parametri, inizializzazione e deinizializzazione degli indicatori, nonché ricezione dei dati e segnali dai buffer degli indicatori negli EA.
Come creare un indicatore Donchian Channel personalizzato utilizzando MQL5 Come creare un indicatore Donchian Channel personalizzato utilizzando MQL5
Esistono molti strumenti tecnici che possono essere utilizzati per visualizzare un canale che circonda i prezzi, uno di questi strumenti è l'indicatore Donchian Channel. In questo articolo impareremo come creare l'indicatore Donchian Channel e come fare trading attraverso un EA.
Template pronti per includere indicatori negli Expert Advisor (Parte 2): Indicatori di Volume e Bill Williams Template pronti per includere indicatori negli Expert Advisor (Parte 2): Indicatori di Volume e Bill Williams
In questo articolo esamineremo gli indicatori standard della categoria Volume e gli indicatori di Bill Williams. Creeremo template pronti all'uso per utilizzare gli indicatori negli EA - dichiarazione e impostazione dei parametri, inizializzazione e deinizializzazione degli indicatori, nonché ricezione dei dati e segnali dai buffer degli indicatori negli EA.