//+------------------------------------------------------------------+ //| GPT_test.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property script_show_inputs //+------------------------------------------------------------------+ //| Константы | //+------------------------------------------------------------------+ #define BarsInHistory 40 //+------------------------------------------------------------------+ //| Внешние параметры для работы скрипта | //+------------------------------------------------------------------+ input string StudyFileName = "study_data.csv"; // Имя файла с обучающей выборкой input string OutputFileName = "loss_study_gpt.csv";// Имя файла для записи динамики ошибки input int BarsToLine = 40; // Количество исторических баров в одном паттерне input int NeuronsToBar = 4; // Количество нейронов входного слоя на 1 бар input bool UseOpenCL = false; // Использовать OpenCL input int BatchSize = 10000; // Размер пакета для обновления матрицы весов input double LearningRate = 0.0001; // Коэффициент обучения input int HiddenLayers = 3; // Количество скрытых слоёв input int HiddenLayer = 40; // Количество нейронов в одном скрытом слое input int Epochs = 1000; // Количество циклов обновления матрицы весов //+------------------------------------------------------------------+ //| Подключаем библиотеку нейронной сети | //+------------------------------------------------------------------+ #include CNet *net; //+------------------------------------------------------------------+ //| Начало программы скрипта | //+------------------------------------------------------------------+ void OnStart() { //--- CArrayObj *layers = new CArrayObj(); if(CheckPointer(layers) == POINTER_INVALID) { PrintFormat("Error of create CArrayObj: %d", GetLastError()); return; } //--- Слой исходных данных CLayerDescription *descr = new CLayerDescription(); if(CheckPointer(descr) == POINTER_INVALID) { PrintFormat("Error of create CLayerDescription: %d", GetLastError()); delete layers; return; } descr.type = defNeuronBase; int prev_count = descr.count = NeuronsToBar * 5; descr.window = 0; descr.activation = ACT_None; descr.optimization = None; if(!layers.Add(descr)) { PrintFormat("Error of add layer: %d", GetLastError()); delete descr; delete layers; return; } //--- Блок GPT descr = new CLayerDescription(); if(CheckPointer(descr) == POINTER_INVALID) { PrintFormat("Error of create CLayerDescription: %d", GetLastError()); delete layers; return; } descr.type = defNeuronGPT; descr.count = BarsToLine; descr.window = prev_count; descr.window_out = NeuronsToBar; descr.step = 8; descr.layers = 1; descr.activation = ACT_None; descr.optimization = Adam; descr.activation_params[0] = 1; if(!layers.Add(descr)) { PrintFormat("Error of add layer: %d", GetLastError()); delete layers; delete descr; return; } //--- Скрытые слои descr = new CLayerDescription(); if(CheckPointer(descr) == POINTER_INVALID) { PrintFormat("Error of create CLayerDescription: %d", GetLastError()); delete layers; return; } descr.type = defNeuronBase; descr.count = HiddenLayer; descr.activation = ACT_SWISH; descr.optimization = Adam; descr.activation_params[0] = 1; for(int i = 0; i < HiddenLayers; i++) { if(!layers.Add(descr)) { PrintFormat("Error of add layer: %d", GetLastError()); delete layers; delete descr; return; } } //--- Слой результатов descr = new CLayerDescription(); if(CheckPointer(descr) == POINTER_INVALID) { PrintFormat("Error of create CLayerDescription: %d", GetLastError()); delete layers; return; } descr.type = defNeuronBase; descr.count = 2; descr.activation = ACT_LINE; descr.optimization = Adam; descr.activation_params[0] = 1; if(!layers.Add(descr)) { PrintFormat("Error of add layer: %d", GetLastError()); delete layers; delete descr; return; } //--- Инициализация модели нейронной сети net = new CNet(); if(CheckPointer(net) == POINTER_INVALID) { PrintFormat("Error of create Net: %d", GetLastError()); return; } //--- if(!net.Create(layers, LearningRate, 0.9, 0.999, ENUM_LOSS_MSE, 0, 0)) { PrintFormat("Error of init Net: %d", GetLastError()); delete layers; delete net; return; } delete layers; net.UseOpenCL(UseOpenCL); net.LossSmoothFactor(BatchSize); //--- Блок загрузки обучающей выборки CArrayObj *data = new CArrayObj(); if(CheckPointer(data) == POINTER_INVALID) { PrintFormat("Error of create Historical data array: %d", GetLastError()); delete net; return; } //--- CArrayObj *result = new CArrayObj(); if(CheckPointer(result) == POINTER_INVALID) { PrintFormat("Error of create Target data array: %d", GetLastError()); delete net; delete data; return; } CBufferDouble *pattern; //--- CBufferDouble *target; //--- Открываем файл и считываем исходных данных int handle = FileOpen(StudyFileName, FILE_READ | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ",", CP_UTF8); if(handle == INVALID_HANDLE) { PrintFormat("Error of open study data file: %d", GetLastError()); delete net; delete data; delete result; return; } while(!FileIsEnding(handle) && !IsStopped()) { pattern = new CBufferDouble(); if(CheckPointer(pattern) == POINTER_INVALID) { PrintFormat("Error of create Pattern data array: %d", GetLastError()); delete net; delete data; delete result; return; } target = new CBufferDouble(); if(CheckPointer(target) == POINTER_INVALID) { PrintFormat("Error of create Pattern Target array: %d", GetLastError()); delete net; delete data; delete result; delete pattern; return; } for(int i = 0; i < NeuronsToBar * BarsInHistory; i++) { if(!pattern.Add(FileReadNumber(handle))) { PrintFormat("Error of read study data from file: %d", GetLastError()); delete net; delete data; delete result; delete pattern; delete target; return; } } pattern.DeleteRange(0, (BarsInHistory - 5)*NeuronsToBar - 1); for(int i = 0; i < 2; i++) if(!target.Add(FileReadNumber(handle))) { PrintFormat("Error of read study data from file: %d", GetLastError()); delete net; delete data; delete result; delete pattern; delete target; return; } if(!data.Add(pattern)) { PrintFormat("Error of add study data to array: %d", GetLastError()); delete net; delete data; delete result; delete pattern; delete target; return; } if(!result.Add(target)) { PrintFormat("Error of add study data to array: %d", GetLastError()); delete net; delete data; delete result; delete pattern; delete target; return; } int total = data.Total(); Comment(StringFormat("Read %d patterns", total)); } FileClose(handle); //--- Блок обучения модели const int patterns = data.Total(); CArrayDouble *loss = new CArrayDouble(); if(CheckPointer(loss) == POINTER_INVALID) { PrintFormat("Error of create loss array: %d", GetLastError()); delete net; delete data; delete result; delete pattern; delete target; return; } int i = -1; int epoch = 0; while(epoch < Epochs && !IsStopped()) { for(int k = 0; k < patterns && !IsStopped(); k++) { pattern = data.At(k); target = result.At(k); if(CheckPointer(pattern) == POINTER_INVALID || CheckPointer(target) == POINTER_INVALID) { i--; continue; } if(!net.FeedForward(pattern)) { PrintFormat("Error in FeedForward: %d", GetLastError()); delete net; delete data; delete result; delete loss; return; } if(!net.Backpropagation(target)) { PrintFormat("Error in Backpropagation: %d", GetLastError()); delete net; delete data; delete result; delete loss; return; } i++; if(i >= BatchSize) { if(!net.UpdateWeights(BatchSize)) continue; i = 0; if(!loss.Add(net.GetRecentAverageLoss())) { PrintFormat("Error of add loss to array: %d", GetLastError()); delete net; delete data; delete result; delete loss; return; } Comment(StringFormat("Studied %d epoch, error %.5f", epoch, net.GetRecentAverageLoss())); epoch++; } } } //--- Сохраняем результаты обучения handle = FileOpen(OutputFileName, FILE_WRITE | FILE_CSV | FILE_ANSI, ",", CP_UTF8); if(handle == INVALID_HANDLE) { PrintFormat("Error of open loss file: %d", GetLastError()); delete net; delete data; delete result; delete loss; return; } for(i = 0; i < loss.Total(); i++) if(FileWrite(handle, loss.At(i))<=0) break; FileClose(handle); PrintFormat("The dynamics of the error change is saved to a file %s\\%s", TerminalInfoString(TERMINAL_DATA_PATH), OutputFileName); net.Save("Study.net"); //--- Очистка памяти delete net; delete loss; delete data; delete result; Comment(""); } //+------------------------------------------------------------------+