Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 2952

 
Aleksey Nikolayev #:
В справке по ONNX нет про функции OnnxSetInputShape() и OnnxSetOutputShape(). Не очень понятно что они должны делать.


Эти методы устанавливают размерность входных и выходных данных модели. Сегодня добавим в справку

//+------------------------------------------------------------------+
//|                                        ONNX.Price.Prediction.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

const long  ExtOutputShape[] = {1,1};
const long  ExtInputShape [] = {1,10,4};
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
int OnStart(void)
  {
   matrix rates;
//--- получаем 10 баров
   if(!rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,2,10))
      return(-1);
//--- на вход модели должен подаваться набор вертикальных векторов OHLC
   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);

   for(int i=0; i<10; i++)
     {
      mm.Row(m,i);
      ms.Row(s,i);
     }

   x_norm-=mm;
   x_norm/=ms;
//--- создаём модель
   long handle=OnnxCreateFromBuffer(model,ONNX_DEBUG_LOGS);

   if(!OnnxSetInputShape(handle,0,ExtInputShape))
     {
      Print("failed, OnnxSetInputShape error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }

   if(!OnnxSetOutputShape(handle,0,ExtOutputShape))
     {
      Print("failed, OnnxSetOutputShape error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//--- запускаем модель
   matrixf x_normf;
   vectorf y_norm(1);

   x_normf.Assign(x_norm);
   if(!OnnxRun(handle,ONNX_DEBUG_LOGS | ONNX_NO_CONVERSION,x_normf,y_norm))
     {
      Print("failed, OnnxRun error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }

   Print(y_norm);
//--- обратно разнормируем цену из выходного значения
   double y_pred=y_norm[0]*s[3]+m[3];

   Print("predicted ",y_pred);
//--- завершили работу
   OnnxRelease(handle);
   return(0);
  }
//+------------------------------------------------------------------+
 
mytarmailS #:
Как понять? 
На компьютере я в бане на 10 лет,  а с телефона вне бана)) 

У вас наверное "фейковый бан по IP":

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Вопрос к администрации сайта mql5.com

Sergey Golubev, 2022.12.16 17:22

Если бан, а вы можете делать тут посты - то это "фейковый бан по IP".
У вас наверное, динамическое IP, и оно случайно "попало" на когда-то у кого-то забаненное.
Я когда "ловлю" такой бан -  просто выключаю компьютер, выключаю роутер, потом включаю роутер и включаю компьютер.
В результате мое IP меняется (а у меня оно тоже динамическое), и надпись про 10 лет исчезает.

...

 

Не получается вывод в МТ5 из ONNX-модели, обученной в LightGBM. Ошибки 5808 и 5805 при установке формы параметров. Но проблема вроде уже с определением размерностей параметров - получаются отрицательные значения (выделено в коде). Может просто чего-нибудь напутал. В питоне 3.10 всё вроде нормально.

Вывод MQL5:

void OnStart()
  {
   long h = OnnxCreate("model.onnx", FILE_COMMON);
   
   //Print(OnnxGetInputCount(h));
   //Print(OnnxGetOutputCount(h));
   //Print(OnnxGetInputName(h, 0));
   //Print(OnnxGetOutputName(h, 0));
   OnnxTypeInfo otype;
   OnnxGetInputTypeInfo(h, 0, otype);
   ArrayPrint(otype.dimensions);                   // -1 8
   //Print(otype.element_type, " ", otype.type);
   OnnxGetOutputTypeInfo(h, 0, otype);
   ArrayPrint(otype.dimensions);                   // -1 1
   //Print(otype.element_type, " ", otype.type);
   
   matrix mx={{8.32520000e+00, 4.10000000e+01, 6.98412698e+00, 1.02380952e+00,
               3.22000000e+02, 2.55555556e+00, 3.78800000e+01,-1.22230000e+02},
              {8.30140000e+00, 2.10000000e+01, 6.23813708e+00, 9.71880492e-01,
               2.40100000e+03, 2.10984183e+00, 3.78600000e+01,-1.22220000e+02},
              {7.25740000e+00, 5.20000000e+01, 8.28813559e+00, 1.07344633e+00,
               4.96000000e+02, 2.80225989e+00, 3.78500000e+01,-1.22240000e+02},
              {5.64310000e+00, 5.20000000e+01, 5.81735160e+00, 1.07305936e+00,
               5.58000000e+02, 2.54794521e+00, 3.78500000e+01,-1.22250000e+02},
              {3.84620000e+00, 5.20000000e+01, 6.28185328e+00, 1.08108108e+00,
               5.65000000e+02, 2.18146718e+00, 3.78500000e+01,-1.22250000e+02}};
   matrix my={{0.0},{0.0},{0.0},{0.0},{0.0}};   
   
   const long  ExtInputShape [] = {1,5,8};
   const long  ExtOutputShape[] = {1,5};
   Print(OnnxSetInputShape(h,0,ExtInputShape));
   Print(GetLastError());                            // 5808
   ResetLastError();
   Print(OnnxSetOutputShape(h,0,ExtOutputShape));
   Print(GetLastError());                            // 5805
   
   OnnxRun(h, ONNX_DEBUG_LOGS | ONNX_NO_CONVERSION, mx, my);
   //Print(mx);
   //Print(my);
   OnnxRelease(h);
  }

Обучение в питоне:

from lightgbm import LGBMRegressor
from sklearn.datasets import fetch_california_housing
import onnxmltools
from onnxconverter_common import *

housing = fetch_california_housing()
X, Y = housing.data, housing.target

model = LGBMRegressor()
model.fit(X, Y)
Yreal, Ypredict = Y[:5], model.predict(X[:5])
print(Yreal)
print(Ypredict)

initial_type = [('input', FloatTensorType([None, len(X[0])]))]
onnx_model = onnxmltools.convert_lightgbm(model, name='LightGBM', initial_types=initial_type)
onnxmltools.utils.save_model(onnx_model, 'model.onnx')

Вывод в питоне:

import numpy as np
import onnxruntime as ort
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()
X, Y = housing.data, housing.target
Xtest, Yreal = X[:5], Y[:5]

sess = ort.InferenceSession("model.onnx", providers=ort.get_available_providers())
input_name = sess.get_inputs()[0].name
Ypredict = sess.run(None, {input_name: Xtest.astype(np.float32)})[0]

print(Xtest)
print(Yreal)
print(Ypredict)
 
Похоже, переходить на питон рановато. Лучше освоить CLI версию LightGBM и сохранять модели в формате if-else на C. Неуниверсально, зато дёшево и сердито)
 
Вспомнилось обсуждение цикличных признаков, вроде времени суток. ИМХО, надо переводить их в обычные, просто подбирая точку для начала отсчёта, в которой происходит наиболее сильная смена возможной закономерности. Можно пользоваться либо соображениями о рынке (расписание сессии, в данном случае), либо чем-то вроде этого, либо обучать древесную модель и брать точку первого сплита по этому признаку.
Один из методов псевдо-адаптации.
Один из методов псевдо-адаптации.
  • 2023.01.30
  • www.mql5.com
Любой скальпер знает, что круглосуточная торговля - глупость. Есть интервалы, где достигается высокая и стабильная прибыльность, поэтому различными способами находят эти интервалы. Например, при
 
Aleksey Nikolayev #:
Вспомнилось обсуждение цикличных признаков, вроде времени суток. ИМХО, надо переводить их в обычные, просто подбирая точку для начала отсчёта, в которой происходит наиболее сильная смена возможной закономерности. Можно пользоваться либо соображениями о рынке (расписание сессии, в данном случае), либо чем-то вроде этого, либо обучать древесную модель и брать точку первого сплита по этому признаку.
Можно взять волатильность вместо приращений, она точно отражает рыночные циклы. И прогнать через 2 модели, одна из которых фильтрует плохие случаи (как в последней статье делал). Результаты иногда приличные, нужно несколько раз попереобучать. Потенциально подобный подход даст больше, чем bestinterval.

ЗЫ onnx на маке завелся из примера, что круто, бустинги не проверял еще 
Там на вход точно матрицу 2-мерную нужно, как в вашем примере? Логичнее одномерный массив с признаками, кажется. Может ругаться на неправильную форму матрицы. Например, вместо одномерного нужно давать 2-мерный, где каждая запись во 2-м измерении, т.е вложенные массивы, содержащие по 1 значению.

Ну и для катбуста есть пример перевода в mql из питона, lgbm вроде ничем не лучше 
 
Maxim Dmitrievsky #:
ЗЫ onnx на маке завелся из примера, что круто, бустинги не проверял еще 
Там на вход точно матрицу 2-мерную нужно, как в вашем примере? Логичнее одномерный массив с признаками, кажется. Может ругаться на неправильную форму матрицы. Например, вместо одномерного нужно давать 2-мерный, где каждая запись во 2-м измерении, т.е вложенные массивы, содержащие по 1 значению.

Ну, при обучении в питоне тестил модель на первых пяти строках датасета. Потом при запуске ONNX в питоне тоже проверил вывод на тех же первых пяти строках. Как ни крути, всё же это матрица. В МТ5 варианте просто скопипастил эти же пять строк в виде матрицы. Да и в примере Рената на вход подаётся тоже матрица из десяти строк и четырёх столбцов.

Проблема там, ИМХО, уже при загрузке модели, поскольку выдаются отрицательные числа в размерностях. Кстати, надо посмотреть что будет выдавать в примере Рената.

OnnxTypeInfo otype;
OnnxGetInputTypeInfo(h, 0, otype);
ArrayPrint(otype.dimensions);                   // -1 8
OnnxGetOutputTypeInfo(h, 0, otype);
ArrayPrint(otype.dimensions);                   // -1 1
 
Maxim Dmitrievsky #:
Можно взять волатильность вместо приращений, она точно отражает рыночные циклы. И прогнать через 2 модели, одна из которых фильтрует плохие случаи (как в последней статье делал). Результаты иногда приличные, нужно несколько раз попереобучать. Потенциально подобный подход даст больше, чем bestinterval.

Не, я просто про общий подход к цикличным переменным. Их надо "разрезать" для превращения в обычные. Но можно же делать это по разному, не обязательно в формальном нуле.

Помимо суточного времени, циклические переменные возникают, например, когда ищутся веса для портфеля из двух символов.

 
Aleksey Nikolayev #:
Похоже, переходить на питон рановато. Лучше освоить CLI версию LightGBM и сохранять модели в формате if-else на C. Неуниверсально, зато дёшево и сердито)
Есть ещё пакет  intrees, там можно правила тянуть с многих деревняных моделей.
Форесты, бусты... 
 
Maxim Dmitrievsky #:
Ну и для катбуста есть пример перевода в mql из питона, lgbm вроде ничем не лучше 

Есть лёгкие сомнения в будущем Яндекса)

Ещё, по идее, lgbm должен лучше интегрироваться с сишарпом и прочими поделками микрософта, если вдруг это станет актуальным)

Причина обращения: