713 lines
No EOL
63 KiB
MQL5
713 lines
No EOL
63 KiB
MQL5
//============================================================================================= MQL5 ===
|
|
// LibreFEI v1.006 (MQL5)
|
|
// Главный модуль обработки событий
|
|
// Librecoin(c)2014-2017
|
|
//============================================================================================= MQL5 ===
|
|
// REVIEWS
|
|
//------------------------------------------------------------------------------------------------------
|
|
// Fourier Extrapolator Adaptive - экстраполятор фурье творческая переработка.
|
|
//============================================================================================= MQL5 ===
|
|
// IDEAS
|
|
//------------------------------------------------------------------------------------------------------
|
|
// 12.12.2017 Идея: расчетную часть выполнить с использованием OpenCL
|
|
//============================================================================================= MQL5 ===
|
|
// PROPERTY
|
|
//------------------------------------------------------------------------------------------------------
|
|
#property strict
|
|
#define ver "1.006"
|
|
#property copyright "Librecoin(c)2014-2017, gpwr(c)2008-2010"
|
|
#property link "https://www.mql5.com/ru/users/kirillovyv"
|
|
#property description "**************************************************"
|
|
#property description " Indicator LibreFEI v"+ver+" Lite (MQL5)"
|
|
#property description " Extrapolator by trigonometric (multitone) model"
|
|
#property description " From Russia with Love! :-)"
|
|
#property description " https://www.mql5.com/ru/users/kirillovyv"
|
|
#property description " Based from: gpwr(c)2008-2010, neoclassic(c)2009"
|
|
#property description "**************************************************"
|
|
#property version ver
|
|
const string vers = "LibreFEI v"+ver; //Version
|
|
//----- indicator property
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 4
|
|
#property indicator_plots 2
|
|
#resource "Kernels/Prog01_02B.cl" as string CL_Source//Код кернел-программ можно подключать как ресурс
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// INTERFACE
|
|
//------------------------------------------------------------------------------------------------------
|
|
input int Npast = 650; //Past bars, to which trigonometric series is fitted
|
|
input int Nfut = 20; //Predicted future bars
|
|
input int Nharm = 9; //Min Narmonics in model
|
|
input double FreqTOL = 0.0000001; //Tolerance of frequency calculations
|
|
input int StartBar = 15; //С какого бара начинаем
|
|
input int MSTimerSet = 500; //Установка таймера xxx миллисекунд
|
|
input int nTickDelay = 5; //Интервал пропуска тиков для тестирования
|
|
input ulong IterLimit = 60; //Iteration limit для Freq
|
|
input bool CommentOn = false; //Вывод комментариев на экран
|
|
input bool PrintOn = false; //Печать комментариев в журнал
|
|
input bool OCLSelector = true; //Использовать OpenCL
|
|
//============================================================================================= MQL5 === OCLSelector
|
|
// Global variable definition
|
|
//------------------------------------------------------------------------------------------------------
|
|
bool TimeInterrupt;
|
|
int nTickSumm;
|
|
//----- indicator buffers
|
|
double pv[]; //0 Отображаемый буфер истории PAST
|
|
double fv[]; //1 Отображаемый буфер прогноза FUTURE
|
|
double pc[]; //2 Расчетный буфер истории PAST
|
|
double fc[]; //3 Расчетный буфер прогноза FUTURE
|
|
//----- Буфер расчетного параметра
|
|
double xc[]; //Буфер расчетного параметра (Close())
|
|
//----- Включатель отладочной печати
|
|
bool PrintDebugSelector=true;
|
|
//----- Хендлы для объектов OpenCL
|
|
int h_CL_Context=INVALID_HANDLE; //Хендл контекста
|
|
int h_CL_Program=INVALID_HANDLE; //Хендл программы
|
|
int h_CL_Kernel=INVALID_HANDLE; //Хендл кернела
|
|
int h_CL_Buffers[]; //Хендлы буферов
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// OnInit() - Custom indicator initialization function
|
|
//------------------------------------------------------------------------------------------------------
|
|
int OnInit()
|
|
{
|
|
//----- initialize global variables
|
|
TimeInterrupt=true;
|
|
nTickSumm=0;
|
|
//----- indicator parametrs
|
|
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
|
|
IndicatorSetString(INDICATOR_SHORTNAME,"LibreFEI");
|
|
//----- indicator buffers mapping
|
|
//Прошлое - буфер отображения PAST
|
|
ArraySetAsSeries(pv,true);
|
|
ArrayInitialize(pv,EMPTY_VALUE);
|
|
SetIndexBuffer(0,pv,INDICATOR_DATA);
|
|
PlotIndexSetString(0,PLOT_LABEL,"Past");
|
|
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
|
|
PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
|
|
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,2);
|
|
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrBlue);
|
|
//Будущее - буфер отображения FUTURE
|
|
ArraySetAsSeries(fv,true);
|
|
ArrayInitialize(fv,EMPTY_VALUE);
|
|
SetIndexBuffer(1,fv,INDICATOR_DATA);
|
|
PlotIndexSetString(1,PLOT_LABEL,"Future");
|
|
PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);
|
|
PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
|
|
PlotIndexSetInteger(1,PLOT_LINE_WIDTH,2);
|
|
PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrRed);
|
|
PlotIndexSetInteger(1,PLOT_SHIFT,Nfut); //future data vector i=0..Nfut; Nfut corresponds to bar=StartBar
|
|
//Прошлое - буфер расчета PAST - разобраться с AsSeries(), сделать false
|
|
ArraySetAsSeries(pc,false);
|
|
ArrayInitialize(pc,EMPTY_VALUE);
|
|
SetIndexBuffer(2,pc,INDICATOR_CALCULATIONS);
|
|
//Будущее - буфер расчета FUTURE
|
|
ArraySetAsSeries(fc,true);//false
|
|
ArrayInitialize(fc,EMPTY_VALUE);
|
|
SetIndexBuffer(3,fc,INDICATOR_CALCULATIONS);
|
|
//Буфер расчетного параметра
|
|
ArraySetAsSeries(xc,false);//Всегда!
|
|
ArrayResize(xc,Npast+1);
|
|
//----- Настройки таймера и глобальных счетчиков
|
|
{if(!MQLInfoInteger(MQL_TESTER))//Не тестирование
|
|
{
|
|
int err=-1;
|
|
int count=50;
|
|
{while((err!=0)&&(count>0))
|
|
{
|
|
ResetLastError();
|
|
EventSetMillisecondTimer(MSTimerSet); //Установка таймера XXX миллисекунд
|
|
err=GetLastError();
|
|
{if(err!=0)
|
|
{
|
|
Sleep(50);
|
|
}}//if(err!=0)
|
|
count--;
|
|
}}//while((err!=0)&&(count>0))
|
|
}}//if(!MQLInfoInteger(MQL_TESTER))
|
|
//----- Подготовительные операции OpenCL
|
|
{if(OCLSelector)
|
|
{
|
|
//----- Включатель отладочной печати
|
|
PrintDebugSelector=true;
|
|
//----- Хендлы для объектов OpenCL
|
|
h_CL_Context=INVALID_HANDLE; //Хендл контекста
|
|
h_CL_Program=INVALID_HANDLE; //Хендл программы
|
|
h_CL_Kernel=INVALID_HANDLE; //Хендл кернела
|
|
//----- Определение числа буферов под переменные
|
|
ArrayResize(h_CL_Buffers,5);//x,ipc,im,ic,is
|
|
ArrayFill(h_CL_Buffers,0,ArraySize(h_CL_Buffers),INVALID_HANDLE);
|
|
//----- Создание контекста (среды) для программы OpenCL (выбор девайса)
|
|
ResetLastError();
|
|
{if((h_CL_Context=CLContextCreate(CL_USE_ANY))==INVALID_HANDLE) //CL_USE_ANY - использовать любое доступное устройство с поддержкой OpenCL
|
|
{
|
|
Print("OpenCL not found, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL found, Хендл на контекст OpenCL:",h_CL_Context," Error:",GetLastError());
|
|
}}//if((h_CL_Context=CLContextCreate(CL_USE_ANY))==INVALID_HANDLE)
|
|
//----- Создание в контексте программы на основе кода в строке CL_Source
|
|
string BuildLog=""; //Лог компиляции
|
|
ResetLastError();
|
|
{if((h_CL_Program=CLProgramCreate(h_CL_Context,CL_Source,BuildLog))==INVALID_HANDLE)//В третьем параметре - лог компиляции
|
|
{
|
|
Print("OpenCL program create failed, error:",GetLastError()," BuildLog=",BuildLog);
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers,BuildLog,PrintDebugSelector);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL program create, Хендл программы OpenCL:",h_CL_Program," Error:",GetLastError());
|
|
}}//if((h_CL_Program=CLProgramCreate(h_CL_Context,CL_Source,BuildLog))==INVALID_HANDLE)
|
|
//----- Создание кернела для расчета значений функции от двух переменных
|
|
string CL_Kernel_Name="TrigFit_OCL"; //Задание имени кернела - задать вручную
|
|
ResetLastError();
|
|
{if((h_CL_Kernel=CLKernelCreate(h_CL_Program,CL_Kernel_Name))==INVALID_HANDLE) //Имя функции должно соответствовать имени в программной строке CL_Source
|
|
{
|
|
Print("OpenCL kernel create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL kernel create, Хендл кернела OpenCL:",h_CL_Kernel," Error:",GetLastError());
|
|
}}//if((h_CL_Kernel=CLKernelCreate(h_CL_Program,"Exch"))==INVALID_HANDLE)
|
|
//----- Создание буферов
|
|
//----- Создание буфера[0] OpenCL для значений x[]
|
|
ResetLastError();
|
|
{if((h_CL_Buffers[0]=CLBufferCreate(h_CL_Context,Npast*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)//__global double *x,
|
|
{
|
|
Print("OpenCL buffer create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL buffer create, Хендл буфера OpenCL:",h_CL_Buffers[0]," Error:",GetLastError());
|
|
}}//if((h_CL_Buffer=CLBufferCreate(h_CL_Context,ArraySize(x)*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
|
//----- Создание буфера[1] OpenCL для значений ipc[] - переделать, только при изменении размерности массива
|
|
ResetLastError();
|
|
{if((h_CL_Buffers[1]=CLBufferCreate(h_CL_Context,Npast*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)//__global double *ipc,
|
|
{
|
|
Print("OpenCL buffer create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL buffer create, Хендл буфера OpenCL:",h_CL_Buffers[1]," Error:",GetLastError());
|
|
}}//if((h_CL_Buffer=CLBufferCreate(h_CL_Context,ArraySize(x)*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
|
//----- Создание буфера[2] OpenCL для значений im[]
|
|
ResetLastError();
|
|
{if((h_CL_Buffers[2]=CLBufferCreate(h_CL_Context,sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)//__global double *m,
|
|
{
|
|
Print("OpenCL buffer create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL buffer create, Хендл буфера OpenCL:",h_CL_Buffers[2]," Error:",GetLastError());
|
|
}}//if((h_CL_Buffer=CLBufferCreate(h_CL_Context,ArraySize(x)*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
|
//----- Создание буфера[3] OpenCL для значений ic[]
|
|
ResetLastError();
|
|
{if((h_CL_Buffers[3]=CLBufferCreate(h_CL_Context,sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)//__global double *c,
|
|
{
|
|
Print("OpenCL buffer create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL buffer create, Хендл буфера OpenCL:",h_CL_Buffers[3]," Error:",GetLastError());
|
|
}}//if((h_CL_Buffer=CLBufferCreate(h_CL_Context,ArraySize(x)*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
|
//----- Создание буфера[4] OpenCL для значений is[]
|
|
ResetLastError();
|
|
{if((h_CL_Buffers[4]=CLBufferCreate(h_CL_Context,sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)//__global double *s,
|
|
{
|
|
Print("OpenCL buffer create failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return(INIT_FAILED);
|
|
}else{
|
|
Print("OpenCL buffer create, Хендл буфера OpenCL:",h_CL_Buffers[4]," Error:",GetLastError());
|
|
}}//if((h_CL_Buffer=CLBufferCreate(h_CL_Context,ArraySize(x)*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
|
}else{
|
|
|
|
}}//if(OCLSelector)
|
|
//----- Выход тут
|
|
return(INIT_SUCCEEDED);
|
|
}//OnInit()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// OnDeinit() - Custom indicator iteration function |
|
|
//------------------------------------------------------------------------------------------------------
|
|
void OnDeinit(const int reason){
|
|
Comment("");
|
|
return;
|
|
}//OnDeinit()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// OnTimer()
|
|
//------------------------------------------------------------------------------------------------------
|
|
void OnTimer(){
|
|
TimeInterrupt=true;
|
|
nTickSumm=0;
|
|
}//OnTimer()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// OnCalculate() - Custom indicator iteration function
|
|
//------------------------------------------------------------------------------------------------------
|
|
int OnCalculate(const int rates_total,
|
|
const int prev_calculated,
|
|
const datetime& time[],
|
|
const double& open[],
|
|
const double& high[],
|
|
const double& low[],
|
|
const double& close[],
|
|
const long& tick_volume[],
|
|
const long& volume[],
|
|
const int& spread[])
|
|
{
|
|
//----- Check for insufficient data
|
|
{if(rates_total<Npast+StartBar+1)
|
|
{
|
|
{if(PrintOn)
|
|
{
|
|
Print("Error: not enough bars in history!"
|
|
+" Total="+IntegerToString(rates_total)
|
|
+" needed="+IntegerToString(Npast+StartBar+1));
|
|
}}//if(PrintOn)
|
|
return(0);
|
|
}}//if(rates_total<Npast)
|
|
//----- Проверка необходимости пересчета по тикам
|
|
{if(MQLInfoInteger(MQL_TESTER))
|
|
{
|
|
nTickSumm++;
|
|
{if(MathMod(nTickSumm,nTickDelay)<1.0)
|
|
{
|
|
nTickSumm=0;
|
|
TimeInterrupt=true;
|
|
}}//if(MathMod(nTickSumm,7)<1.0)
|
|
}}//if(MQLInfoInteger(MQL_TESTER))
|
|
//----- Проверка необходимости пересчета по таймеру
|
|
{if(rates_total<=prev_calculated)//размер входных таймсерий меньше или равен, чем ранее обработано (обычно размер входных на предшествующем тике)
|
|
{//Изменений нет - проверяем таймер
|
|
{if(!TimeInterrupt)//если нет прерывания от msec таймера
|
|
{
|
|
return(rates_total); //Сваливаем, ибо нет изменений и прерывания таймера
|
|
}else{//есть прерывание таймера - сбрасываем и выполняем расчет
|
|
TimeInterrupt=false;
|
|
}}//if(!TimeInterrupt)
|
|
}}//if(rates_total<=prev_calculated)
|
|
//----- Определение серийности массивов данных
|
|
ArraySetAsSeries(open,true);
|
|
ArraySetAsSeries(close,true);
|
|
ArraySetAsSeries(high,true);
|
|
ArraySetAsSeries(low,true);
|
|
ArraySetAsSeries(spread,true);
|
|
//----- Заполнение исходного массива для расчета прогноза
|
|
{for(int i=0;i<Npast;i++)
|
|
{
|
|
xc[i]=close[i];
|
|
}}//for(int i=0;i<Npast;i++)
|
|
//----- Расчет индикаторных буферов
|
|
Calc_Fourier(xc,pc,fc,Npast,Nharm);
|
|
//----- Расчет и вывод индикаторных буферов и справочной информации
|
|
{if(CommentOn)
|
|
{
|
|
Comment( "LibreFEI"+" "+
|
|
string(TimeCurrent())+" "+
|
|
"ST="+IntegerToString(StartBar)+" "+
|
|
"NF="+IntegerToString(Nfut)+" "+
|
|
"NP="+IntegerToString(Npast)+" "+
|
|
"NH="+IntegerToString(Nharm)+" "
|
|
);
|
|
}}//if(CommentOn)
|
|
{if(PrintOn)
|
|
{
|
|
Print( string(TimeCurrent())+" "+
|
|
"NP="+IntegerToString(Npast)+" "+
|
|
"NH="+IntegerToString(Nharm)+" "
|
|
);
|
|
}}//if(PrintOn)
|
|
//----- Гасим индикацию
|
|
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_NONE); //pv Past View
|
|
PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_NONE); //fv Future View
|
|
PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_NONE); //pc Past Calculate
|
|
PlotIndexSetInteger(3,PLOT_DRAW_TYPE,DRAW_NONE); //fc Future Calculate
|
|
ArrayInitialize(pv,EMPTY_VALUE);
|
|
ArrayInitialize(fv,EMPTY_VALUE);
|
|
//----- Перекладка массивов для отображения
|
|
//ArrayCopy(pv,pc,0,0,Npast+StartBar+1); - Если один массив AsSeries, а второй нет, то разворачивает
|
|
{for(int i=0;i<=Npast+StartBar;i++)
|
|
{
|
|
pv[i]=pc[i];
|
|
}}//for(int i=0;i<=Npast+StartBar;i++)
|
|
{for(int i=0;i<=Nfut;i++)
|
|
{
|
|
fv[Nfut-i]=fc[i];
|
|
}}//for(int i=0;i<=Nfut;i++)
|
|
//----- Включаем индикацию
|
|
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE); //pv
|
|
PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE); //fv
|
|
PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_LINE); //pc
|
|
PlotIndexSetInteger(3,PLOT_DRAW_TYPE,DRAW_LINE); //fs
|
|
ChartRedraw(ChartID());
|
|
//-----
|
|
return(rates_total);
|
|
}//OnCalculate()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// Calc_Fourier() - Calc_Fourier
|
|
//------------------------------------------------------------------------------------------------------
|
|
void Calc_Fourier(double &x[],double &p[],double &f[],int iNpast,int iNharm){
|
|
//-----
|
|
//----- initialize indicator buffers to EMPTY_VALUE
|
|
ArrayInitialize(p,EMPTY_VALUE);
|
|
ArrayInitialize(f,EMPTY_VALUE);
|
|
//----- Find average of past values
|
|
double av=0.0;
|
|
//Заполнение исходного массива для расчета и накопление суммы для вычисления среднего
|
|
{for(int i=0;i<iNpast;i++)
|
|
{
|
|
av=av+x[i];
|
|
}}//for(int i=0;i<Npast;i++)
|
|
//Расчет среднего
|
|
av=av/iNpast;
|
|
//----- initialize model outputs
|
|
{for(int i=0;i<iNpast;i++)
|
|
{
|
|
p[i]=av; //Прошлое заполняем средним значением от [0] на максимальную глубину
|
|
}}//for(int i=0;i<iNpast;i++)
|
|
{for(int i=0;i<=Nfut;i++)
|
|
{
|
|
f[i]=av; //Будущее заполняем средним значением от [0] на глубину Nfut
|
|
}}//for(int i=0;i<iNpast;i++)
|
|
//----- fit trigonometric model and calculate predictions
|
|
double w,m,c,s;
|
|
{for(int harm=1;harm<=iNharm;harm++)//Nharmm - раз прогоняемся в цикле
|
|
{
|
|
Freq(x,p,iNpast,w,m,c,s);
|
|
double mcc=0.0;
|
|
double ss=0.0;
|
|
{for(int i=0;i<iNpast;i++)
|
|
{
|
|
mcc=m+c*MathCos(w*i);
|
|
ss=s*MathSin(w*i);
|
|
p[i]+=mcc+ss;
|
|
{if(i<=Nfut)
|
|
{
|
|
f[i]+=mcc-ss;
|
|
}}//if(i<=Nfut)
|
|
}}//for(int i=0;i<iNpast;i++)
|
|
}}//for(int harm=1;harm<=Nharmm;harm++)
|
|
return;
|
|
}//Calc_Fourier()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// Freq() - Quinn and Fernandes algorithm for finding frequency
|
|
//------------------------------------------------------------------------------------------------------
|
|
void Freq(double& x[],double& ipc[],int n,double& w,double& m,double& c,double& s)
|
|
{
|
|
double z[];
|
|
ArrayResize(z,n);
|
|
double alpha=0.0;
|
|
double beta=2.0;
|
|
z[0]=x[0]-ipc[0];
|
|
ulong IterCount=0;
|
|
{while((MathAbs(alpha-beta)>FreqTOL)&&(IterCount<IterLimit))
|
|
{
|
|
alpha=beta;
|
|
z[1]=x[1]-ipc[1]+alpha*z[0];
|
|
double num=z[0]*z[1];
|
|
double den=z[0]*z[0];
|
|
{for(int i=2;i<n;i++)
|
|
{
|
|
z[i]=x[i]-ipc[i]+alpha*z[i-1]-z[i-2];
|
|
num+=z[i-1]*(z[i]+z[i-2]);
|
|
den+=z[i-1]*z[i-1];
|
|
}}//for(int i=2;i<n;i++)
|
|
beta=num/den;
|
|
IterCount++;
|
|
}}//while(MathAbs(alpha-beta)>FreqTOL)
|
|
w=MathArccos(beta/2.0);
|
|
////----- Сравнение расчетов
|
|
//double m1,c1,s1;
|
|
//m1=m;c1=c;s1=s;
|
|
//TrigFitOCL(x,ipc,n,w,m,c,s);
|
|
//Print("1. m=",DoubleToString(m,8)," c=",DoubleToString(c,8)," s=",DoubleToString(s,8));
|
|
//m=m1;c=c1;s=s1;
|
|
//TrigFit(x,ipc,n,w,m,c,s);
|
|
//Print("2. m=",DoubleToString(m,8)," c=",DoubleToString(c,8)," s=",DoubleToString(s,8));
|
|
{if(OCLSelector)
|
|
{
|
|
TrigFitOCL(x,ipc,n,w,m,c,s);
|
|
}else{
|
|
TrigFit(x,ipc,n,w,m,c,s);
|
|
}}//if(OCLSelector)
|
|
}//Freq()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// TrigFitOCL() - Least-squares fitting of trigonometric series
|
|
//------------------------------------------------------------------------------------------------------
|
|
void TrigFitOCL(double& x[],double& ipc[],int n,double w,double& m,double& c,double& s)
|
|
{
|
|
//----- Транзитные переменные
|
|
double im[1];//2 для m
|
|
double ic[1];//3 для c
|
|
double is[1];//4 для s
|
|
im[0]=m;
|
|
ic[0]=c;
|
|
is[0]=s;
|
|
//----- Устанавливаем в качестве 0-го параметра функции OpenCL (кернела) буфер по хендлу h_CL_Buffers[0]
|
|
ResetLastError();
|
|
{if(!CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffers[0]))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer))
|
|
//----- Устанавливаем в качестве 1-го параметра функции OpenCL (кернела) буфер по хендлу h_CL_Buffers[1]
|
|
ResetLastError();
|
|
{if(!CLSetKernelArgMem(h_CL_Kernel,1,h_CL_Buffers[1]))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer_ipc))
|
|
//----- Устанавливаем в качестве 2-го параметра функции OpenCL (кернела) значение переменной n
|
|
ResetLastError();
|
|
{if(!CLSetKernelArg(h_CL_Kernel,2,n))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer_ipc))
|
|
//----- Устанавливаем в качестве 3-го параметра функции OpenCL (кернела) значение переменной w
|
|
ResetLastError();
|
|
{if(!CLSetKernelArg(h_CL_Kernel,3,w))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer_ipc))
|
|
//----- Устанавливаем в качестве 4-го параметра функции OpenCL (кернела) буфер по хендлу h_CL_Buffers[2]
|
|
ResetLastError();
|
|
{if(!CLSetKernelArgMem(h_CL_Kernel,4,h_CL_Buffers[2]))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer_ipc))
|
|
//----- Устанавливаем в качестве 5-го параметра функции OpenCL (кернела) буфер по хендлу h_CL_Buffers[3]
|
|
ResetLastError();
|
|
{if(!CLSetKernelArgMem(h_CL_Kernel,5,h_CL_Buffers[3]))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(CLSetKernelArgMem(h_CL_Kernel,0,h_CL_Buffer_ipc))
|
|
//----- Устанавливаем в качестве 6-го параметра функции OpenCL (кернела) буфер по хендлу h_CL_Buffers[4]
|
|
ResetLastError();
|
|
{if(!CLSetKernelArgMem(h_CL_Kernel,6,h_CL_Buffers[4]))
|
|
{
|
|
Print("OpenCL set buffer failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL set buffer, Error:",GetLastError());
|
|
}}//if(!CLSetKernelArgMem(h_CL_Kernel,6,h_CL_Buffers[4]))
|
|
//----- Записываем исходные значения x[] в буфер по хендлу h_CL_Buffers[0]
|
|
ResetLastError();
|
|
uint nElementsWrite=CLBufferWrite(h_CL_Buffers[0],x,0,0,n);
|
|
{if(nElementsWrite<(uint)n)
|
|
{
|
|
Print("OpenCL buffer x write failed, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL buffer write, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
}}//if(nElementsWrite<=0)
|
|
//----- Записываем исходные значения ipc[] в буфер по хендлу h_CL_Buffers[1]
|
|
ResetLastError();
|
|
nElementsWrite=CLBufferWrite(h_CL_Buffers[1],ipc,0,0,n);
|
|
{if(nElementsWrite<(uint)n)
|
|
{
|
|
Print("OpenCL buffer ipc write failed, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL buffer write, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
}}//if(nElementsWrite<=0)
|
|
//----- Записываем исходное значение m в буфер по хендлу h_CL_Buffers[2]
|
|
ResetLastError();
|
|
nElementsWrite=CLBufferWrite(h_CL_Buffers[2],im,0,0,1);
|
|
{if(nElementsWrite<1)
|
|
{
|
|
Print("OpenCL buffer write failed, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL buffer write, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
}}//if(nElementsWrite<=0)
|
|
//----- Записываем исходное значение c в буфер по хендлу h_CL_Buffers[3]
|
|
ResetLastError();
|
|
nElementsWrite=CLBufferWrite(h_CL_Buffers[3],ic,0,0,1);
|
|
{if(nElementsWrite<1)
|
|
{
|
|
Print("OpenCL buffer write failed, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL buffer write, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
}}//if(nElementsWrite<=0)
|
|
//----- Записываем исходное значение s в буфер по хендлу h_CL_Buffers[4]
|
|
ResetLastError();
|
|
nElementsWrite=CLBufferWrite(h_CL_Buffers[4],is,0,0,1);
|
|
{if(nElementsWrite<1)
|
|
{
|
|
Print("OpenCL buffer write failed, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL buffer write, nElementsWrite=",nElementsWrite," error:",GetLastError());
|
|
}}//if(nElementsWrite<=0)
|
|
//----- Запускаем выполнение кернела
|
|
ResetLastError();
|
|
{if(!CLExecute(h_CL_Kernel))
|
|
{
|
|
Print("OpenCL execute failed, error:",GetLastError());
|
|
ShutDown(h_CL_Context,h_CL_Program,h_CL_Kernel,h_CL_Buffers);
|
|
return;
|
|
}else{
|
|
//Print("OpenCL execute, error:",GetLastError());
|
|
}}//if(!CLExecute(h_CL_Kernel))
|
|
//----- Считываем полученные значения в массивы
|
|
//Print("Из буфера прочитано ",CLBufferRead(h_CL_Buffers[0],x,0,0,5)," элементов");
|
|
CLBufferRead(h_CL_Buffers[0],x,0,0,n);
|
|
//Print("Из буфера прочитано ",CLBufferRead(h_CL_Buffers[1],ipc,0,0,3)," элементов");
|
|
CLBufferRead(h_CL_Buffers[1],ipc,0,0,n);
|
|
//Print("Из буфера прочитано ",CLBufferRead(h_CL_Buffers[2],im,0,0,1)," элементов");
|
|
CLBufferRead(h_CL_Buffers[2],im,0,0,1);
|
|
m=im[0];
|
|
//Print("Из буфера прочитано ",CLBufferRead(h_CL_Buffers[3],ic,0,0,1)," элементов");
|
|
CLBufferRead(h_CL_Buffers[3],ic,0,0,1);
|
|
c=ic[0];
|
|
//Print("Из буфера прочитано ",CLBufferRead(h_CL_Buffers[4],is,0,0,1)," элементов");
|
|
CLBufferRead(h_CL_Buffers[4],is,0,0,1);
|
|
s=is[0];
|
|
return;
|
|
}//TrigFitOCL()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// TrigFit() - Least-squares fitting of trigonometric series
|
|
//------------------------------------------------------------------------------------------------------
|
|
void TrigFit(
|
|
double &x[],
|
|
double &ipc[],
|
|
int n,
|
|
double w,
|
|
double &m,
|
|
double &c,
|
|
double &s
|
|
)
|
|
{
|
|
//c=ipc[0];
|
|
double Sc =0.0;
|
|
double Ss =0.0;
|
|
double Scc=0.0;
|
|
double Sss=0.0;
|
|
double Scs=0.0;
|
|
double Sx =0.0;
|
|
double Sxc=0.0;
|
|
double Sxs=0.0;
|
|
{for(int i=0;i<n;i++)
|
|
{
|
|
double cos_w_i=cos(w*i);
|
|
double sin_w_i=sin(w*i);
|
|
double dx=x[i]-ipc[i];
|
|
Sc +=cos_w_i;
|
|
Ss +=sin_w_i;
|
|
Scc+=cos_w_i*cos_w_i;
|
|
Sss+=sin_w_i*sin_w_i;
|
|
Scs+=cos_w_i*sin_w_i;
|
|
Sx +=dx;
|
|
Sxc+=dx*cos_w_i;
|
|
Sxs+=dx*sin_w_i;
|
|
}}//for(int i=0;i<n;i++)
|
|
Sc /=n;
|
|
Ss /=n;
|
|
Scc/=n;
|
|
Sss/=n;
|
|
Scs/=n;
|
|
Sx /=n;
|
|
Sxc/=n;
|
|
Sxs/=n;
|
|
{if(w==0.0)
|
|
{
|
|
m=Sx;
|
|
c=0.0;
|
|
s=0.0;
|
|
}else{
|
|
// calculating a, b, and m
|
|
double den=pow(Scs-Sc*Ss,2)-(Scc-Sc*Sc)*(Sss-Ss*Ss);
|
|
c=((Sxs-Sx*Ss)*(Scs-Sc*Ss)-(Sxc-Sx*Sc)*(Sss-Ss*Ss))/den;
|
|
s=((Sxc-Sx*Sc)*(Scs-Sc*Ss)-(Sxs-Sx*Ss)*(Scc-Sc*Sc))/den;
|
|
m=Sx-c*Sc-s*Ss;
|
|
}}//if(w==0.0)
|
|
return;
|
|
}//TrigFit()
|
|
//
|
|
//============================================================================================= MQL5 ===
|
|
// ShutDown() function
|
|
//------------------------------------------------------------------------------------------------------
|
|
void ShutDown(
|
|
int &i_CL_Context,
|
|
int &i_CL_Program,
|
|
int &i_CL_Kernel,
|
|
int &i_CL_Buffers[],
|
|
const string i_BuildLog = "",
|
|
const bool i_PrintDebugSelector = false
|
|
)
|
|
{
|
|
//----- Build Log Print
|
|
{if((i_PrintDebugSelector)&&(i_BuildLog!=""))
|
|
{
|
|
string LogLines[];
|
|
StringSplit(i_BuildLog,'\n',LogLines);
|
|
int LogLinesCount=ArraySize(LogLines);
|
|
{for(int i=0; i<LogLinesCount; i++)
|
|
{
|
|
Print(LogLines[i]);
|
|
}}//for(int i=0; i<LogLinesCount; i++)
|
|
}}//if((i_PrintDebugSelector)&&(i_BuildLog!=""))
|
|
//----- Remove buffer
|
|
{for(int i=0;i<=ArraySize(i_CL_Buffers)-1;i++)
|
|
{
|
|
{if(i_CL_Buffers[i]!=INVALID_HANDLE)
|
|
{
|
|
CLBufferFree(i_CL_Buffers[i]);
|
|
i_CL_Buffers[i]=INVALID_HANDLE;
|
|
}}//if(i_CL_Buffers[i]=INVALID_HANDLE)
|
|
}}//for(i=0;i<=ArraySize(i_CL_Buffers);i++)
|
|
//----- Remove kernel
|
|
{if(i_CL_Kernel!=INVALID_HANDLE)
|
|
{
|
|
CLKernelFree(i_CL_Kernel);
|
|
i_CL_Kernel=INVALID_HANDLE;
|
|
}}//if(i_CL_Kernel!=INVALID_HANDLE)
|
|
//----- Remove program
|
|
{if(i_CL_Program!=INVALID_HANDLE)
|
|
{
|
|
CLProgramFree(i_CL_Program);
|
|
i_CL_Program=INVALID_HANDLE;
|
|
}}//if(m_program!=INVALID_HANDLE)
|
|
//----- Remove context
|
|
{if(i_CL_Context!=INVALID_HANDLE)
|
|
{
|
|
CLContextFree(i_CL_Context);
|
|
i_CL_Context=INVALID_HANDLE;
|
|
}}//if(m_context!=INVALID_HANDLE)
|
|
}//ShutDown()
|
|
// |