Model Çalıştırma

Bir ONNX modelinin MQL5'te çalıştırılması için şu 3 adımın tamamlanması gerekir:

  1. Modeli, OnnxCreate fonksiyonunu kullanarak bir *.onnx dosyasından veya OnnxCreateFromBuffer fonksiyonunu kullanarak bir diziden yükleyin.
  2. OnnxSetInputShape ve OnnxSetOutputShape fonksiyonlarını kullanarak girdi ve çıktı verilerinin şekillerini belirtin.
  3. Modeli, ilgili girdi ve çıktı parametrelerini ileterek OnnxRun fonksiyonunu kullanarak çalıştırın.
  4. Gerektiğinde OnnxRelease fonksiyonunu kullanarak modelin çalışmasını sonlandırabilirsiniz.

 

Bir ONNX modeli oluştururken, https://github.com/microsoft/onnxruntime/blob/rel-1.14.0/docs/OperatorKernels.md adresinde açıklanan mevcut sınırları ve kısıtlamaları göz önünde bulundurmalısınız.

Bu tür kısıtlamaların bazı örnekleri aşağıda gösterilmektedir:

İşlem

Desteklenen veri türleri

ReduceSum

tensor(double), tensor(float), tensor(int32), tensor(int64)

Mul

tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)

 

Aşağıda, herkese açık ONNX.Price.Prediction projesinden bir MQL5 kodu örneği bulunmaktadır.

const long   ExtOutputShape[] = {1,1};    // modelin çıktı şekli
const long   ExtInputShape [] = {1,10,4}; // modelin girdi şekli
#resource "Python/model.onnx" as uchar ExtModel[]// kaynak olarak model
//+------------------------------------------------------------------+
//| Komut dosyası başlatma fonksiyonu                                |
//+------------------------------------------------------------------+
int OnStart(void)
  {
   matrix rates;
//--- 10 çubuk al
   if(!rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,2,10))
      return(-1);
//--- girdi olarak OHLC vektörü kümesi kullan
   matrix x_norm=rates.Transpose();
   vector m=x_norm.Mean(0);               
   vector s=x_norm.Std(0);
   matrix mm(10,4);
   matrix ms(10,4);
//--- normalleştirme matrislerini doldur
   for(int i=0i<10i++)
     {
      mm.Row(m,i);
      ms.Row(s,i);
     }
//--- girdi verilerini normalleştir
   x_norm-=mm;
   x_norm/=ms;
//--- modeli oluştur
   long handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);
//--- girdi verilerinin şeklini belirt
   if(!OnnxSetInputShape(handle,0,ExtInputShape))
     {
      Print("OnnxSetInputShape failed, error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//--- çıktı verilerinin şeklini belirt
   if(!OnnxSetOutputShape(handle,0,ExtOutputShape))
     {
      Print("OnnxSetOutputShape failed, error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//--- normalleştirilmiş girdi verilerini float türüne dönüştür
   matrixf x_normf;
   x_normf.Assign(x_norm);
//--- modelin çıktı verilerini (yani fiyat öngörüsünü) buradan al
   vectorf y_norm(1);
//--- modeli çalıştır
   if(!OnnxRun(handle,ONNX_DEBUG_LOGS | ONNX_NO_CONVERSION,x_normf,y_norm))
     {
      Print("OnnxRun failed, error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//--- modelin çıktı değerini günlüğe yazdır
   Print(y_norm);
//--- öngörülen fiyatı elde etmek için ters dönüşümü yap
   double y_pred=y_norm[0]*s[3]+m[3];
   Print("price predicted:",y_pred);
//--- çalışmayı tamamla
   OnnxRelease(handle);
   return(0);
  }

Komut dosyası çalışması örneği:

ONNXCreating and using per session threadpools since use_per_session_threads_ is true
ONNXDynamic block base set to 0
ONNXInitializing session.
ONNXAdding default CPU execution provider.
ONNXTotal shared scalar initializer count0
ONNXTotal fused reshape node count0
ONNXTotal shared scalar initializer count0
ONNXTotal fused reshape node count0
ONNXUse DeviceBasedPartition as default
ONNXSaving initialized tensors.
ONNXDone saving initialized tensors
ONNXSession successfully initialized.
[0.28188983]
predicted 1.0559258806393044

MetaTrader 5 terminali, hesaplamalar için en uygun yürütücüyü seçti - ONNX Runtime Execution Provider. Bu örnekte, model CPU üzerinde yürütüldü.

Önceki 10 çubuğun değerlerine dayalı olarak yapılan başarılı Kapanış fiyatı öngörülerinin yüzdesini hesaplamak için komut dosyasını düzenleyelim.

#resource "Python/model.onnx" as uchar ExtModel[]// kaynak olarak model
 
#define TESTS 10000  // test veri kümesi sayısı
//+------------------------------------------------------------------+
//| Komut dosyası başlatma fonksiyonu                                |
//+------------------------------------------------------------------+
int OnStart()
  {
//--- modeli oluştur
   long session_handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);
   if(session_handle==INVALID_HANDLE)
     {
      Print("Cannot create model. Hata ",GetLastError());
      return(-1);
     }
 
//--- model için girdi tensörü büyüklüğü tanımlanmadığından, açıkça belirtilmelidir
//--- birinci indeks grup büyüklüğüdür, ikinci indeks seri büyüklüğüdür, üçüncü indeks ise seri (OHLC) sayısıdır
   const long input_shape[]={1,10,4};
   if(!OnnxSetInputShape(session_handle,0,input_shape))
     {
      Print("OnnxSetInputShape error ",GetLastError());
      return(-2);
     }
 
//--- model için çıktı tensörü büyüklüğü tanımlanmadığından, açıkça belirtilmelidir
//--- birinci indeks grup büyüklüğüdür, girdi tensöründeki grup büyüklüğüyle eşleşmelidir
//--- ikinci indeks öngörülen fiyatların sayısıdır (burada sadece Kapanış fiyatı öngörülmektedir)
   const long output_shape[]={1,1};
   if(!OnnxSetOutputShape(session_handle,0,output_shape))
     {
      Print("OnnxSetOutputShape error ",GetLastError());
      return(-3);
     }
//--- testleri çalıştır
   vector closes(TESTS);      // kontrol fiyatlarını depolamak için vektör
   vector predicts(TESTS);    // elde edilen öngörüleri depolamak için vektör
   vector prev_closes(TESTS); // önceki fiyatları depolamak için vektör
 
   matrix rates;              // OHLC serilerini almak için matris
   matrix splitted[2];        // serileri test ve kontrole bölmek için iki alt matris
   ulong  parts[]={10,1};     // bölünmüş alt matrislerin büyüklükleri
 
//--- önceki çubuktan başla
   for(int i=1i<=TESTSi++)
     {
      //--- 11 çubuk al
      rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,i,11);
      //--- matrisi test ve kontrole böl
      rates.Vsplit(parts,splitted);
      //--- kontrol matrisinden Kapanış fiyatını al
      closes[i-1]=splitted[1][3][0];
      //--- test edilen serideki son Kapanış fiyatı
      prev_closes[i-1]=splitted[0][3][9];
 
      //--- 10 çubukluk test matrisini teste gönder
      predicts[i-1]=PricePredictionTest(session_handle,splitted[0]);
      //--- çalışma zamanı hatası
      if(predicts[i-1]<=0)
        {
         OnnxRelease(session_handle);
         return(-4);
        }
     }
//--- çalışmayı tamamla
   OnnxRelease(session_handle);
//--- fiyat hareketinin doğru öngörülüp öngörülmediğini değerlendir
   int    right_directions=0;
   vector delta_predicts=prev_closes-predicts;
   vector delta_actuals=prev_closes-closes;
 
   for(int i=0i<TESTSi++)
      if((delta_predicts[i]>0 && delta_actuals[i]>0) || (delta_predicts[i]<0 && delta_actuals[i]<0))
         right_directions++;
   PrintFormat("right direction predictions = %.2f%%",(right_directions*100.0)/double(TESTS));
//--- 
   return(0);
  }
//+------------------------------------------------------------------+
//|  Verileri hazırla ve modeli çalıştır                             |
//+------------------------------------------------------------------+
double PricePredictionTest(const long session_handle,matrixrates)
  {
   static matrixf input_data(10,4); //dönüştürülmüş girdi için matris
   static vectorf output_data(1);   // sonucu almak için vektör
   static matrix mm(10,4);          // Mean yatay vektörlerin matrisi
   static matrix ms(10,4);          // Std yatay vektörlerin matrisi
 
//--- modelin girdisi OHLC dikey vektörler kümesi olmalıdır
   matrix x_norm=rates.Transpose();
//--- fiyatları normalleştir
   vector m=x_norm.Mean(0);
   vector s=x_norm.Std(0);
   for(int i=0i<10i++)
     {
      mm.Row(m,i);
      ms.Row(s,i);
     }
   x_norm-=mm;
   x_norm/=ms;
 
//--- modeli çalıştır
   input_data.Assign(x_norm);
   if(!OnnxRun(session_handle,ONNX_DEBUG_LOGS,input_data,output_data))
     {
      Print("OnnxRun error ",GetLastError());
      return(0);
     }
//--- fiyatı çıktı değerinden normalleştirilmemiş hale getir
   double y_pred=output_data[0]*s[3]+m[3];
 
   return(y_pred);
  }

Komut dosyasını çalıştıralım: öngörü doğruluğu yaklaşık %51'dir.

ONNX: Creating and using per session threadpools since use_per_session_threads_ is true
ONNX: Dynamic block base set to 0
ONNX: Initializing session.
ONNX: Adding default CPU execution provider.
ONNX: Total shared scalar initializer count: 0
ONNX: Total fused reshape node count: 0
ONNX: Total shared scalar initializer count: 0
ONNX: Total fused reshape node count: 0
ONNX: Use DeviceBasedPartition as default
ONNX: Saving initialized tensors.
ONNX: Done saving initialized tensors
ONNX: Session successfully initialized.
right direction predictions = 51.34 %