Init mql5 project

This commit is contained in:
Bell
2025-10-09 22:06:54 +07:00
commit 5dbabfd64b
619 changed files with 500541 additions and 0 deletions
Binary file not shown.
@@ -0,0 +1,143 @@
//+------------------------------------------------------------------+
//| TestAccountInfo.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#include <Trade\AccountInfo.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//---
#include "AccountInfoSampleInit.mqh"
//+------------------------------------------------------------------+
//| Script to testing the use of class CAccountInfo. |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Account Info Sample script class |
//+------------------------------------------------------------------+
class CAccountInfoSample
{
protected:
CAccountInfo m_account;
//--- chart objects
CChartObjectLabel m_label[19];
CChartObjectLabel m_label_info[19];
public:
CAccountInfoSample(void);
~CAccountInfoSample(void);
//---
bool Init(void);
void Deinit(void);
void Processing(void);
private:
void AccountInfoToChart(void);
};
//---
CAccountInfoSample ExtScript;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CAccountInfoSample::CAccountInfoSample(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CAccountInfoSample::~CAccountInfoSample(void)
{
}
//+------------------------------------------------------------------+
//| Method Init. |
//+------------------------------------------------------------------+
bool CAccountInfoSample::Init(void)
{
int i,sy=10;
int dy=16;
color color_label;
color color_info;
//--- tuning colors
color_info =(color)(ChartGetInteger(0,CHART_COLOR_BACKGROUND)^0xFFFFFF);
color_label=(color)(color_info^0x202020);
//---
if(ChartGetInteger(0,CHART_SHOW_OHLC))
sy+=16;
//--- creation Labels[]
for(i=0;i<19;i++)
{
m_label[i].Create(0,"Label"+IntegerToString(i),0,20,sy+dy*i);
m_label[i].Description(init_str[i]);
m_label[i].Color(color_label);
m_label[i].FontSize(8);
//---
m_label_info[i].Create(0,"LabelInfo"+IntegerToString(i),0,120,sy+dy*i);
m_label_info[i].Description(" ");
m_label_info[i].Color(color_info);
m_label_info[i].FontSize(8);
}
AccountInfoToChart();
//--- redraw chart
ChartRedraw();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method Deinit. |
//+------------------------------------------------------------------+
void CAccountInfoSample::Deinit(void)
{
}
//+------------------------------------------------------------------+
//| Method Processing. |
//+------------------------------------------------------------------+
void CAccountInfoSample::Processing(void)
{
AccountInfoToChart();
//--- redraw chart
ChartRedraw();
Sleep(50);
}
//+------------------------------------------------------------------+
//| Method InfoToChart. |
//+------------------------------------------------------------------+
void CAccountInfoSample::AccountInfoToChart(void)
{
m_label_info[0].Description((string)m_account.Login());
m_label_info[1].Description(m_account.TradeModeDescription());
m_label_info[2].Description((string)m_account.Leverage());
m_label_info[3].Description(m_account.MarginModeDescription());
m_label_info[4].Description((string)m_account.TradeAllowed());
m_label_info[5].Description((string)m_account.TradeExpert());
m_label_info[6].Description(DoubleToString(m_account.Balance(),2));
m_label_info[7].Description(DoubleToString(m_account.Credit(),2));
m_label_info[8].Description(DoubleToString(m_account.Profit(),2));
m_label_info[9].Description(DoubleToString(m_account.Equity(),2));
m_label_info[10].Description(DoubleToString(m_account.Margin(),2));
m_label_info[11].Description(DoubleToString(m_account.FreeMargin(),2));
m_label_info[12].Description(DoubleToString(m_account.MarginLevel(),2));
m_label_info[13].Description(DoubleToString(m_account.MarginCall(),2));
m_label_info[14].Description(DoubleToString(m_account.MarginStopOut(),2));
m_label_info[15].Description(m_account.Name());
m_label_info[16].Description(m_account.Server());
m_label_info[17].Description(m_account.Currency());
m_label_info[18].Description(m_account.Company());
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart(void)
{
//--- call init function
if(ExtScript.Init())
{
//--- cycle until the script is not halted
while(!IsStopped())
ExtScript.Processing();
}
//--- call deinit function
ExtScript.Deinit();
}
//+------------------------------------------------------------------+
@@ -0,0 +1,17 @@
//+------------------------------------------------------------------+
//| AccountInfoInitSample.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Arrays to initialize graphics objects AccountInfoSample. |
//+------------------------------------------------------------------+
string init_str[]=
{
"Login","TradeMode","Leverage","MarginMode","TradeAllowed",
"TradeExpert","Balance","Credit","Profit","Equity",
"Margin","FreeMargin","MarginLevel","MarginCall","MarginStopOut",
"Name","Server","Currency","Company"
};
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,102 @@
//+------------------------------------------------------------------+
//| ArrayDoubleSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#include <Arrays\ArrayDouble.mqh>
#include <Files\FileBin.mqh>
//---
const int ExtArraySize=10000;
const int ExtArrayAdd=100;
string ExtFileName="ArrayDoubleSample.bin";
//+------------------------------------------------------------------+
//| Example class CArrayDouble |
//+------------------------------------------------------------------+
int OnStart(void)
{
int i,pos;
double key;
CFileBin File;
CArrayDouble ArrayDouble;
//---
printf("Start sample %s.",__FILE__);
//--- fill an array of background information
//--- open file for reading
if(File.Open(ExtFileName,FILE_READ)!=INVALID_HANDLE)
{
//--- read array from file
if(!ArrayDouble.Load(File.Handle()))
{
//--- error reading from file
printf("%s (%4d): error %d",__FILE__,__LINE__,GetLastError());
}
//--- do not forget close file
File.Close();
}
//--- check whether enough information in the array
if(ArrayDouble.Total()<ExtArraySize)
{
//--- information in the file is not enough, or it is not at all
//--- reserve position in the array for the missing information
if(!ArrayDouble.Reserve(ExtArraySize-ArrayDouble.Total()))
{
//--- displaying the log error information
printf("%s (%4d): reserve error",__FILE__,__LINE__);
//--- remove a previously created array
return(__LINE__);
}
//--- additional fill an array of "random" values
for(i=ArrayDouble.Total();i<ExtArraySize;i++)
ArrayDouble.Add(MathRand()*MathPow(10,MathRand()%100));
}
//--- sort array
ArrayDouble.Sort();
//--- inserts the additional data without violating sorting (ExtArrayAdd items)
for(i=0;i<ExtArrayAdd;i++)
ArrayDouble.InsertSort(MathRand()*MathPow(10,MathRand()%100));
//--- set tolerance "fuzzy" comparison for the search
ArrayDouble.Delta(0.1);
//--- produce some of the search in sorted array
key=MathRand()*MathPow(10,MathRand()%100);
if((pos=ArrayDouble.SearchGreat(key))==-1)
printf("Search for items greater than %f, not found",key);
else
{
printf("Search for items greater than %f, found %f in the position %d",key,ArrayDouble.At(pos),pos);
//--- your actions have found the element
//--- ...
//---
}
key=MathRand()*MathPow(10,MathRand()%100);
if((pos=ArrayDouble.SearchLess(key))==-1)
printf("Search for items less than %f, not found",key);
else
{
printf("Search for items less than %f, found %f in the position %d",key,ArrayDouble.At(pos),pos);
//--- your actions have found the element
//--- ...
//---
}
//--- Remove from the array of extra data (ExtArrayAdd/2 largest and ExtArrayAdd/2 lowest)
ArrayDouble.DeleteRange(ArrayDouble.Total()-ExtArrayAdd/2-1,ArrayDouble.Total());
ArrayDouble.DeleteRange(0,ExtArraySize/2);
//--- save the modified array of file
//--- open file for writing
if(File.Open(ExtFileName,FILE_WRITE)!=INVALID_HANDLE)
if(ArrayDouble.Save(File.Handle()))
{
//--- normal completion
//--- because when you call the destructor, an open file is closed automatically
//--- and explicitly close the file is not necessary but desirable
printf("End of sample %s. OK!",__FILE__);
return(0);
}
//--- error with file
//--- displaying the log error information
printf("%s (%4d): error %d",__FILE__,__LINE__,GetLastError());
return(__LINE__);
}
//+------------------------------------------------------------------+
Binary file not shown.
+211
View File
@@ -0,0 +1,211 @@
//+------------------------------------------------------------------+
//| CanvasSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Demonstrating Canvas features"
//---
#include <Canvas\Canvas.mqh>
//+------------------------------------------------------------------+
//| inputs |
//+------------------------------------------------------------------+
input int Width=800;
input int Height=600;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
int total=1024;
int limit=MathMax(Width,Height);
int x1,x2,x3,y1,y2,y3,r;
int x[],y[];
//--- check
if(Width<100 || Height<100)
{
Print("Too simple.");
return(-1);
}
//--- create canvas
CCanvas canvas;
if(!canvas.CreateBitmapLabel("SampleCanvas",0,0,Width,Height,COLOR_FORMAT_ARGB_RAW))
{
Print("Error creating canvas: ",GetLastError());
return(-1);
}
//--- deawing
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- start randomizer
srand(GetTickCount());
//--- draw pixels
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
canvas.PixelSet(x1,y1,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- draw horizontal/vertical lines
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
x2=rand()%limit;
y1=rand()%limit;
y2=rand()%limit;
if(i%2==0)
canvas.LineHorizontal(x1,x2,y1,RandomRGB());
else
canvas.LineVertical(x1,y1,y2,RandomRGB());
canvas.Update();
}
//--- draw lines
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
x2=rand()%limit;
y1=rand()%limit;
y2=rand()%limit;
canvas.Line(x1,y1,x2,y2,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- draw filled circles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
r =rand()%limit;
canvas.FillCircle(x1,y1,r,RandomRGB());
canvas.Update();
}
//--- draw circles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
r =rand()%limit;
canvas.Circle(x1,y1,r,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- draw filled rectangles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
x2=rand()%limit;
y2=rand()%limit;
canvas.FillRectangle(x1,y1,x2,y2,RandomRGB());
canvas.Update();
}
//--- draw rectangles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
x2=rand()%limit;
y2=rand()%limit;
canvas.Rectangle(x1,y1,x2,y2,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- draw filled triangles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
x2=rand()%limit;
y2=rand()%limit;
x3=rand()%limit;
y3=rand()%limit;
canvas.FillTriangle(x1,y1,x2,y2,x3,y3,RandomRGB());
canvas.Update();
}
//--- draw triangles
for(int i=0;i<total && !IsStopped();i++)
{
x1=rand()%limit;
y1=rand()%limit;
x2=rand()%limit;
y2=rand()%limit;
x3=rand()%limit;
y3=rand()%limit;
canvas.Triangle(x1,y1,x2,y2,x3,y3,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//---
ArrayResize(x,10);
ArrayResize(y,10);
//--- draw polyline
for(int i=0;i<10;i++)
{
x[i]=rand()%Width;
y[i]=rand()%Height;
}
canvas.Polyline(x,y,RandomRGB());
canvas.Update();
//--- draw polygon
for(int i=0;i<10;i++)
{
x[i]=rand()%Width;
y[i]=rand()%Height;
}
canvas.Polygon(x,y,RandomRGB());
canvas.Update();
//--- filling
for(int i=0;i<total && !IsStopped();i++)
{
int xf=rand()%Width;
int yf=rand()%Height;
canvas.Fill(xf,yf,RandomRGB());
canvas.Update();
}
//--- erase
canvas.Erase(XRGB(0x1F,0x1F,0x1F));
canvas.Update();
//--- draw text
string text;
x1=Width/2;
y1=Height/2;
r =y1-50;
for(int i=0;i<8;i++)
{
double a=i*M_PI_4;
uint clr=RandomRGB();
int deg=(int)(180*a/M_PI);
x2=x1+(int)(r*cos(a));
y2=y1-(int)(r*sin(a));
canvas.LineAA(x1,y1,x2,y2,clr,STYLE_DASHDOTDOT);
text="Angle "+IntegerToString(deg);
canvas.FontSet(canvas.FontNameGet(),canvas.FontSizeGet(),canvas.FontFlagsGet(),10*deg);
canvas.TextOut(x2,y2,text,clr,TA_RIGHT|TA_BOTTOM);
canvas.Update();
}
//--- finish
ObjectDelete(0,"SampleCanvas");
canvas.Destroy();
return(0);
}
//+------------------------------------------------------------------+
//| Random RGB color |
//+------------------------------------------------------------------+
uint RandomRGB(void)
{
return(XRGB(rand()%255,rand()%255,rand()%255));
}
//+------------------------------------------------------------------+
@@ -0,0 +1,66 @@
//+------------------------------------------------------------------+
//| HistogramChartSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Example of using histogram"
//---
#include <Canvas\Charts\HistogramChart.mqh>
//+------------------------------------------------------------------+
//| inputs |
//+------------------------------------------------------------------+
input bool Accumulative=true;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
int k=100;
double arr[10];
//--- create chart
CHistogramChart chart;
if(!chart.CreateBitmapLabel("SampleHistogramChart",10,10,600,450))
{
Print("Error creating histogram chart: ",GetLastError());
return(-1);
}
if(Accumulative)
{
chart.Accumulative();
chart.VScaleParams(20*k*10,-10*k*10,20);
}
else
chart.VScaleParams(20*k,-10*k,20);
chart.ShowValue(true);
chart.ShowScaleTop(false);
chart.ShowScaleBottom(false);
chart.ShowScaleRight(false);
chart.ShowLegend();
for(int j=0;j<5;j++)
{
for(int i=0;i<10;i++)
{
k=-k;
if(k>0)
arr[i]=k*(i+10-j);
else
arr[i]=k*(i+10-j)/2;
}
chart.SeriesAdd(arr,"Item"+IntegerToString(j));
}
//--- play with values
while(!IsStopped())
{
int i=rand()%5;
int j=rand()%10;
k=rand()%3000-1000;
chart.ValueUpdate(i,j,k);
Sleep(200);
}
//--- finish
chart.Destroy();
return(0);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,66 @@
//+------------------------------------------------------------------+
//| LineChartSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Example of using line chart"
//---
#include <Canvas\Charts\LineChart.mqh>
//+------------------------------------------------------------------+
//| inputs |
//+------------------------------------------------------------------+
input bool Accumulative=false;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
int k=100;
double arr[10];
//--- create chart
CLineChart chart;
//--- create chart
if(!chart.CreateBitmapLabel("SampleHistogrammChart",10,10,600,450))
{
Print("Error creating line chart: ",GetLastError());
return(-1);
}
if(Accumulative)
{
chart.Accumulative();
chart.VScaleParams(20*k*10,-10*k*10,20);
}
else
chart.VScaleParams(20*k,-10*k,15);
chart.ShowScaleTop(false);
chart.ShowScaleRight(false);
chart.ShowLegend();
chart.Filled();
for(int j=0;j<5;j++)
{
for(int i=0;i<10;i++)
{
k=-k;
if(k>0)
arr[i]=k*(i+10-j);
else
arr[i]=k*(i+10-j)/2;
}
chart.SeriesAdd(arr,"Item"+IntegerToString(j));
}
//--- play with values
while(!IsStopped())
{
int i=rand()%5;
int j=rand()%10;
k=rand()%3000-1000;
chart.ValueUpdate(i,j,k);
Sleep(200);
}
//--- finish
chart.Destroy();
return(0);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,97 @@
//+------------------------------------------------------------------+
//| PieChartSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Example of using pie chart"
//---
#include <Canvas\Charts\PieChart.mqh>
//+------------------------------------------------------------------+
//| inputs |
//+------------------------------------------------------------------+
input int Width=600;
input int Height=450;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
//--- check
if(Width<=0 || Height<=0)
{
Print("Too simple.");
return(-1);
}
//--- create chart
CPieChart pie_chart;
if(!pie_chart.CreateBitmapLabel("PieChart",10,10,Width,Height))
{
Print("Error creating pie chart: ",GetLastError());
return(-1);
}
pie_chart.ShowPercent();
//--- draw
for(uint i=0;i<30;i++)
{
pie_chart.ValueAdd(100*(i+1),"Item "+IntegerToString(i));
Sleep(10);
}
Sleep(2000);
//--- disable legend
pie_chart.LegendAlignment(ALIGNMENT_LEFT);
Sleep(2000);
//--- disable legend
pie_chart.LegendAlignment(ALIGNMENT_RIGHT);
Sleep(2000);
//--- disable legend
pie_chart.LegendAlignment(ALIGNMENT_TOP);
Sleep(2000);
//--- disable legend
pie_chart.ShowLegend(false);
Sleep(2000);
//--- disable percentage
pie_chart.ShowPercent(false);
Sleep(2000);
//--- disable descriptors
pie_chart.ShowDescriptors(false);
Sleep(2000);
//--- enable all
pie_chart.ShowLegend();
pie_chart.ShowValue();
pie_chart.ShowDescriptors();
Sleep(2000);
//--- or like this
pie_chart.ShowFlags(FLAG_SHOW_LEGEND|FLAG_SHOW_DESCRIPTORS|FLAG_SHOW_PERCENT);
uint total=pie_chart.DataTotal();
//--- play with values
for(uint i=0;i<total && !IsStopped();i++)
{
pie_chart.ValueUpdate(i,100*(rand()%10+1));
Sleep(1000);
}
//--- play with colors
for(uint i=0;i<total && !IsStopped();i++)
{
pie_chart.ColorUpdate(i%total,RandomRGB());
Sleep(1000);
}
//--- rotate
while(!IsStopped())
{
pie_chart.DataOffset(pie_chart.DataOffset()+1);
Sleep(200);
}
//--- finish
pie_chart.Destroy();
return(0);
}
//+------------------------------------------------------------------+
//| Random RGB color |
//+------------------------------------------------------------------+
uint RandomRGB(void)
{
return(XRGB(rand()%255,rand()%255,rand()%255));
}
//+------------------------------------------------------------------+
@@ -0,0 +1,163 @@
//+------------------------------------------------------------------+
//| ChartSampleInit.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Arrays to initialize graphics objects ObjChartSample. |
//+------------------------------------------------------------------+
#define NUM_PANELS 8
#define NUM_LABELS 40
#define NUM_EDITS 38
#define NUM_BUTTONS 28
//--- for Pabel[]
string p_str[NUM_PANELS]=
{
"Modes","Anothers","Scales","Shows","Timeframes","Symbols","Colors",
"Read only parameters"
};
//--- for Label[]
int l_x[NUM_LABELS]=
{
20,20,20,20,20,20,20,
20,20,20,20,20,20,
80,140,200,260,20,20,20,20,
20,80,110,160,260,290,
20,20,20,20,20,20,20,20,20,20,20,20,20
};
int l_y[NUM_LABELS]=
{
14,49,84,151,218,269,346,
1,21,41,61,81,101,
121,121,121,121,141,161,181,201,
241,221,221,221,221,221,
21,41,61,81,101,121,141,161,181,201,221,241,261
};
int l_pan[NUM_LABELS]=
{
14,49,84,151,218,269,346,
7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,
6,6,6,6,6,6,6,6,6,6,6,6,6
};
string l_str[]=
{
"Modes","Anothers","Scales","Shows","Timeframes","Symbols","Read only parameters",
"Handle","Visible bars","First bar","Width (bars)","Width (pix)","Win total",
"Win 0","Win 1","Win 2","Win 3","Visible","Height (pix)","Price min","Price max",
"OnDropped","Win","Price","Time","X","Y",
"Background","Foreground","Grid","BarUp","BarDown","CandleBull","CandleBear",
"ChartLine","Volumes","LineBid","LineAsk","LineLast","StopLevels"
};
//--- for Edit[]
int e_x[NUM_EDITS]=
{
220,220,320,320,95,245,120,
80,80,80,140,200,260,320,
80,80,80,80,
80,140,200,260,320,
80,140,200,260,320,
80,140,200,260,320,
80,100,160,260,290
};
int e_y[NUM_EDITS]=
{
0,0,0,0,16,16,32,
20,100,140,140,140,140,140,
0,40,60,80,
160,160,160,160,160,
180,180,180,180,180,
200,200,200,200,200,
240,240,240,240,240
};
int e_sizeX[NUM_EDITS]=
{
80,80,0,0,75,75,100,
60,60,60,60,60,60,0,
60,60,60,60,
60,60,60,60,0,
60,60,60,60,0,
60,60,60,60,0,
20,60,100,30,30
};
int e_pan[NUM_EDITS]=
{
1,2,2,2,2,2,2,
7,7,7,7,7,7,7,
7,7,7,7,
7,7,7,7,7,
7,7,7,7,7,
7,7,7,7,7,
7,7,7,7,7
};
//--- for Button[]
int b_x[NUM_BUTTONS]=
{
20,120,220,
95,170,20,300,300,
20,120,300,300,20,170,20,
20,95,170,245,20,120,220,
20,120,220,
20,120,220
};
int b_y[NUM_BUTTONS]=
{
0,0,0,
0,0,0,0,8,
0,0,0,8,16,16,32,
0,0,0,0,16,16,16,
32,32,32,
0,0,0
};
int b_sizeX[NUM_BUTTONS]=
{
100,100,100,
75,50,75,20,20,
100,100,20,20,75,75,100,
75,75,75,75,100,100,100,
100,100,100,
100,100,100
};
int b_sizeY[NUM_BUTTONS]=
{
16,16,16,
16,16,16,8,8,
16,16,8,8,16,16,16,
16,16,16,16,16,16,16,
16,16,16,
16,16,16
};
string b_str[NUM_BUTTONS]=
{
"Bars","Candles","Line",
"AutoScroll","Shift","Foreground"," "," ",
"Scale fix","Scale fix 1/1"," "," ",
"Fixed Max","Fixed Min",
"Scale PixPerBar",
"Show OHLC","Show Bid","Show Ask","Show Last",
"Show Separator","Show Grid","Show ObjDescr",
"Not Volumes","Tick Volumes","Real Volumes",
"Yellow on Black","Green on Black","Black on White"
};
int b_pan[NUM_BUTTONS]=
{
0,0,0,
1,1,1,1,1,
2,2,2,2,2,2,2,
3,3,3,3,3,3,3,
3,3,3,
6,6,6
};
//--- for ButtonTF[]
string tf_str[]=
{
"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30",
"H1","H2","H3","H4","H6","H12","D1","W1","MN"
};
int tf_int[]=
{
1,2,3,4,5,6,10,12,15,20,30,
0x4001,0x4002,0x4003,0x4004,0x4006,0x400c,0x4018,0x8001,0xc001
};
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,775 @@
//+------------------------------------------------------------------+
//| ChartSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#include <Charts\Chart.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
#include <ChartObjects\ChartObjectPanel.mqh>
//---
#include "ChartSampleInit.mqh"
//+------------------------------------------------------------------+
//| Script to demonstrate the use of class CChart. |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Chart Sample script class |
//+------------------------------------------------------------------+
class CChartSample
{
protected:
CChart m_chart; // instance of the class to access properties chart
CChartObjectButton *m_button[NUM_BUTTONS]; // array of pointers other buttons
CChartObjectButton *m_button_tf[20]; // array of pointers period buttons
CChartObjectButton *m_button_sym[]; // array of pointers symbol buttons
int m_num_symbols; // number of symbol
CChartObjectEdit *m_edit[NUM_EDITS]; // array of pointers other edits
CChartObjectEdit *m_edit_color[13]; // array of pointers to colors show
CChartObjectEdit *m_edit_rgb[13][3]; // array of pointers to RGB show
CChartObjectLabel *m_label[NUM_LABELS]; // array of pointers to labels
CChartObjectPanel m_panel[NUM_PANELS]; // array of panels
public:
CChartSample(void);
~CChartSample(void);
//--- initialization
bool Init(void);
void Deinit(void);
//--- processing
void Processing(void);
private:
void CheckPanelModes(void);
void CheckPanelAnothers(void);
void CheckPanelScales(void);
void CheckPanelShows(void);
void CheckPanelTimeframes(void);
void CheckPanelSymbols(void);
void CheckPanelColors(void);
void CheckPanelReadOnly(void);
};
//---
CChartSample ExtScript;
//+------------------------------------------------------------------+
//| Constructor. |
//+------------------------------------------------------------------+
CChartSample::CChartSample(void) : m_num_symbols(0)
{
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
CChartSample::~CChartSample(void)
{
//--- does not perform any action
//--- all dynamic objects created in the method Init(),
//--- will be deleted when deleting panels,
//--- to which they were added
}
//+------------------------------------------------------------------+
//| Method CheckPanelModes. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelModes(void)
{
if(m_button[0].State() && m_chart.Mode()!=CHART_BARS)
{
//--- Set Bars Mode
m_button[1].State(false);
m_button[2].State(false);
m_chart.Mode(CHART_BARS);
}
if(m_button[1].State() && m_chart.Mode()!=CHART_CANDLES)
{
//--- Set Candles Mode
m_button[0].State(false);
m_button[2].State(false);
m_chart.Mode(CHART_CANDLES);
}
if(m_button[2].State() && m_chart.Mode()!=CHART_LINE)
{
//--- Set Line Mode
m_button[0].State(false);
m_button[1].State(false);
m_chart.Mode(CHART_LINE);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelAnothers. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelAnothers(void)
{
int i,j;
//--- Set Autoscroll
if(m_button[3].State())
{
if(!m_chart.AutoScroll())
m_chart.AutoScroll(true);
}
else
{
if(m_chart.AutoScroll())
m_chart.AutoScroll(false);
}
//--- Set Shift
if(m_button[4].State())
{
if(m_edit[0].Description()=="")
m_edit[0].Description(DoubleToString(m_chart.ShiftSize()));
else
{
i=(int)StringToInteger(m_edit[0].Description());
j=i;
if(i>50)
i=50;
if(i<10)
i=10;
if(j!=i)
m_edit[0].Description(IntegerToString(i));
if(i!=m_chart.ShiftSize())
m_chart.ShiftSize(i);
}
if(!m_chart.Shift())
m_chart.Shift(true);
}
else
{
m_edit[0].Description("");
if(m_chart.Shift())
m_chart.Shift(false);
}
//--- Set Shift Size
if(m_button[6].State())
{
if(m_button[4].State())
{
//--- Set Shift Size Up
i=(int)StringToInteger(m_edit[0].Description());
if(i<50)
m_chart.ShiftSize(++i);
m_edit[0].Description(IntegerToString(i));
}
m_button[6].State(false);
}
if(m_button[7].State())
{
if(m_button[4].State())
{
//--- Set Shift Size Down
i=(int)StringToInteger(m_edit[0].Description());
if(i>10)
m_chart.ShiftSize(--i);
m_edit[0].Description(IntegerToString(i));
}
m_button[7].State(false);
}
m_edit[2].Description(DoubleToString(m_chart.ShiftSize()));
//--- Set Foreground
if(m_button[5].State())
{
if(!m_chart.Foreground())
m_chart.Foreground(true);
}
else
{
if(m_chart.Foreground())
m_chart.Foreground(false);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelScales. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelScales(void)
{
int i;
double d;
//--- Set Scale fix
if(m_button[8].State())
{
if(m_edit[4].Description()=="")
{
m_edit[4].Description(DoubleToString(m_chart.PriceMax(0),4));
m_edit[5].Description(DoubleToString(m_chart.PriceMin(0),4));
}
if(!m_chart.ScaleFix())
m_chart.ScaleFix(true);
}
else
{
if(m_edit[4].Description()!="")
{
m_edit[4].Description("");
m_edit[5].Description("");
}
if(m_chart.ScaleFix())
m_chart.ScaleFix(false);
}
//--- Set Scale fix 1 to 1
if(m_button[9].State())
{
if(!m_chart.ScaleFix_11())
m_chart.ScaleFix_11(true);
}
else
{
if(m_chart.ScaleFix_11())
m_chart.ScaleFix_11(false);
}
//--- Set Scale
if(m_button[10].State())
{
//--- Set Scale Up
i=(int)StringToInteger(m_edit[1].Description());
if(i<5)
{
i++;
m_chart.Scale(i);
m_edit[1].Description(IntegerToString(i));
}
m_button[10].State(false);
}
if(m_button[11].State())
{
//--- Set Scale Down
i=(int)StringToInteger(m_edit[1].Description());
if(i>0)
{
i--;
m_chart.Scale(i);
m_edit[1].Description(IntegerToString(i));
}
m_button[11].State(false);
}
m_edit[3].Description(IntegerToString(m_chart.Scale()));
//--- Set Fixed Max
if(m_button[12].State())
{
if(m_chart.ScaleFix())
{
d=StringToDouble(m_edit[4].Description());
if(m_chart.FixedMax()!=d)
m_chart.FixedMax(d);
m_edit[4].Description(DoubleToString(d,4));
}
else
m_edit[4].Description("");
m_button[12].State(false);
}
//--- Set Fixed Min
if(m_button[13].State())
{
if(m_chart.ScaleFix())
{
d=StringToDouble(m_edit[5].Description());
if(m_chart.FixedMin()!=d)
m_chart.FixedMin(d);
m_edit[5].Description(DoubleToString(d,4));
}
else
m_edit[5].Description("");
m_button[13].State(false);
}
//--- Set Scale PPB
if(m_button[14].State())
{
if(m_edit[6].Description()=="")
{
d=m_chart.PointsPerBar();
if(d==0.0)
{
d=1.0;
m_chart.PointsPerBar(d);
}
m_edit[6].Description(DoubleToString(d,4));
}
if(!m_chart.ScalePPB())
m_chart.ScalePPB(true);
d=StringToDouble(m_edit[6].Description());
if(m_chart.PointsPerBar()!=d)
m_chart.PointsPerBar(d);
}
else
{
m_edit[6].Description("");
if(m_chart.ScalePPB())
m_chart.ScalePPB(false);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelShows. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelShows(void)
{
//--- Set Show OHLC
if(m_button[15].State())
{
if(!m_chart.ShowOHLC())
m_chart.ShowOHLC(true);
}
else
{
if(m_chart.ShowOHLC())
m_chart.ShowOHLC(false);
}
//--- Set Show Bid
if(m_button[16].State())
{
if(!m_chart.ShowLineBid())
m_chart.ShowLineBid(true);
}
else
{
if(m_chart.ShowLineBid())
m_chart.ShowLineBid(false);
}
//--- Set Show Ask
if(m_button[17].State())
{
if(!m_chart.ShowLineAsk())
m_chart.ShowLineAsk(true);
}
else
{
if(m_chart.ShowLineAsk())
m_chart.ShowLineAsk(false);
}
//--- Set Show Last
if(m_button[18].State())
{
if(!m_chart.ShowLastLine())
m_chart.ShowLastLine(true);
}
else
{
if(m_chart.ShowLastLine())
m_chart.ShowLastLine(false);
}
//--- Set Show Separator
if(m_button[19].State())
{
if(!m_chart.ShowPeriodSep())
m_chart.ShowPeriodSep(true);
}
else
{
if(m_chart.ShowPeriodSep())
m_chart.ShowPeriodSep(false);
}
//--- Set Show Grid
if(m_button[20].State())
{
if(!m_chart.ShowGrid())
m_chart.ShowGrid(true);
}
else
{
if(m_chart.ShowGrid())
m_chart.ShowGrid(false);
}
//--- Set Show Objects Descriptor
if(m_button[21].State())
{
if(!m_chart.ShowObjectDescr())
m_chart.ShowObjectDescr(true);
}
else
{
if(m_chart.ShowObjectDescr())
m_chart.ShowObjectDescr(false);
}
//--- Set Show Not Volumes
if(m_button[22].State())
{
m_chart.ShowVolumes((ENUM_CHART_VOLUME_MODE)0);
m_button[22].State(false);
}
//--- Set Show Tick Volumes
if(m_button[23].State())
{
m_chart.ShowVolumes((ENUM_CHART_VOLUME_MODE)1);
m_button[23].State(false);
}
//--- Set Show Real Volumes
if(m_button[24].State())
{
m_chart.ShowVolumes((ENUM_CHART_VOLUME_MODE)2);
m_button[24].State(false);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelTimeframes. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelTimeframes(void)
{
int i,j;
//--- No Set Period PERIOD_MN
if(m_button_tf[19].State())
m_button_tf[19].State(false);
//--- Set Period
for(i=0;i<20;i++)
if(m_button_tf[i].State())
{
if(m_chart.Period()!=tf_int[i])
m_chart.SetSymbolPeriod(m_chart.Symbol(),(ENUM_TIMEFRAMES)tf_int[i]);
else
continue;
for(j=0;j<20;j++)
if(i!=j)
m_button_tf[j].State(false);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelSymbols. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelSymbols(void)
{
int i,j;
//--- Set Symbol
for(i=0;i<m_num_symbols;i++)
if(m_button_sym[i].State())
{
if(m_chart.Symbol()!=SymbolName(i,true))
{
m_chart.SetSymbolPeriod(SymbolName(i,true),m_chart.Period());
//--- by changing the symbol switch OFF ScaleFix if it is ON
m_button[8].State(false);
}
else
continue;
for(j=0;j<m_num_symbols;j++)
if(i!=j)
m_button_sym[j].State(false);
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelColors. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelColors(void)
{
int i;
color c;
static color yellow_on_black[]={clrBlack,clrWhite,clrLightSlateGray,clrYellow,clrYellow,clrBlack,clrWhite,clrYellow,clrLimeGreen,clrLightSlateGray,clrRed,C'0,192,0',clrRed};
static color green_on_black[] ={clrBlack,clrWhite,clrLightSlateGray,clrLime,clrLime,clrBlack,clrWhite,clrLime,clrLimeGreen,clrLightSlateGray,clrRed,C'0,192,0',clrRed};
static color black_on_white[] ={clrWhite,clrBlack,clrSilver,clrBlack,clrBlack,clrWhite,clrBlack,clrBlack,clrGreen,clrSilver,clrSilver,clrSilver,clrOrangeRed};
static int color_id[]=
{
CHART_COLOR_BACKGROUND,CHART_COLOR_FOREGROUND,CHART_COLOR_GRID,CHART_COLOR_CHART_UP,
CHART_COLOR_CHART_DOWN,CHART_COLOR_CANDLE_BULL,CHART_COLOR_CANDLE_BEAR,CHART_COLOR_CHART_LINE,
CHART_COLOR_VOLUME,CHART_COLOR_BID,CHART_COLOR_ASK,CHART_COLOR_LAST,CHART_COLOR_STOP_LEVEL
};
//---
if(m_button[25].State())
{
//--- Set "Yellow on Black"
m_button[25].State(false);
for(i=0;i<13;i++)
m_chart.SetInteger((ENUM_CHART_PROPERTY_INTEGER)color_id[i],yellow_on_black[i]);
}
if(m_button[26].State())
{
//--- Set "Green on Black"
m_button[26].State(false);
for(i=0;i<13;i++)
m_chart.SetInteger((ENUM_CHART_PROPERTY_INTEGER)color_id[i],green_on_black[i]);
}
if(m_button[27].State())
{
//--- Set "Black on White" palette
m_button[27].State(false);
for(i=0;i<13;i++)
m_chart.SetInteger((ENUM_CHART_PROPERTY_INTEGER)color_id[i],black_on_white[i]);
}
//--- tuning colors
color color_label=(color)(m_chart.ColorBackground()^0xFFFFFF);
for(i=7;i<NUM_LABELS;i++)
m_label[i].Color(color_label);
for(i=0;i<13;i++)
{
c=(color)m_chart.GetInteger((ENUM_CHART_PROPERTY_INTEGER)color_id[i]);
m_edit_color[i].BackColor(c);
m_edit_rgb[i][0].Description((string)((c&0xFF0000)>>16));
m_edit_rgb[i][1].Description((string)((c&0xFF00)>>8));
m_edit_rgb[i][2].Description((string)(c&0xFF));
}
}
//+------------------------------------------------------------------+
//| Method CheckPanelReadOnly. |
//+------------------------------------------------------------------+
void CChartSample::CheckPanelReadOnly(void)
{
int i,j;
//--- Get VisibleBars
m_edit[7].Description((string)m_chart.VisibleBars());
//--- Get WindowsTotal
m_edit[8].Description((string)(j=m_chart.WindowsTotal()));
j%=6;
//--- Get WindowIsVisible[i]
for(i=0;i<j;i++)
m_edit[9+i].Description((string)m_chart.WindowIsVisible(i));
//--- Get WindowHandle
m_edit[14].Description((string)m_chart.WindowHandle());
//--- Get FirstVisibleBar
m_edit[15].Description((string)m_chart.FirstVisibleBar());
//--- Get WidthInBars
m_edit[16].Description((string)m_chart.WidthInBars());
//--- Get WidthInPixels
m_edit[17].Description((string)m_chart.WidthInPixels());
//--- Get HeightInPixels[i]
for(i=0;i<j;i++)
m_edit[18+i].Description((string)m_chart.HeightInPixels(i));
//--- Get PriceMin[i]
for(i=0;i<j;i++)
m_edit[23+i].Description(DoubleToString(m_chart.PriceMin(i),4));
//--- Get PriceMax[i]
for(i=0;i<j;i++)
m_edit[28+i].Description(DoubleToString(m_chart.PriceMax(i),4));
//--- Get WindowOnDropped
m_edit[33].Description((string)m_chart.WindowOnDropped());
//--- Get PriceOnDropped
m_edit[34].Description(DoubleToString(m_chart.PriceOnDropped(),4));
//--- Get TimeOnDropped
m_edit[35].Description(TimeToString(m_chart.TimeOnDropped()));
//--- Get XOnDropped
m_edit[36].Description((string)m_chart.XOnDropped());
//--- YOnDropped
m_edit[37].Description((string)m_chart.YOnDropped());
}
//+------------------------------------------------------------------+
//| Method Init. |
//+------------------------------------------------------------------+
bool CChartSample::Init(void)
{
int i,j,x;
int sx,sy=16;
color color_label;
//---
if((m_num_symbols=SymbolsTotal(true))==0)
return(false);
//---
if(m_chart.Open(SymbolName(0,true),PERIOD_M1)==0)
{
printf("Chart not created");
return(false);
}
//--- tuning colors
color_label=(color)(m_chart.ColorBackground()^0xFFFFFF);
//--- create m_panel[]
for(i=0;i<NUM_PANELS;i++)
{
m_panel[i].Create(m_chart.ChartId(),"Panel"+IntegerToString(i),0,10,sy,150,16);
m_panel[i].Description(p_str[i]);
m_panel[i].Color(clrBlack);
m_panel[i].FontSize(8);
m_panel[i].State(true);
sy+=m_panel[i].Y_Size();
}
sy=4;
//--- creation m_label[]
for(i=7;i<NUM_LABELS;i++)
{
if((m_label[i]=new CChartObjectLabel)==NULL)
return(false);
m_label[i].Create(m_chart.ChartId(),"Label"+IntegerToString(i),0,l_x[i],sy+l_y[i]);
m_label[i].Description(l_str[i]);
m_label[i].Color(color_label);
if(i>=7)
m_label[i].FontSize(8);
if(l_pan[i]<NUM_PANELS)
m_panel[l_pan[i]].Attach(m_label[i]);
}
//--- creation m_button[]
for(i=0;i<NUM_BUTTONS;i++)
{
if((m_button[i]=new CChartObjectButton)==NULL)
return(false);
m_button[i].Create(m_chart.ChartId(),"Button"+IntegerToString(i),0,b_x[i],sy+b_y[i],b_sizeX[i],b_sizeY[i]);
m_button[i].Description(b_str[i]);
m_button[i].Color(clrBlack);
m_button[i].FontSize(8);
if(b_pan[i]<NUM_PANELS)
m_panel[b_pan[i]].Attach(m_button[i]);
}
//--- creation m_edit[]
for(i=0;i<NUM_EDITS;i++)
{
if((m_edit[i]=new CChartObjectEdit)==NULL)
return(false);
m_edit[i].Create(m_chart.ChartId(),"Edit"+IntegerToString(i),0,e_x[i],sy+e_y[i],e_sizeX[i],16);
m_edit[i].FontSize(8);
if(e_pan[i]<NUM_PANELS)
m_panel[e_pan[i]].Attach(m_edit[i]);
}
//--- creation m_edit_color[] and m_edit_rgb[][]
for(i=0;i<13;i++)
{
if((m_edit_color[i]=new CChartObjectEdit)==NULL)
return(false);
m_edit_color[i].Create(m_chart.ChartId(),"EditColor"+IntegerToString(i),0,80,20+20*i,16,16);
m_edit_color[i].FontSize(8);
m_panel[6].Attach(m_edit_color[i]);
for(j=0;j<3;j++)
{
if((m_edit_rgb[i][j]=new CChartObjectEdit)==NULL)
return(false);
m_edit_rgb[i][j].Create(m_chart.ChartId(),"EditRGB"+IntegerToString(i)+"_"+IntegerToString(j),0,100+80*j,20+20*i,50,16);
m_edit_rgb[i][j].FontSize(8);
m_panel[6].Attach(m_edit_rgb[i][j]);
}
}
//--- creation m_button_tf[]
for(i=0;i<20;i++)
{
x=28*(i%11);
if(i%11<4)
{
sx=26;
x-=2*(i%11);
}
else
{
x-=8;
sx=28;
}
if(i>16)
x+=28;
if(i>17)
x+=28;
if((m_button_tf[i]=new CChartObjectButton)==NULL)
return(false);
m_button_tf[i].Create(m_chart.ChartId(),"ButtonTF"+IntegerToString(i),0,20+x,16*(i/11),sx,16);
if(m_chart.Period()==tf_int[i])
m_button_tf[i].State(true);
m_button_tf[i].Description(tf_str[i]);
m_button_tf[i].Color(clrBlue);
m_button_tf[i].FontSize(8);
m_panel[4].Attach(m_button_tf[i]);
}
//--- creation m_button_sym[]
ArrayResize(m_button_sym,m_num_symbols);
for(i=0;i<m_num_symbols;i++)
{
if((m_button_sym[i]=new CChartObjectButton)==NULL)
return(false);
m_button_sym[i].Create(m_chart.ChartId(),"ButtonS"+IntegerToString(i),0,20+60*(i%5),16*(i/5),60,16);
m_button_sym[i].Description(SymbolName(i,true));
if(m_chart.Symbol()==SymbolName(i,true))
m_button_sym[i].State(true);
m_button_sym[i].Color(clrGreen);
m_button_sym[i].FontSize(8);
m_panel[5].Attach(m_button_sym[i]);
}
//--- initial installation of the objects
m_button[0].State(true);
m_button[1].State(false);
m_button[2].State(false);
m_button[3].State(m_chart.AutoScroll());
m_button[4].State(m_chart.Shift());
m_button[5].State(m_chart.Foreground());
m_button[6].State(false);
m_button[7].State(false);
m_button[8].State(m_chart.ScaleFix());
m_button[9].State(m_chart.ScaleFix_11());
m_button[10].State(false);
m_button[11].State(false);
m_button[12].State(false);
m_button[13].State(false);
m_button[14].State(m_chart.ScalePPB());
m_button[15].State(m_chart.ShowOHLC());
m_button[16].State(m_chart.ShowLineBid());
m_button[17].State(m_chart.ShowLineAsk());
m_button[18].State(m_chart.ShowLastLine());
m_button[19].State(m_chart.ShowPeriodSep());
m_button[20].State(m_chart.ShowGrid());
m_button[21].State(m_chart.ShowObjectDescr());
m_button[22].State(false);
//--- initial installation of the chart
if(m_chart.Shift())
m_edit[0].Description(DoubleToString(m_chart.ShiftSize()));
else
m_edit[0].Description("");
m_edit[1].Description(IntegerToString(m_chart.Scale()));
m_edit[2].Description(m_edit[0].Description());
m_edit[3].Description(m_edit[1].Description());
if(m_chart.ScaleFix())
{
m_edit[4].Description(DoubleToString(m_chart.PriceMax(0),4));
m_edit[5].Description(DoubleToString(m_chart.PriceMin(0),4));
}
else
{
m_edit[4].Description("");
m_edit[5].Description("");
}
if(m_chart.ScalePPB())
m_edit[6].Description(DoubleToString(m_chart.PointsPerBar(),4));
else
m_edit[6].Description("");
//--- tune m_panel[]
sy=16;
for(i=0;i<NUM_PANELS;i++)
{
m_panel[i].Y_Distance(sy);
sy+=m_panel[i].Y_Size();
}
//--- redraw chart
m_chart.Redraw();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method Deinit. |
//+------------------------------------------------------------------+
void CChartSample::Deinit(void)
{
}
//+------------------------------------------------------------------+
//| Method Processing. |
//+------------------------------------------------------------------+
void CChartSample::Processing(void)
{
int i;
int sy=0;
//---
for(i=0;i<NUM_PANELS;i++)
if(m_panel[i].CheckState())
{
sy=m_panel[i].Y_Distance()+m_panel[i].Y_Size();
i++;
break;
}
for(;i<NUM_PANELS;i++)
{
m_panel[i].Y_Distance(sy);
sy+=m_panel[i].Y_Size();
}
CheckPanelModes();
CheckPanelAnothers();
CheckPanelScales();
CheckPanelShows();
CheckPanelTimeframes();
CheckPanelSymbols();
CheckPanelColors();
CheckPanelReadOnly();
//--- chart redrawn (with the processing of events)
m_chart.Redraw();
Sleep(50);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
//--- call init function
if(ExtScript.Init())
{
//--- cycle until the script is not halted
while(!IsStopped())
ExtScript.Processing();
}
//--- call deinit function
ExtScript.Deinit();
//---
return(0);
}
//+------------------------------------------------------------------+
+187
View File
@@ -0,0 +1,187 @@
//+------------------------------------------------------------------+
//| Sphere.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//+------------------------------------------------------------------+
//| Class CSphere. |
//| Appointment: Class of the graphical object "Sphere". |
//+------------------------------------------------------------------+
class CSphere : public CArrayObj
{
private:
int m_id; // sphere idintifier
color m_color; // sphere color
int m_num_parallel; // number of parallels
int m_num_meridian; // number of meridians
int m_radius; // sphere radius in pixels
int m_center_X; // coordinate of the center X
int m_center_Y; // coordinate of the center Y
CSphere *m_orbite_center; // "sun"
double m_orbite_radius; // orbital radius
double m_orbite_fi_X; // angle of inclination to the axis X
double m_orbite_fi_Y; // angle of inclination to the axis Y
double m_orbite_fi_Z; // angle of inclination to the axis Z
double m_d_fi_orb; // angular velocity of the orbit
//--- working variables
double m_fi_orb;
double m_fi_x;
double m_fi_y;
double m_fi_z;
public:
CSphere(void);
~CSphere(void);
//--- methods of access to protected data
int CenterX(void) const { return(m_center_X); }
int CenterY(void) const { return(m_center_Y); }
//---
bool Create(const int id,const color c,const int x,const int y,const int r,const int p,const int m,const string str);
void SetOrbite(CSphere *sun,const double fi_x,const double fi_y,const double fi_z,const double d_fi_orb);
void Recalculate(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSphere::CSphere(void) : m_id(0),
m_color(0),
m_num_parallel(0),
m_num_meridian(0),
m_radius(0),
m_center_X(0),
m_center_Y(0),
m_orbite_center(NULL),
m_orbite_radius(0.0),
m_orbite_fi_X(0.0),
m_orbite_fi_Y(0.0),
m_orbite_fi_Z(0.0),
m_d_fi_orb(0.0),
m_fi_orb(0.0),
m_fi_x(0.0),
m_fi_y(0.0),
m_fi_z(0.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSphere::~CSphere(void)
{
}
//+------------------------------------------------------------------+
//| Create object |
//+------------------------------------------------------------------+
bool CSphere::Create(const int id,const color c,const int x,const int y,const int r,const int p,const int m,const string str)
{
CArrayObj *arr;
CChartObjectLabel *label;
//---
m_id=id;
m_color =c;
m_num_parallel=(p>r/3) ? r/3 : p;
m_num_meridian=(m>r/3) ? r/3 : m;
m_radius =r;
m_center_X =x;
m_center_Y =y;
if(!Reserve(p)) return(false);
//--- loop parallels
for(int i=0;i<p;i++)
{
arr=new CArrayObj;
if(arr==NULL)
return(false);
if(!arr.Reserve(m))
return(false);
//--- loop meridians
for(int j=0;j<m;j++)
{
label=new CChartObjectLabel;
if(label==NULL)
return(false);
label.Create(0,"ar"+string(id)+"_"+string(j)+"_"+string(i),0,0,0);
label.Color(m_color);
label.Description(str);
arr.Add(label);
}
Add(arr);
}
return(true);
}
//+------------------------------------------------------------------+
//| Setting |
//+------------------------------------------------------------------+
void CSphere::SetOrbite(CSphere *sun,const double fi_x,const double fi_y,const double fi_z,const double d_fi_orb)
{
m_orbite_center=sun;
m_orbite_fi_X=fi_x;
m_orbite_fi_Y=fi_y;
m_d_fi_orb=d_fi_orb;
m_orbite_fi_Z=fi_z;
m_orbite_radius=MathSqrt(MathPow(m_center_X-m_orbite_center.CenterX(),2)+MathPow(m_center_Y-m_orbite_center.CenterY(),2))/2;
}
//+------------------------------------------------------------------+
//| Recalculation of the sphere. |
//+------------------------------------------------------------------+
void CSphere::Recalculate(void)
{
CArrayObj *arr;
CChartObjectLabel *label;
//---
double d_fi_m,d_fi_p;
double x,y,z;
int i,q;
double idx3=0;
double idx4=0;
//---
d_fi_m=2*M_PI/m_num_meridian;
d_fi_p=M_PI/m_num_parallel;
//---
idx3=idx4;
if(m_orbite_center!=NULL)
{
//--- calculation of the coordinates of the dynamic center of the orbit
m_fi_orb+=m_d_fi_orb;
m_center_X=(int)(m_orbite_center.CenterX()+m_orbite_radius*(MathSin(m_fi_orb)+MathCos(m_orbite_fi_X)*MathSin(m_orbite_fi_Y)));
m_center_Y=(int)(m_orbite_center.CenterY()+m_orbite_radius*(MathCos(m_fi_orb)+MathSin(m_orbite_fi_X)*MathCos(m_orbite_fi_Y)));
}
q=-m_num_parallel/2-1;
//--- loop parallels
for(int j=0;j<m_num_parallel;j++)
{
q++;
arr=At(j);
//--- loop meridians
for(i=0;i<m_num_meridian;i++)
{
//--- calculation of the coordinates of the point of excluding traffic
x=m_radius*MathSin(d_fi_m*i)*MathCos(d_fi_p*q);
y=m_radius*MathSin(d_fi_p*q);
z=m_radius*MathCos(d_fi_m*i)*MathCos(d_fi_p*q);
//--- recalculation of the coordinates of the point of view of traffic
label=arr.At(i);
label.X_Distance(m_center_X+x2d_(x,y,z,m_fi_x,m_fi_y,m_fi_z));
label.Y_Distance(m_center_Y+y2d_(x,y,z,m_fi_x,m_fi_y,m_fi_z));
}
idx3=idx3+0.5*m_id;
}
//---
m_fi_z=m_fi_z+MathSin(idx3*0.08)/32+MathCos(idx3*0.16)*0.01;
m_fi_x=m_fi_x+MathCos(idx3*0.08)*0.016+MathCos(idx3*0.12)*0.008;
}
//+------------------------------------------------------------------+
//| auxiliary function |
//+------------------------------------------------------------------+
int x2d_(double x_,double y_,double z_,double fi_x_,double fi_y_,double fi_z_)
{
return((int)(x_*MathCos(fi_z_)+y_*MathSin(fi_z_)));
}
//+------------------------------------------------------------------+
//| auxiliary function |
//+------------------------------------------------------------------+
int y2d_(double x_,double y_,double z_,double fi_x_,double fi_y_,double fi_z_)
{
return((int)((-x_*MathSin(fi_z_)+y_*MathCos(fi_z_))*MathCos(fi_x_)+z_*MathSin(fi_x_)));
}
//+------------------------------------------------------------------+
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,239 @@
//+------------------------------------------------------------------+
//| BitonicSort.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//--- COpenCL class
#include <OpenCL/OpenCL.mqh>
#resource "Kernels/bitonicsort.cl" as string cl_program
//+------------------------------------------------------------------+
//| QuickSortAscending |
//+------------------------------------------------------------------+
//| The function sorts array[] QuickSort algorithm. |
//| |
//| Arguments: |
//| array : Array with values to sort |
//| first : First element index |
//| last : Last element index |
//| |
//| Return value: None |
//+------------------------------------------------------------------+
void QuickSortAscending(double &array[],int first,int last)
{
int i,j;
double p_double,t_double;
//---
if(first<0 || last<0)
return;
//---
i=first;
j=last;
while(i<last)
{
p_double=array[(first+last)>>1];
while(i<j)
{
while(array[i]<p_double)
{
if(i==ArraySize(array)-1)
break;
i++;
}
while(array[j]>p_double)
{
if(j==0)
break;
j--;
}
if(i<=j)
{
//-- swap elements i and j
t_double=array[i];
array[i]=array[j];
array[j]=t_double;
i++;
if(j==0)
break;
j--;
}
}
if(first<j)
QuickSortAscending(array,first,j);
first=i;
j=last;
}
}
//+------------------------------------------------------------------+
//| QuickSort_CPU |
//+------------------------------------------------------------------+
bool QuickSort_CPU(double &data_array[],ulong &time_cpu)
{
int data_count=ArraySize(data_array);
//---
if(data_count<=1)
return(false);
//--- sort values on CPU
time_cpu=GetMicrosecondCount();
QuickSortAscending(data_array,0,data_count-1);
time_cpu=ulong((GetMicrosecondCount()-time_cpu)/1000);
//---
return(true);
}
//+------------------------------------------------------------------+
//| BitonicSort_GPU |
//+------------------------------------------------------------------+
bool BitonicSort_GPU(COpenCL &OpenCL,double &data_array[],ulong &time_gpu)
{
int data_count=ArraySize(data_array);
//---
if(data_count<=1)
return(false);
//--- check support working with double
if(!OpenCL.SupportDouble())
{
PrintFormat("Working with double (cl_khr_fp64) is not supported on the device.");
return(false);
}
OpenCL.SetKernelsCount(1);
OpenCL.KernelCreate(0,"BitonicSort_GPU");
//--- create buffers
OpenCL.SetBuffersCount(1);
if(!OpenCL.BufferFromArray(0,data_array,0,data_count,CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferFromArray for data array. Error code=%d",GetLastError());
return(false);
}
OpenCL.SetArgumentBuffer(0,0,0);
//---
uint work_offset[1]= {0};
uint global_size[1];
uint passes_total=0;
uint stages_total=0;
global_size[0]=data_count>>1;
for(uint temp=data_count; temp>1; temp>>=1)
stages_total++;
//--- GPU calculation start
time_gpu=GetMicrosecondCount();
for(uint stage=0; stage<stages_total; stage++)
{
//--- set stage of the algorithm
OpenCL.SetArgument(0,1,stage);
for(uint pass=0; pass<stage+1; pass++)
{
//--- set pass of the current stage
OpenCL.SetArgument(0,2,pass);
//--- execute kernel
if(!OpenCL.Execute(0,1,work_offset,global_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
else
passes_total++;
}
}
//---
if(!OpenCL.BufferRead(0,data_array,0,0,data_count))
{
PrintFormat("Error in BufferRead for data array with %d size. Error code=%d",data_count,GetLastError());
return(false);
}
//--- GPU calculation finish
time_gpu=ulong((GetMicrosecondCount()-time_gpu)/1000);
PrintFormat("Bitonic sort finished. Total stages=%d, total passes=%d",stages_total,passes_total);
//---
return(true);
}
//+------------------------------------------------------------------+
//| PrepareDataArray |
//+------------------------------------------------------------------+
bool PrepareDataArray(long global_memory_size,double &data[],int &data_count)
{
int pwr_max=(int)(MathLog(global_memory_size/2/sizeof(double))/MathLog(2));
int pwr=(int)MathMax(15,pwr_max-4);
//--- prepare array and generate random data
data_count=(int)MathPow(2,pwr);
if(data_count<4096)
data_count=4096;
if(data_count>4*1024*1024)
data_count=4*1024*1024;
Print(data_count," elements in double array");
//---
if(ArrayResize(data,data_count)<data_count)
{
Print("Error in ArrayResize. Error code=",GetLastError());
return(false);
}
for(int i=0; i<data_count; i++)
data[i]=(double)(100000000*MathRand()/32767.0);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
COpenCL OpenCL;
//--- OpenCL
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return;
}
//---
long global_memory_size=0;
if(!OpenCL.GetGlobalMemorySize(global_memory_size))
{
Print("Error in request of global memory size. Error code=",GetLastError());
return;
}
//--- prepare array with random values
double data_cpu[];
int data_count=0;
if(PrepareDataArray(global_memory_size,data_cpu,data_count)==false)
return;
//--- copy array values for sorting on GPU
double data_gpu[];
if(ArrayCopy(data_gpu,data_cpu,0,0,data_count)!=data_count)
return;
//--- Quick sort values using CPU
ulong time_cpu=0;
if(!QuickSort_CPU(data_cpu,time_cpu))
return;
//--- Bitonic sort values using GPU
ulong time_gpu=0;
if(!BitonicSort_GPU(OpenCL,data_gpu,time_gpu))
return;
//--- remove OpenCL objects
OpenCL.Shutdown();
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
PrintFormat("time CPU=%d ms, time GPU =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- check calculations
double total_error=0;
for(int i=0; i<data_count; i++)
total_error+=MathAbs(data_gpu[i]-data_cpu[i]);
PrintFormat("Total error = %f",total_error);
}
//+------------------------------------------------------------------+
Binary file not shown.
+354
View File
@@ -0,0 +1,354 @@
//+------------------------------------------------------------------+
//| FFT.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Math/Stat/Math.mqh>
#include <OpenCL/OpenCL.mqh>
#resource "Kernels/fft.cl" as string cl_program
#define kernel_init "fft_init"
#define kernel_stage "fft_stage"
#define kernel_scale "fft_scale"
#define NUM_POINTS 1024
#define FFT_DIRECTION 1
//+------------------------------------------------------------------+
//| Fast Fourier transform and its inverse (both recursively) |
//| Copyright (C) 2004, Jerome R. Breitenbach. All rights reserved. |
//| Reference: |
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
//| Recursive direct FFT transform |
//+------------------------------------------------------------------+
void fft(const int N,double &x_real[],double &x_imag[],double &X_real[],double &X_imag[])
{
//--- prepare temporary arrays
double XX_real[],XX_imag[];
ArrayResize(XX_real,N);
ArrayResize(XX_imag,N);
//--- calculate FFT by a recursion
fft_rec(N,0,1,x_real,x_imag,X_real,X_imag,XX_real,XX_imag);
}
//+------------------------------------------------------------------+
//| Recursive inverse FFT transform |
//+------------------------------------------------------------------+
void ifft(const int N,double &x_real[],double &x_imag[],double &X_real[],double &X_imag[])
{
int N2=N/2; // half the number of points in IFFT
//--- calculate IFFT via reciprocity property of DFT
fft(N,X_real,X_imag,x_real,x_imag);
x_real[0]=x_real[0]/N;
x_imag[0]=x_imag[0]/N;
x_real[N2]=x_real[N2]/N;
x_imag[N2]=x_imag[N2]/N;
for(int i=1; i<N2; i++)
{
double tmp0=x_real[i]/N;
double tmp1=x_imag[i]/N;
x_real[i]=x_real[N-i]/N;
x_imag[i]=x_imag[N-i]/N;
x_real[N-i]=tmp0;
x_imag[N-i]=tmp1;
}
}
//+------------------------------------------------------------------+
//| FFT recursion |
//+------------------------------------------------------------------+
void fft_rec(const int N,const int offset,const int delta,double &x_real[],double &x_imag[],double &X_real[],double &X_imag[],double &XX_real[],double &XX_imag[])
{
static const double TWO_PI=(double)(2*M_PI);
int N2=N/2; // half the number of points in FFT
int k00,k01,k10,k11; // indices for butterflies
if(N!=2)
{
//--- perform recursive step
//--- calculate two (N/2)-point DFT's
fft_rec(N2,offset,2*delta,x_real,x_imag,XX_real,XX_imag,X_real,X_imag);
fft_rec(N2,offset+delta,2*delta,x_real,x_imag,XX_real,XX_imag,X_real,X_imag);
//--- combine the two (N/2)-point DFT's into one N-point DFT
for(int k=0; k<N2; k++)
{
k00 = offset + k*delta;
k01 = k00 + N2*delta;
k10 = offset + 2*k*delta;
k11 = k10 + delta;
double cs=(double)MathCos(TWO_PI*k/(double)N);
double sn=(double)MathSin(TWO_PI*k/(double)N);
double tmp0 = cs*XX_real[k11] + sn*XX_imag[k11];
double tmp1 = cs*XX_imag[k11] - sn*XX_real[k11];
X_real[k01] = XX_real[k10] - tmp0;
X_imag[k01] = XX_imag[k10] - tmp1;
X_real[k00] = XX_real[k10] + tmp0;
X_imag[k00] = XX_imag[k10] + tmp1;
}
}
else
{
//--- perform 2-point DFT
k00=offset;
k01=k00+delta;
X_real[k01] = x_real[k00] - x_real[k01];
X_imag[k01] = x_imag[k00] - x_imag[k01];
X_real[k00] = x_real[k00] + x_real[k01];
X_imag[k00] = x_imag[k00] + x_imag[k01];
}
}
//+------------------------------------------------------------------+
//| FFT_CPU |
//+------------------------------------------------------------------+
bool FFT_CPU(int direction,int power,double &data_real[],double &data_imag[],ulong &time_cpu)
{
//--- calculate the number of points
int N=1;
for(int i=0;i<power;i++)
N*=2;
//---prepare temporary arrays
double XX_real[],XX_imag[];
ArrayResize(XX_real,N);
ArrayResize(XX_imag,N);
//--- CPU calculation start
time_cpu=GetMicrosecondCount();
if(direction>0)
fft(N,data_real,data_imag,XX_real,XX_imag);
else
ifft(N,XX_real,XX_imag,data_real,data_imag);
//--- CPU calculation finished
time_cpu=ulong((GetMicrosecondCount()-time_cpu));
//--- copy calculated data
ArrayCopy(data_real,XX_real,0,0,WHOLE_ARRAY);
ArrayCopy(data_imag,XX_imag,0,0,WHOLE_ARRAY);
//---
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool ExecutionWait(COpenCL& OpenCL,int kernel_index)
{
for(int i=0;;)
{
ENUM_OPENCL_EXECUTION_STATUS status=OpenCL.ExecutionStatus(kernel_index);
if(status==CL_COMPLETE)
{
Print("i=",i);
return(true);
}
if(status<0 || IsStopped())
break;
if(++i%10000==0)
{
Print("running... i=",i," execute_status=",status);
Sleep(1);
}
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| FFT_GPU |
//+------------------------------------------------------------------+
bool FFT_GPU(int direction,int power,double &data_real[],double &data_imag[],ulong &time_gpu)
{
//--- calculate the number of points
int num_points=1;
for(int i=0;i<power;i++)
num_points*=2;
//--- prepare data array for GPU calculation
double data[];
ArrayResize(data,2*num_points);
for(int i=0; i<num_points; i++)
{
data[2*i]=data_real[i];
data[2*i+1]=data_imag[i];
}
COpenCL OpenCL;
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//--- check support working with double
if(!OpenCL.SupportDouble())
{
PrintFormat("Working with double (cl_khr_fp64) is not supported on the device.");
return(false);
}
//--- create kernels
OpenCL.SetKernelsCount(3);
OpenCL.KernelCreate(0,kernel_init);
OpenCL.KernelCreate(1,kernel_stage);
OpenCL.KernelCreate(2,kernel_scale);
//--- create buffers
OpenCL.SetBuffersCount(2);
if(!OpenCL.BufferFromArray(0,data,0,2*num_points,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for input buffer. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferCreate(1,2*num_points*sizeof(double),CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferCreate for data buffer. Error code=%d",GetLastError());
return(false);
}
//--- determine maximum work-group size
int workgroup_size=(int)CLGetInfoInteger(OpenCL.GetKernel(0),CL_KERNEL_WORK_GROUP_SIZE);
//--- determine local memory size
uint local_mem_size=(uint)CLGetInfoInteger(OpenCL.GetContext(),CL_DEVICE_LOCAL_MEM_SIZE);
local_mem_size/=3;
local_mem_size*=2;
local_mem_size/=num_points;
local_mem_size*=num_points;
Print("local_mem_size=",local_mem_size);
int points_per_group=(int)local_mem_size/(2*sizeof(double));
if(points_per_group>num_points)
points_per_group=num_points;
//--- set kernel arguments
OpenCL.SetArgumentBuffer(0,0,0);
OpenCL.SetArgumentBuffer(0,1,1);
OpenCL.SetArgumentLocalMemory(0,2,local_mem_size);
OpenCL.SetArgument(0,3,points_per_group);
OpenCL.SetArgument(0,4,num_points);
OpenCL.SetArgument(0,5,direction);
//--- OpenCL execute settings
int task_dimension=1;
uint global_size=(uint)((num_points/points_per_group)*workgroup_size);
uint global_work_offset[1]={0};
uint global_work_size[1];
global_work_size[0]=global_size;
uint local_work_size[1];
local_work_size[0]=workgroup_size;
//--- GPU calculation start
time_gpu=GetMicrosecondCount();
//-- execute kernel fft_init
if(!OpenCL.Execute(0,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_init: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
if(!ExecutionWait(OpenCL,0))
return(false);
Print("fft_init passed");
//-- further stages of the FFT
if(num_points>points_per_group)
{
Print("num_points=",num_points," points_per_group=",points_per_group);
//--- set arguments for kernel 1
OpenCL.SetArgumentBuffer(1,0,1);
OpenCL.SetArgument(1,2,points_per_group);
OpenCL.SetArgument(1,3,direction);
for(int stage=2; stage<=num_points/points_per_group; stage<<=1)
{
OpenCL.SetArgument(1,1,stage);
//-- execute kernel fft_stage
if(!OpenCL.Execute(1,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_stage: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
Print("fft_stage ",stage," passed");
}
if(!ExecutionWait(OpenCL,1))
return(false);
}
//--- scale values if performing the inverse FFT
if(direction<0)
{
Print("direction=",direction);
OpenCL.SetArgumentBuffer(2,0,1);
OpenCL.SetArgument(2,1,points_per_group);
OpenCL.SetArgument(2,2,num_points);
//-- execute kernel fft_scale
if(!OpenCL.Execute(2,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_scale: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
if(!ExecutionWait(OpenCL,2))
return(false);
Print("fft_scale passed");
}
//--- read the results from GPU memory
if(!OpenCL.BufferRead(1,data,0,0,2*num_points))
{
PrintFormat("Error in BufferRead for data_buffer2. Error code=%d",GetLastError());
return(false);
}
Print("buffer read");
//--- GPU calculation finished
time_gpu=ulong((GetMicrosecondCount()-time_gpu));
//--- copy calculated data and release OpenCL handles
for(int i=0; i<num_points; i++)
{
data_real[i]=data[2*i];
data_imag[i]=data[2*i+1];
}
OpenCL.Shutdown();
Print("OpenCL shutdown");
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int datacount=NUM_POINTS;
int power=(int)(MathLog(NUM_POINTS)/M_LN2);
if(MathPow(2,power)!=datacount)
{
PrintFormat("Number of elements must be power of 2. Elements: %d",datacount);
return;
}
//--- prepare data for FFT calculation
double data_real[],data_imag[];
ArrayResize(data_real,datacount);
ArrayResize(data_imag,datacount);
for(int i=0; i<datacount; i++)
{
data_real[i]=(double)i;
data_imag[i]=0;
}
int direction=FFT_DIRECTION;
//--- data arrays for CPU calculation
double CPU_real[],CPU_imag[];
ArrayCopy(CPU_real,data_real,0,0,WHOLE_ARRAY);
ArrayCopy(CPU_imag,data_imag,0,0,WHOLE_ARRAY);
ulong time_cpu=0;
//--- calculate FFT using CPU
FFT_CPU(direction,power,CPU_real,CPU_imag,time_cpu);
//--- data arrays for GPU calculation
double GPU_real[],GPU_imag[];
ArrayCopy(GPU_real,data_real,0,0,WHOLE_ARRAY);
ArrayCopy(GPU_imag,data_imag,0,0,WHOLE_ARRAY);
ulong time_gpu=0;
//--- calculate FFT using GPU
if(!FFT_GPU(direction,power,GPU_real,GPU_imag,time_gpu))
{
PrintFormat("Error in calculation FFT on GPU.");
return;
}
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
PrintFormat("FFT calculation for %d points.",datacount);
PrintFormat("time CPU=%d microseconds, time GPU =%d microseconds, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- determine average error
double average_error=0.0;
for(int i=0; i<datacount; i++)
{
average_error += MathAbs(CPU_real[i]-GPU_real[i]);
average_error += MathAbs(CPU_imag[i]-GPU_imag[i]);
}
average_error=average_error/(datacount*2);
PrintFormat("Average error = %f",average_error);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,31 @@
//--- by default some GPU doesn't support doubles
//--- cl_khr_fp64 directive is used to enable work with doubles
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
//+-----------------------------------------------------------+
//| OpenCL kernel |
//| The bitonic sort kernel does an ascending sort. |
//+-----------------------------------------------------------+
//| R. Banger,K. Bhattacharyya, OpenCL Programming by Example:|
//| A comprehensive guide on OpenCL programming with examples |
//| PACKT Publishing, 2013. |
//+-----------------------------------------------------------+
__kernel void BitonicSort_GPU(__global double *data,const uint stage,const uint pass)
{
uint id=get_global_id(0);
uint distance = 1<<(stage-pass);
uint left_id =(id &(distance-1));
left_id+=(id>>(stage-pass))*(distance<<1);
uint right_id=left_id+distance;
double left_value=data[left_id];
double right_value=data[right_id];
uint same_direction=(id>>stage)&0x1;
uint temp = same_direction?right_id:temp;
right_id = same_direction?left_id:right_id;
left_id = same_direction?temp:left_id;
int compare_res=(left_value<right_value);
double greater = compare_res?right_value:left_value;
double lesser = compare_res?left_value:right_value;
data[left_id] = lesser;
data[right_id]= greater;
};
//+------------------------------------------------------------------+
@@ -0,0 +1,156 @@
//--- by default some GPU doesn't support doubles
//--- cl_khr_fp64 directive is used to enable work with doubles
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
//+------------------------------------------------------------------+
//| fft_init OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_init(__global double2 *in_data,
__global double2 *out_data,
__local double2 *l_data,
uint points_per_group,uint size,int dir)
{
uint4 br,index;
uint points_per_item,g_addr,l_addr,i,fft_index,stage,N2;
double2 x1,x2,x3,x4,sum12,diff12,sum34,diff34;
points_per_item=points_per_group/get_local_size(0);
l_addr = get_local_id(0)*points_per_item;
g_addr = get_group_id(0)*points_per_group + l_addr;
//--- load data from bit-reversed addresses and perform 4-point FFTs
for(i=0; i<points_per_item; i+=4)
{
index=(uint4)(g_addr,g_addr+1,g_addr+2,g_addr+3);
fft_index=size/2;
stage=1;
N2 =(uint)log2((double)size)-1;
br =(index<< N2) & fft_index;
br|=(index>> N2) & stage;
//--- bit-reverse addresses
while(N2>1)
{
N2-=2;
fft_index>>=1;
stage<<=1;
br |= (index << N2) & fft_index;
br |= (index >> N2) & stage;
}
//--- load global data
x1 = in_data[br.s0];
x2 = in_data[br.s1];
x3 = in_data[br.s2];
x4 = in_data[br.s3];
sum12=x1+x2;
diff12= x1-x2;
sum34 = x3+x4;
diff34=(double2)(x3.s1-x4.s1,x4.s0-x3.s0)*dir;
l_data[l_addr]=sum12+sum34;
l_data[l_addr+1] = diff12 + diff34;
l_data[l_addr+2] = sum12 - sum34;
l_data[l_addr+3] = diff12 - diff34;
l_addr += 4;
g_addr += 4;
}
//--- perform initial stages of the FFT - each of length N2*2
for(N2=4; N2<points_per_item; N2<<=1)
{
l_addr=get_local_id(0)*points_per_item;
for(fft_index=0; fft_index<points_per_item; fft_index+=2*N2)
{
x1=l_data[l_addr];
l_data[l_addr]+=l_data[l_addr+N2];
l_data[l_addr+N2]=x1-l_data[l_addr+N2];
for(i=1; i<N2; i++)
{
x3.s0=cos(M_PI_F*i/N2);
x3.s1=dir*sin(M_PI_F*i/N2);
x2=(double2)(l_data[l_addr+N2+i].s0*x3.s0+l_data[l_addr+N2+i].s1*x3.s1,l_data[l_addr+N2+i].s1*x3.s0-l_data[l_addr+N2+i].s0*x3.s1);
l_data[l_addr+N2+i]=l_data[l_addr+i]-x2;
l_data[l_addr+i]+=x2;
}
l_addr+=2*N2;
}
}
barrier(CLK_LOCAL_MEM_FENCE);
//--- perform FFT with other items in group - each of length N2*2
stage=2;
for(N2=points_per_item; N2<points_per_group; N2<<=1)
{
br.s0=(get_local_id(0)+(get_local_id(0)/stage)*stage) *(points_per_item/2);
size = br.s0 % (N2*2);
for(i=br.s0; i<br.s0+points_per_item/2; i++)
{
x3.s0=cos(M_PI_F*size/N2);
x3.s1=dir*sin(M_PI_F*size/N2);
x2=(double2)(l_data[N2+i].s0*x3.s0+l_data[N2+i].s1*x3.s1,l_data[N2+i].s1*x3.s0-l_data[N2+i].s0*x3.s1);
l_data[N2+i]=l_data[i]-x2;
l_data[i]+=x2;
size++;
}
stage<<=1;
barrier(CLK_LOCAL_MEM_FENCE);
}
//--- store results in global memory
l_addr = get_local_id(0)*points_per_item;
g_addr = get_group_id(0)*points_per_group + l_addr;
for(i=0; i<points_per_item; i+=4)
{
out_data[g_addr]=l_data[l_addr];
out_data[g_addr+1] = l_data[l_addr+1];
out_data[g_addr+2] = l_data[l_addr+2];
out_data[g_addr+3] = l_data[l_addr+3];
g_addr += 4;
l_addr += 4;
}
}
//+------------------------------------------------------------------+
//| fft_stage OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_stage(__global double2 *g_data,uint stage,uint points_per_group,int dir)
{
uint points_per_item,addr,N,ang,i;
double c,s;
double2 input1,input2,w;
points_per_item=points_per_group/get_local_size(0);
addr=(get_group_id(0)+(get_group_id(0)/stage)*stage)*(points_per_group/2)+get_local_id(0)*(points_per_item/2);
N=points_per_group*(stage/2);
ang=addr%(N*2);
for(i=addr; i<addr+points_per_item/2; i++)
{
c = cos(M_PI_F*ang/N);
s = dir*sin(M_PI_F*ang/N);
input1 = g_data[i];
input2 = g_data[i+N];
w=(double2)(input2.s0*c+input2.s1*s,input2.s1*c-input2.s0*s);
g_data[i]=input1+w;
g_data[i+N]=input1-w;
ang++;
}
}
//+------------------------------------------------------------------+
//| fft_scale OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_scale(__global double2 *g_data,uint points_per_group,uint scale)
{
uint points_per_item,addr,i;
points_per_item=points_per_group/get_local_size(0);
addr=get_group_id(0)*points_per_group+get_local_id(0)*points_per_item;
for(i=addr; i<addr+points_per_item; i++)
{
g_data[i]/=scale;
}
}
//+------------------------------------------------------------------+
@@ -0,0 +1,69 @@
//--- by default some GPU doesn't support doubles
//--- cl_khr_fp64 directive is used to enable work with doubles
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
//+-----------------------------------------------------------+
//| OpenCL kernel for matrix multiplication |
//| using global work groups |
//+-----------------------------------------------------------+
//| http://gpgpu-computing4.blogspot.ru/2009/09/ |
//| /matrix-multiplication-2-opencl.html |
//+-----------------------------------------------------------+
__kernel void MatrixMult_GPU1(__global double *matrix_a,
__global double *matrix_b,
__global double *matrix_c,
int rows_a,int cols_a,int cols_b)
{
int i=get_global_id(0);
int j=get_global_id(1);
double sum=0.0;
for(int k=0; k<cols_a; k++)
{
sum+=matrix_a[cols_a*i+k]*matrix_b[cols_b*k+j];
}
matrix_c[cols_b*i+j]=sum;
}
#define BLOCK_SIZE 10
//+-----------------------------------------------------------+
//| OpenCL kernel for matrix multiplication |
//| using local groups with common local memory |
//+-----------------------------------------------------------+
//| http://gpgpu-computing4.blogspot.ru/2009/10/ |
//| /matrix-multiplication-3-opencl.html |
//+-----------------------------------------------------------+
__kernel void MatrixMult_GPU2(__global double *matrix_a,
__global double *matrix_b,
__global double *matrix_c,
int rows_a,int cols_a,int cols_b)
{
int group_i=get_group_id(0);
int group_j=get_group_id(1);
int i=get_local_id(0);
int j=get_local_id(1);
int offset_b=BLOCK_SIZE*group_i;
int offset_a_start=cols_a*BLOCK_SIZE*group_j;
double sum=(float)0.0;
for(int offset_a=offset_a_start;
offset_a<offset_a_start+cols_a;
offset_a+=BLOCK_SIZE,
offset_b+=BLOCK_SIZE*cols_b)
{
__local double submatrix_a[BLOCK_SIZE][BLOCK_SIZE];
__local double submatrix_b[BLOCK_SIZE][BLOCK_SIZE];
submatrix_a[i][j]=matrix_a[offset_a+cols_a*i+j];
submatrix_b[i][j]=matrix_b[offset_b+cols_b*i+j];
barrier(CLK_LOCAL_MEM_FENCE);
for(int k=0; k<BLOCK_SIZE; k++)
sum+=submatrix_a[i][k]*submatrix_b[k][j];
barrier(CLK_LOCAL_MEM_FENCE);
}
int offset_c=BLOCK_SIZE*(cols_b*group_j+group_i);
matrix_c[offset_c+cols_b*i+j]=sum;
};
//+------------------------------------------------------------------+
@@ -0,0 +1,51 @@
//--- by default some GPU doesn't support doubles
//--- cl_khr_fp64 directive is used to enable work with doubles
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
//+------------------------------------------------------------------+
//| Morlet wavelet function |
//+------------------------------------------------------------------+
double Morlet(const double t)
{
return exp(-t*t*0.5)*cos(M_2_PI*t);
}
//+------------------------------------------------------------------+
//| OpenCL kernel function |
//+------------------------------------------------------------------+
__kernel void Wavelet_GPU(__global double *data,int datacount,int x_size,int y_size,__global double *result)
{
size_t i = get_global_id(0);
size_t j = get_global_id(1);
double a1=(double)10e-10;
double a2=(double)15.0;
double da=(a2-a1)/(double)y_size;
double db=((double)datacount-(double)0.0)/x_size;
double a=a1+j*da;
double b=0+i*db;
uint norm=1;
double B=(double)1.0; //Morlet
double B_inv=(double)1.0/B;
double a_inv=(double)1.0/a;
double dt=(double)1.0;
double coef=(double)0.0;
if(norm==0)
coef=sqrt(a_inv);
else
{
for(int k=0; k<datacount; k++)
{
double arg=(dt*k-b)*a_inv;
arg=-B_inv*arg*arg;
coef=coef+exp(arg);
}
}
double sum=(float)0.0;
for(int k=0; k<datacount; k++)
{
double arg=(dt*k-b)*a_inv;
sum+=data[k]*Morlet(arg);
}
sum=sum/coef;
uint pos=(int)(j*x_size+i);
result[pos]=sum;
};
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,225 @@
//+------------------------------------------------------------------+
//| MatrixMult.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <OpenCL/OpenCL.mqh>
//--- OpenCL kernels
#resource "Kernels/matrixmult.cl" as string cl_program
#define BLOCK_SIZE 10
//+------------------------------------------------------------------+
//| MatrixMult_CPU |
//+------------------------------------------------------------------+
bool MatrixMult_CPU(const double &matrix_a[],const double &matrix_b[],double &matrix_c[],
const int rows_a,const int cols_a,const int cols_b,ulong &time_cpu)
{
int size=rows_a*cols_b;
if(ArrayResize(matrix_c,size)!=size)
return(false);
//--- CPU calculation started
time_cpu=GetMicrosecondCount();
for(int i=0; i<rows_a; i++)
{
for(int j=0; j<cols_b; j++)
{
double sum=0.0;
for(int k=0; k<cols_a; k++)
{
sum+=matrix_a[cols_a*i+k]*matrix_b[cols_b*k+j];
}
matrix_c[cols_b*i+j]=sum;
}
}
//--- CPU calculation finished
time_cpu=ulong((GetMicrosecondCount()-time_cpu)/1000);
//---
return(true);
}
//+------------------------------------------------------------------+
//| MatrixMult_GPU |
//+------------------------------------------------------------------+
bool MatrixMult_GPU(const double &matrix_a[],const double &matrix_b[],double &matrix1_c[],double &matrix2_c[],
const int rows_a,const int cols_a,const int cols_b,const int size_a,const int size_b,
const int size_c,ulong &time1_gpu,ulong &time2_gpu)
{
const int task_dimension=2;
//--- prepare matrices for result
if(ArrayResize(matrix1_c,size_c)!=size_c || ArrayResize(matrix2_c,size_c)!=size_c)
return(false);
ArrayFill(matrix1_c,0,size_c,(double)0.0);
ArrayFill(matrix2_c,0,size_c,(double)0.0);
//--- OpenCL
COpenCL OpenCL;
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//--- check support working with double
if(!OpenCL.SupportDouble())
{
PrintFormat("Working with double (cl_khr_fp64) is not supported on the device.");
return(false);
}
//--- create kernels
OpenCL.SetKernelsCount(2);
OpenCL.KernelCreate(0,"MatrixMult_GPU1");
OpenCL.KernelCreate(1,"MatrixMult_GPU2");
//--- create buffers
OpenCL.SetBuffersCount(3);
//---
if(!OpenCL.BufferFromArray(0,matrix_a,0,size_a,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for matrix A. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferFromArray(1,matrix_b,0,size_b,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for matrix B. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferCreate(2,size_c*sizeof(double),CL_MEM_WRITE_ONLY))
{
PrintFormat("Error in BufferCreate for matrix C. Error code=%d",GetLastError());
return(false);
}
//--- prepare arguments for kernel 0
int kernel_index=0;
OpenCL.SetArgumentBuffer(kernel_index,0,0);
OpenCL.SetArgumentBuffer(kernel_index,1,1);
OpenCL.SetArgumentBuffer(kernel_index,2,2);
OpenCL.SetArgument(kernel_index,3,rows_a);
OpenCL.SetArgument(kernel_index,4,cols_a);
OpenCL.SetArgument(kernel_index,5,cols_b);
//--- set task dimension a_rows x b_cols
uint global_work_size[2];
//--- set dimensions
global_work_size[0]=rows_a;
global_work_size[1]=cols_b;
uint global_work_offset[2]={0,0};
//--- GPU calculation start kernel 0
time1_gpu=GetMicrosecondCount();
if(!OpenCL.Execute(kernel_index,task_dimension,global_work_offset,global_work_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferRead(2,matrix1_c,0,0,size_c))
{
PrintFormat("Error in BufferRead for matrix1 C. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finished
time1_gpu=ulong((GetMicrosecondCount()-time1_gpu)/1000);
//--- prepare arguments for kernel 1
kernel_index=1;
//--- set arguments
OpenCL.SetArgumentBuffer(kernel_index,0,0);
OpenCL.SetArgumentBuffer(kernel_index,1,1);
OpenCL.SetArgumentBuffer(kernel_index,2,2);
OpenCL.SetArgument(kernel_index,3,rows_a);
OpenCL.SetArgument(kernel_index,4,cols_a);
OpenCL.SetArgument(kernel_index,5,cols_b);
uint local_work_size[2];
local_work_size[0]=BLOCK_SIZE;
local_work_size[1]=BLOCK_SIZE;
//--- GPU calculation start, kernel1
time2_gpu=GetMicrosecondCount();
if(!OpenCL.Execute(kernel_index,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferRead(2,matrix2_c,0,0,size_c))
{
PrintFormat("Error in BufferRead for matrix2 C. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finished
time2_gpu=ulong((GetMicrosecondCount()-time2_gpu)/1000);
//--- remove OpenCL objects
OpenCL.Shutdown();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- matrix A 1000x2000
int rows_a=1000;
int cols_a=2000;
//--- matrix B 2000x1000
int rows_b=cols_a;
int cols_b=1000;
//--- matrix C 1000x1000
int rows_c=rows_a;
int cols_c=cols_b;
//--- matrix A: size=rows_a*cols_a
int size_a=rows_a*cols_a;
int size_b=rows_b*cols_b;
int size_c=rows_c*cols_c;
//--- prepare matrix A
double matrix_a[];
ArrayResize(matrix_a,rows_a*cols_a);
for(int i=0; i<rows_a; i++)
for(int j=0; j<cols_a; j++)
{
matrix_a[i*cols_a+j]=(double)(10*MathRand()/32767);
}
//--- prepare matrix B
double matrix_b[];
ArrayResize(matrix_b,rows_b*cols_b);
for(int i=0; i<rows_b; i++)
for(int j=0; j<cols_b; j++)
{
matrix_b[i*cols_b+j]=(double)(10*MathRand()/32767);
}
//--- CPU: calculate matrix product matrix_a*matrix_b
double matrix_c_cpu[];
ulong time_cpu=0;
if(!MatrixMult_CPU(matrix_a,matrix_b,matrix_c_cpu,rows_a,cols_a,cols_b,time_cpu))
{
PrintFormat("Error in calculation on CPU. Error code=%d",GetLastError());
return;
}
//--- calculate matrix product using GPU
double matrix_c_gpu_method1[];
double matrix_c_gpu_method2[];
ulong time_gpu_method1=0;
ulong time_gpu_method2=0;
if(!MatrixMult_GPU(matrix_a,matrix_b,matrix_c_gpu_method1,matrix_c_gpu_method2,rows_a,cols_a,cols_b,size_a,size_b,size_c,time_gpu_method1,time_gpu_method2))
{
PrintFormat("Error in calculation on GPU. Error code=%d",GetLastError());
return;
}
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio1=0;
double CPU_GPU_ratio2=0;
if(time_gpu_method1!=0)
CPU_GPU_ratio1=1.0*time_cpu/time_gpu_method1;
if(time_gpu_method2!=0)
CPU_GPU_ratio2=1.0*time_cpu/time_gpu_method2;
PrintFormat("time CPU=%d ms, time GPU global work groups =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu_method1,CPU_GPU_ratio1);
PrintFormat("time CPU=%d ms, time GPU local work groups =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu_method2,CPU_GPU_ratio2);
//--- check calculations
double total_error1=0;
double total_error2=0;
for(int i=0; i<rows_c; i++)
{
for(int j=0; j<cols_c; j++)
{
int pos=cols_c*i+j;
total_error1+=MathAbs(matrix_c_gpu_method1[pos]-matrix_c_cpu[pos]);
total_error2+=MathAbs(matrix_c_gpu_method2[pos]-matrix_c_cpu[pos]);
}
}
PrintFormat("Total error for method 1 = %f",total_error1);
PrintFormat("Total error for method 2 = %f",total_error2);
}
//+------------------------------------------------------------------+
Binary file not shown.
+419
View File
@@ -0,0 +1,419 @@
//+------------------------------------------------------------------+
//| Wavelet.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Math/Stat/Math.mqh>
#include <Graphics/Graphic.mqh>
#include <OpenCL/OpenCL.mqh>
#define CPU_DATA 1
#define GPU_DATA 2
#define SIZE_X 600
#define SIZE_Y 200
#resource "Kernels/wavelet.cl" as string cl_program
//+------------------------------------------------------------------+
//| CWavelet |
//+------------------------------------------------------------------+
class CWavelet
{
protected:
int m_xsize;
int m_ysize;
int m_maxcolor;
string m_res_name;
string m_label_name;
uchar m_palette[3*256];
//---
double m_data[];
double m_wavelet_data_CPU[];
double m_wavelet_data_GPU[];
uint m_bmp_buffer[];
COpenCL m_OpenCL;
double Morlet(const double t);
void ShowWaveletData(const double &m_wavelet_data[]);
int GetPalColor(const int index);
void Blend(const uint c1,const uint c2,const uint r1,const uint g1,const uint b1,const uint r2,const uint g2,const uint b2);
bool WaveletCPU(const double &data[],const int datacount,const int x_size,const int y_size,const int i,const int j,const bool norm,double &result[]);
public:
//---
void Create(const string name,const int x0,const int y0,const int x_size,const int y_size);
bool CalculateWavelet_CPU(const double &data[],uint &time);
bool CalculateWavelet_GPU(double &data[],uint &time);
void ShowWavelet(const int mode);
};
//+------------------------------------------------------------------+
//| Morlet wavelet function |
//+------------------------------------------------------------------+
double CWavelet::Morlet(const double t)
{
double v=t;
double res=MathExp(-v*v*0.5)*MathCos(M_2_PI*v);
return ((double)res);
}
//+------------------------------------------------------------------+
//| GetPalColor |
//+------------------------------------------------------------------+
int CWavelet::GetPalColor(const int index)
{
int ind=index;
if(ind<=0)
ind=0;
if(ind>255)
ind=255;
int idx=3*(ind);
uchar r=m_palette[idx];
uchar g=m_palette[idx+1];
uchar b=m_palette[idx+2];
//---
return(b+256*g+65536*r);
}
//+------------------------------------------------------------------+
//| Gradient palette |
//+------------------------------------------------------------------+
void CWavelet::Blend(const uint c1,const uint c2,const uint r1,const uint g1,const uint b1,const uint r2,const uint g2,const uint b2)
{
int n=int(c2-c1);
for(int i=0; i<=n; i++)
{
if((c1+i+2)<m_palette.Size())
{
m_palette[3*(c1+i)]=uchar(MathRound(1*(r1*(n-i)+r2*i)*1.0/n));
m_palette[3*(c1+i)+1]=uchar(MathRound(1*(g1*(n-i)+g2*i)*1.0/n));
m_palette[3*(c1+i)+2]=uchar(MathRound(1*(b1*(n-i)+b2*i)*1.0/n));
}
}
}
//+------------------------------------------------------------------+
//| Create |
//+------------------------------------------------------------------+
void CWavelet::Create(const string name,const int x0,const int y0,const int x_size,const int y_size)
{
//---
m_xsize=x_size;
m_ysize=y_size;
int size=m_xsize*m_ysize;
ArrayResize(m_bmp_buffer,size);
ArrayFill(m_bmp_buffer,0,size,0);
ArrayResize(m_wavelet_data_CPU,size);
ArrayResize(m_wavelet_data_GPU,size);
ArrayFill(m_wavelet_data_CPU,0,size,0);
ArrayFill(m_wavelet_data_GPU,0,size,0);
m_res_name=name;
m_label_name=m_res_name;
StringToUpper(m_label_name);
ResourceCreate(m_res_name,m_bmp_buffer,m_xsize,m_ysize,0,0,0,COLOR_FORMAT_XRGB_NOALPHA);
ObjectCreate(0,m_label_name,OBJ_BITMAP_LABEL,0,0,0);
ObjectSetInteger(0,m_label_name,OBJPROP_XDISTANCE,x0);
ObjectSetInteger(0,m_label_name,OBJPROP_YDISTANCE,y0);
ObjectSetString(0,m_label_name,OBJPROP_BMPFILE,NULL);
ObjectSetString(0,m_label_name,OBJPROP_BMPFILE,"::"+m_label_name);
//---
m_maxcolor=100;
Blend(0,20,0,0,95,0,0,246);
Blend(21,40,0,0,246,0,236,226);
Blend(41,60,0,236,226,226,246,0);
Blend(61,80,226,246,0,226,0,0);
Blend(81,100,226,0,0,123,0,0);
}
//+------------------------------------------------------------------+
//| WaveletCPU |
//+------------------------------------------------------------------+
bool CWavelet::WaveletCPU(const double &data[],const int datacount,const int x_size,const int y_size,const int i,const int j,const bool norm,double &result[])
{
double a1=(double)10e-10;
double a2=(double)15.0;
double da=(double)(a2-a1)/y_size;
double db=(double)(datacount-0)/x_size;
int pos=j*x_size+i;
//---
double a=a1+j*da;
double b=i*db;
double B=(double)1.0; //Morlet
double B_inv=(double)1.0/B;
double a_inv=(double)1/a;
double dt=(double)1.0;
double coef=(double)0.0;
if(!norm)
coef=(double)MathSqrt(a_inv);
else
{
for(int k=0; k<datacount; k++)
{
double arg=(dt*k-b)*a_inv;
arg=-B_inv*arg*arg;
coef+=(double)MathExp(arg);
}
}
double sum=0.0;
for(int k=0; k<datacount; k++)
{
double arg=(dt*k-b)*a_inv;
sum+=data[k]*Morlet(arg);
}
sum/=coef;
result[pos]=sum;
//---
return(true);
}
//+------------------------------------------------------------------+
//| CalculateWavelet_CPU |
//+------------------------------------------------------------------+
bool CWavelet::CalculateWavelet_CPU(const double &data[],uint &time)
{
time=GetTickCount();
int datacount=ArraySize(data);
ArrayCopy(m_data,data,0,0,WHOLE_ARRAY);
for(int i=0; i<m_xsize; i++)
{
for(int j=0; j<m_ysize; j++)
{
WaveletCPU(m_data,datacount,m_xsize,m_ysize,i,j,true,m_wavelet_data_CPU);
}
}
time=GetTickCount()-time;
//---
return(true);
}
//+------------------------------------------------------------------+
//| CalculateWavelet_GPU |
//+------------------------------------------------------------------+
bool CWavelet::CalculateWavelet_GPU(double &data[],uint &time)
{
int datacount=ArraySize(data);
if(!m_OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//--- check support working with double
if(!m_OpenCL.SupportDouble())
{
PrintFormat("Working with double (cl_khr_fp64) is not supported on the device.");
return(false);
}
//---
m_OpenCL.SetKernelsCount(1);
m_OpenCL.KernelCreate(0,"Wavelet_GPU");
//---
m_OpenCL.SetBuffersCount(2);
if(!m_OpenCL.BufferFromArray(0,data,0,datacount,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for data array. Error code=%d",GetLastError());
return(false);
}
if(!m_OpenCL.BufferCreate(1,m_xsize*m_ysize*sizeof(double),CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferCreate for data array. Error code=%d",GetLastError());
return(false);
}
m_OpenCL.SetArgumentBuffer(0,0,0);
m_OpenCL.SetArgumentBuffer(0,4,1);
//---
ArrayResize(m_wavelet_data_GPU,m_xsize*m_ysize);
uint work[2];
uint offset[2]={0,0};
//--- set dimensions
work[0]=m_xsize;
work[1]=m_ysize;
//--- set parameters and write data to buffer
m_OpenCL.SetArgument(0,1,datacount);
m_OpenCL.SetArgument(0,2,m_xsize);
m_OpenCL.SetArgument(0,3,m_ysize);
time=GetTickCount();
//--- GPU calculation start
if(!m_OpenCL.Execute(0,2,offset,work))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!m_OpenCL.BufferRead(1,m_wavelet_data_GPU,0,0,m_xsize*m_ysize))
{
PrintFormat("Error in BufferRead for m_wavelet_data_GPU array. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finish
time=GetTickCount()-time;
//---
m_OpenCL.Shutdown();
return(true);
}
//+------------------------------------------------------------------+
//| ShowWavelet |
//+------------------------------------------------------------------+
void CWavelet::ShowWavelet(const int mode)
{
if(mode==CPU_DATA)
ShowWaveletData(m_wavelet_data_CPU);
else
if(mode==GPU_DATA)
ShowWaveletData(m_wavelet_data_GPU);
}
//+------------------------------------------------------------------+
//| ShowWaveletData |
//+------------------------------------------------------------------+
void CWavelet::ShowWaveletData(const double &m_wavelet_data[])
{
//--- calculate min/max and range
int count=ArraySize(m_wavelet_data);
double min_value=m_wavelet_data[0];
double max_value=m_wavelet_data[0];
for(int i=1; i<count; i++)
{
min_value=MathMin(min_value,m_wavelet_data[i]);
max_value=MathMax(max_value,m_wavelet_data[i]);
}
double range=max_value-min_value;
if(range>0)
{
for(int j=0; j<m_ysize; j++)
{
for(int i=0; i<m_xsize; i++)
{
int pos=j*m_xsize+i;
int colindex=int(m_maxcolor*(m_wavelet_data[pos]-min_value)/range);
m_bmp_buffer[pos]=GetPalColor(colindex);
}
}
//--- show image
ResourceCreate(m_res_name,m_bmp_buffer,m_xsize,m_ysize,0,0,0,COLOR_FORMAT_XRGB_NOALPHA);
ChartRedraw();
}
}
//+------------------------------------------------------------------+
//| Weirstrass function |
//+------------------------------------------------------------------+
double Weirstrass(double x,double a,double b)
{
double sum=0.0;
double b0=b;
double a0=a;
for(int n=0; n<35; n++)
{
double v=b0*(double)MathCos(a0*M_PI*x);
sum=sum+v;
a0=a0*a;
b0=b0*b;
}
return(sum);
}
//+------------------------------------------------------------------+
//| PrepareModelData |
//+------------------------------------------------------------------+
void PrepareModelData(double &price_data[],const int datacount)
{
ArrayResize(price_data,datacount);
//--- Weirstrass function
double x1=0;
double x2=2;
double dx=(x2-x1)/datacount;
for(int i=0; i<datacount; i++)
{
price_data[i]=Weirstrass(x1+dx*i,(double)3,(double)0.62);
}
}
//+------------------------------------------------------------------+
//| PreparePriceData |
//+------------------------------------------------------------------+
void PreparePriceData(const string symbol,ENUM_TIMEFRAMES timeframe,double &price_data[],const int datacount)
{
ArrayResize(price_data,datacount);
CopyClose(symbol,timeframe,0,datacount,price_data);
}
//+------------------------------------------------------------------+
//| PrepareMomentumData |
//+------------------------------------------------------------------+
void PrepareMomentumData(double &price_data[],double &momentum_data[],const int momentum_period)
{
int size=ArraySize(price_data);
int datacount=size-momentum_period;
//---
ArrayResize(momentum_data,datacount);
for(int i=0; i<datacount; i+=1)
{
momentum_data[i]=price_data[i+momentum_period]-price_data[i];
}
ArrayCopy(price_data,price_data,momentum_period,0,datacount);
ArrayResize(price_data,datacount);
//--- rescale momentum data
double min_value=momentum_data[0];
double max_value=momentum_data[0];
for(int i=1; i<datacount; i++)
{
double value=momentum_data[i];
if(momentum_data[i]>max_value)
max_value=value;
if(momentum_data[i]<min_value)
min_value=value;
}
double range=max_value-min_value;
for(int i=0; i<datacount; i+=1)
momentum_data[i]=-1+2*(momentum_data[i]-min_value)/range;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int momentum_period=8;
double price_data[];
double momentum_data[];
PrepareModelData(price_data,SIZE_X+momentum_period);
//PreparePriceData("EURUSD",PERIOD_M1,price_data,SIZE_X+momentum_period);
PrepareMomentumData(price_data,momentum_data,momentum_period);
//---
CGraphic graph_price;
CGraphic graph_momentum;
graph_price.Create(0,"price",0,0,0,SIZE_X+130+6,SIZE_Y);
graph_price.XAxis().MaxGrace(0);
graph_price.HistorySymbolSize(10);
graph_price.CurveAdd(price_data,ColorToARGB(clrRed,255),CURVE_LINES,"Price");
graph_price.CurvePlotAll();
graph_price.Redraw(true);
graph_price.Update();
//---
graph_momentum.Create(0,"momentum",0,0,SIZE_Y,SIZE_X+130+6,SIZE_Y+SIZE_Y);
graph_momentum.XAxis().MaxGrace(0);
graph_momentum.HistorySymbolSize(10);
graph_momentum.CurveAdd(momentum_data,ColorToARGB(clrBlue,255),CURVE_LINES,"Momentum");
graph_momentum.CurvePlotAll();
graph_momentum.Redraw(true);
graph_momentum.Update();
//---
CWavelet wavelet;
//---
uint time_cpu=0;
wavelet.Create("Wavelet",50,2*SIZE_Y,SIZE_X,SIZE_Y);
if(!wavelet.CalculateWavelet_CPU(momentum_data,time_cpu))
{
PrintFormat("Error in calculation on CPU. Error code=%d",GetLastError());
return;
}
//wavelet.ShowWavelet(CPU_DATA);
uint time_gpu=0;
if(!wavelet.CalculateWavelet_GPU(momentum_data,time_gpu))
{
PrintFormat("Error in calculation on GPU. Error code=%d",GetLastError());
return;
}
wavelet.ShowWavelet(GPU_DATA);
//---
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
//---
PrintFormat("time CPU=%d ms, time GPU=%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- Sleep 10 seconds
Sleep(10000);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,232 @@
//+------------------------------------------------------------------+
//| BitonicSort.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//--- COpenCL class
#include <OpenCL/OpenCL.mqh>
#resource "Kernels/bitonicsort.cl" as string cl_program
//+------------------------------------------------------------------+
//| QuickSortAscending |
//+------------------------------------------------------------------+
//| The function sorts array[] QuickSort algorithm. |
//| |
//| Arguments: |
//| array : Array with values to sort |
//| first : First element index |
//| last : Last element index |
//| |
//| Return value: None |
//+------------------------------------------------------------------+
void QuickSortAscending(float &array[],int first,int last)
{
int i,j;
float p_float,t_float;
//---
if(first<0 || last<0)
return;
//---
i=first;
j=last;
while(i<last)
{
p_float=array[(first+last)>>1];
while(i<j)
{
while(array[i]<p_float)
{
if(i==ArraySize(array)-1)
break;
i++;
}
while(array[j]>p_float)
{
if(j==0)
break;
j--;
}
if(i<=j)
{
//-- swap elements i and j
t_float=array[i];
array[i]=array[j];
array[j]=t_float;
i++;
if(j==0)
break;
j--;
}
}
if(first<j)
QuickSortAscending(array,first,j);
first=i;
j=last;
}
}
//+------------------------------------------------------------------+
//| QuickSort_CPU |
//+------------------------------------------------------------------+
bool QuickSort_CPU(float &data_array[],ulong &time_cpu)
{
int data_count=ArraySize(data_array);
//---
if(data_count<=1)
return(false);
//--- sort values on CPU
time_cpu=GetMicrosecondCount();
QuickSortAscending(data_array,0,data_count-1);
time_cpu=ulong((GetMicrosecondCount()-time_cpu)/1000);
//---
return(true);
}
//+------------------------------------------------------------------+
//| BitonicSort_GPU |
//+------------------------------------------------------------------+
bool BitonicSort_GPU(COpenCL &OpenCL,float &data_array[],ulong &time_gpu)
{
int data_count=ArraySize(data_array);
//---
if(data_count<=1)
return(false);
OpenCL.SetKernelsCount(1);
OpenCL.KernelCreate(0,"BitonicSort_GPU");
//--- create buffers
OpenCL.SetBuffersCount(1);
if(!OpenCL.BufferFromArray(0,data_array,0,data_count,CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferFromArray for data array. Error code=%d",GetLastError());
return(false);
}
OpenCL.SetArgumentBuffer(0,0,0);
//---
uint work_offset[1]= {0};
uint global_size[1];
uint passes_total=0;
uint stages_total=0;
global_size[0]=data_count>>1;
for(uint temp=data_count; temp>1; temp>>=1)
stages_total++;
//--- GPU calculation start
time_gpu=GetMicrosecondCount();
for(uint stage=0; stage<stages_total; stage++)
{
//--- set stage of the algorithm
OpenCL.SetArgument(0,1,stage);
for(uint pass=0; pass<stage+1; pass++)
{
//--- set pass of the current stage
OpenCL.SetArgument(0,2,pass);
//--- execute kernel
if(!OpenCL.Execute(0,1,work_offset,global_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
else
passes_total++;
}
}
//---
if(!OpenCL.BufferRead(0,data_array,0,0,data_count))
{
PrintFormat("Error in BufferRead for data array with %d size. Error code=%d",data_count,GetLastError());
return(false);
}
//--- GPU calculation finish
time_gpu=ulong((GetMicrosecondCount()-time_gpu)/1000);
PrintFormat("Bitonic sort finished. Total stages=%d, total passes=%d",stages_total,passes_total);
//---
return(true);
}
//+------------------------------------------------------------------+
//| PrepareDataArray |
//+------------------------------------------------------------------+
bool PrepareDataArray(long global_memory_size,float &data[],int &data_count)
{
int pwr_max=(int)(MathLog(global_memory_size/2/sizeof(float))/MathLog(2));
int pwr=(int)MathMax(15,pwr_max-4);
//--- prepare array and generate random data
data_count=(int)MathPow(2,pwr);
if(data_count<4096)
data_count=4096;
if(data_count>4*1024*1024)
data_count=4*1024*1024;
Print(data_count," elements in float array");
//---
if(ArrayResize(data,data_count)<data_count)
{
Print("Error in ArrayResize. Error code=",GetLastError());
return(false);
}
for(int i=0; i<data_count; i++)
data[i]=(float)(100000000*MathRand()/32767.0);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
COpenCL OpenCL;
//--- OpenCL
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return;
}
//---
long global_memory_size=0;
if(!OpenCL.GetGlobalMemorySize(global_memory_size))
{
Print("Error in request of global memory size. Error code=",GetLastError());
return;
}
//--- prepare array with random values
float data_cpu[];
int data_count;
if(PrepareDataArray(global_memory_size,data_cpu,data_count)==false)
return;
//--- copy array values for sorting on GPU
float data_gpu[];
if(ArrayCopy(data_gpu,data_cpu,0,0,data_count)!=data_count)
return;
//--- Quick sort values using CPU
ulong time_cpu=0;
if(!QuickSort_CPU(data_cpu,time_cpu))
return;
//--- Bitonic sort values using GPU
ulong time_gpu=0;
if(!BitonicSort_GPU(OpenCL,data_gpu,time_gpu))
return;
//--- remove OpenCL objects
OpenCL.Shutdown();
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
PrintFormat("time CPU=%d ms, time GPU =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- check calculations
float total_error=0;
for(int i=0; i<data_count; i++)
total_error+=MathAbs(data_gpu[i]-data_cpu[i]);
PrintFormat("Total error = %f",total_error);
}
//+------------------------------------------------------------------+
Binary file not shown.
+349
View File
@@ -0,0 +1,349 @@
//+------------------------------------------------------------------+
//| FFT.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Math/Stat/Math.mqh>
#include <OpenCL/OpenCL.mqh>
#resource "Kernels/fft.cl" as string cl_program
#define kernel_init "fft_init"
#define kernel_stage "fft_stage"
#define kernel_scale "fft_scale"
#define NUM_POINTS 1024
#define FFT_DIRECTION 1
//+------------------------------------------------------------------+
//| Fast Fourier transform and its inverse (both recursively) |
//| Copyright (C) 2004, Jerome R. Breitenbach. All rights reserved. |
//| Reference: |
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
//| Recursive direct FFT transform |
//+------------------------------------------------------------------+
void fft(const int N,float &x_real[],float &x_imag[],float &X_real[],float &X_imag[])
{
//--- prepare temporary arrays
float XX_real[],XX_imag[];
ArrayResize(XX_real,N);
ArrayResize(XX_imag,N);
//--- calculate FFT by a recursion
fft_rec(N,0,1,x_real,x_imag,X_real,X_imag,XX_real,XX_imag);
}
//+------------------------------------------------------------------+
//| Recursive inverse FFT transform |
//+------------------------------------------------------------------+
void ifft(const int N,float &x_real[],float &x_imag[],float &X_real[],float &X_imag[])
{
int N2=N/2; // half the number of points in IFFT
//--- calculate IFFT via reciprocity property of DFT
fft(N,X_real,X_imag,x_real,x_imag);
x_real[0]=x_real[0]/N;
x_imag[0]=x_imag[0]/N;
x_real[N2]=x_real[N2]/N;
x_imag[N2]=x_imag[N2]/N;
for(int i=1; i<N2; i++)
{
float tmp0=x_real[i]/N;
float tmp1=x_imag[i]/N;
x_real[i]=x_real[N-i]/N;
x_imag[i]=x_imag[N-i]/N;
x_real[N-i]=tmp0;
x_imag[N-i]=tmp1;
}
}
//+------------------------------------------------------------------+
//| FFT recursion |
//+------------------------------------------------------------------+
void fft_rec(const int N,const int offset,const int delta,float &x_real[],float &x_imag[],float &X_real[],float &X_imag[],float &XX_real[],float &XX_imag[])
{
static const float TWO_PI=(float)(2*M_PI);
int N2=N/2; // half the number of points in FFT
int k00,k01,k10,k11; // indices for butterflies
if(N!=2)
{
//--- perform recursive step
//--- calculate two (N/2)-point DFT's
fft_rec(N2,offset,2*delta,x_real,x_imag,XX_real,XX_imag,X_real,X_imag);
fft_rec(N2,offset+delta,2*delta,x_real,x_imag,XX_real,XX_imag,X_real,X_imag);
//--- combine the two (N/2)-point DFT's into one N-point DFT
for(int k=0; k<N2; k++)
{
k00 = offset + k*delta;
k01 = k00 + N2*delta;
k10 = offset + 2*k*delta;
k11 = k10 + delta;
float cs=(float)MathCos(TWO_PI*k/(float)N);
float sn=(float)MathSin(TWO_PI*k/(float)N);
float tmp0 = cs*XX_real[k11] + sn*XX_imag[k11];
float tmp1 = cs*XX_imag[k11] - sn*XX_real[k11];
X_real[k01] = XX_real[k10] - tmp0;
X_imag[k01] = XX_imag[k10] - tmp1;
X_real[k00] = XX_real[k10] + tmp0;
X_imag[k00] = XX_imag[k10] + tmp1;
}
}
else
{
//--- perform 2-point DFT
k00=offset;
k01=k00+delta;
X_real[k01] = x_real[k00] - x_real[k01];
X_imag[k01] = x_imag[k00] - x_imag[k01];
X_real[k00] = x_real[k00] + x_real[k01];
X_imag[k00] = x_imag[k00] + x_imag[k01];
}
}
//+------------------------------------------------------------------+
//| FFT_CPU |
//+------------------------------------------------------------------+
bool FFT_CPU(int direction,int power,float &data_real[],float &data_imag[],ulong &time_cpu)
{
//--- calculate the number of points
int N=1;
for(int i=0;i<power;i++)
N*=2;
//---prepare temporary arrays
float XX_real[],XX_imag[];
ArrayResize(XX_real,N);
ArrayResize(XX_imag,N);
//--- CPU calculation start
time_cpu=GetMicrosecondCount();
if(direction>0)
fft(N,data_real,data_imag,XX_real,XX_imag);
else
ifft(N,XX_real,XX_imag,data_real,data_imag);
//--- CPU calculation finished
time_cpu=ulong((GetMicrosecondCount()-time_cpu));
//--- copy calculated data
ArrayCopy(data_real,XX_real,0,0,WHOLE_ARRAY);
ArrayCopy(data_imag,XX_imag,0,0,WHOLE_ARRAY);
//---
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool ExecutionWait(COpenCL& OpenCL,int kernel_index)
{
for(int i=0;;)
{
ENUM_OPENCL_EXECUTION_STATUS status=OpenCL.ExecutionStatus(kernel_index);
if(status==CL_COMPLETE)
{
Print("i=",i);
return(true);
}
if(status<0 || IsStopped())
break;
if(++i%10000==0)
{
Print("running... i=",i," execute_status=",status);
Sleep(1);
}
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| FFT_GPU |
//+------------------------------------------------------------------+
bool FFT_GPU(int direction,int power,float &data_real[],float &data_imag[],ulong &time_gpu)
{
//--- calculate the number of points
int num_points=1;
for(int i=0;i<power;i++)
num_points*=2;
//--- prepare data array for GPU calculation
float data[];
ArrayResize(data,2*num_points);
for(int i=0; i<num_points; i++)
{
data[2*i]=data_real[i];
data[2*i+1]=data_imag[i];
}
COpenCL OpenCL;
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//--- create kernels
OpenCL.SetKernelsCount(3);
OpenCL.KernelCreate(0,kernel_init);
OpenCL.KernelCreate(1,kernel_stage);
OpenCL.KernelCreate(2,kernel_scale);
//--- create buffers
OpenCL.SetBuffersCount(2);
if(!OpenCL.BufferFromArray(0,data,0,2*num_points,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for input buffer. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferCreate(1,2*num_points*sizeof(float),CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferCreate for data buffer. Error code=%d",GetLastError());
return(false);
}
//--- determine maximum work-group size
int workgroup_size=(int)CLGetInfoInteger(OpenCL.GetKernel(0),CL_KERNEL_WORK_GROUP_SIZE);
//--- determine local memory size
uint local_mem_size=(uint)CLGetInfoInteger(OpenCL.GetContext(),CL_DEVICE_LOCAL_MEM_SIZE);
local_mem_size/=3;
local_mem_size*=2;
local_mem_size/=num_points;
local_mem_size*=num_points;
Print("local_mem_size=",local_mem_size);
int points_per_group=(int)local_mem_size/(2*sizeof(float));
if(points_per_group>num_points)
points_per_group=num_points;
//--- set kernel arguments
OpenCL.SetArgumentBuffer(0,0,0);
OpenCL.SetArgumentBuffer(0,1,1);
OpenCL.SetArgumentLocalMemory(0,2,local_mem_size);
OpenCL.SetArgument(0,3,points_per_group);
OpenCL.SetArgument(0,4,num_points);
OpenCL.SetArgument(0,5,direction);
//--- OpenCL execute settings
int task_dimension=1;
uint global_size=(uint)((num_points/points_per_group)*workgroup_size);
uint global_work_offset[1]={0};
uint global_work_size[1];
global_work_size[0]=global_size;
uint local_work_size[1];
local_work_size[0]=workgroup_size;
//--- GPU calculation start
time_gpu=GetMicrosecondCount();
//-- execute kernel fft_init
if(!OpenCL.Execute(0,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_init: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
if(!ExecutionWait(OpenCL,0))
return(false);
Print("fft_init passed");
//-- further stages of the FFT
if(num_points>points_per_group)
{
Print("num_points=",num_points," points_per_group=",points_per_group);
//--- set arguments for kernel 1
OpenCL.SetArgumentBuffer(1,0,1);
OpenCL.SetArgument(1,2,points_per_group);
OpenCL.SetArgument(1,3,direction);
for(int stage=2; stage<=num_points/points_per_group; stage<<=1)
{
OpenCL.SetArgument(1,1,stage);
//-- execute kernel fft_stage
if(!OpenCL.Execute(1,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_stage: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
Print("fft_stage ",stage," passed");
}
if(!ExecutionWait(OpenCL,1))
return(false);
}
//--- scale values if performing the inverse FFT
if(direction<0)
{
Print("direction=",direction);
OpenCL.SetArgumentBuffer(2,0,1);
OpenCL.SetArgument(2,1,points_per_group);
OpenCL.SetArgument(2,2,num_points);
//-- execute kernel fft_scale
if(!OpenCL.Execute(2,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("fft_scale: Error in CLExecute. Error code=%d",GetLastError());
return(false);
}
if(!ExecutionWait(OpenCL,2))
return(false);
Print("fft_scale passed");
}
//--- read the results from GPU memory
if(!OpenCL.BufferRead(1,data,0,0,2*num_points))
{
PrintFormat("Error in BufferRead for data_buffer2. Error code=%d",GetLastError());
return(false);
}
Print("buffer read");
//--- GPU calculation finished
time_gpu=ulong((GetMicrosecondCount()-time_gpu));
//--- copy calculated data and release OpenCL handles
for(int i=0; i<num_points; i++)
{
data_real[i]=data[2*i];
data_imag[i]=data[2*i+1];
}
OpenCL.Shutdown();
Print("OpenCL shutdown");
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int datacount=NUM_POINTS;
int power=(int)(MathLog(NUM_POINTS)/M_LN2);
if(MathPow(2,power)!=datacount)
{
PrintFormat("Number of elements must be power of 2. Elements: %d",datacount);
return;
}
//--- prepare data for FFT calculation
float data_real[],data_imag[];
ArrayResize(data_real,datacount);
ArrayResize(data_imag,datacount);
for(int i=0; i<datacount; i++)
{
data_real[i]=(float)i;
data_imag[i]=0;
}
int direction=FFT_DIRECTION;
//--- data arrays for CPU calculation
float CPU_real[],CPU_imag[];
ArrayCopy(CPU_real,data_real,0,0,WHOLE_ARRAY);
ArrayCopy(CPU_imag,data_imag,0,0,WHOLE_ARRAY);
ulong time_cpu=0;
//--- calculate FFT using CPU
FFT_CPU(direction,power,CPU_real,CPU_imag,time_cpu);
//--- data arrays for GPU calculation
float GPU_real[],GPU_imag[];
ArrayCopy(GPU_real,data_real,0,0,WHOLE_ARRAY);
ArrayCopy(GPU_imag,data_imag,0,0,WHOLE_ARRAY);
ulong time_gpu=0;
//--- calculate FFT using GPU
if(!FFT_GPU(direction,power,GPU_real,GPU_imag,time_gpu))
{
PrintFormat("Error in calculation FFT on GPU.");
return;
}
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
PrintFormat("FFT calculation for %d points.",datacount);
PrintFormat("time CPU=%d microseconds, time GPU =%d microseconds, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- determine average error
float average_error=0.0;
for(int i=0; i<datacount; i++)
{
average_error += (float)MathAbs(CPU_real[i]-GPU_real[i]);
average_error += (float)MathAbs(CPU_imag[i]-GPU_imag[i]);
}
average_error=average_error/(datacount*2);
PrintFormat("Average error = %f",average_error);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,28 @@
//+-----------------------------------------------------------+
//| OpenCL kernel |
//| The bitonic sort kernel does an ascending sort. |
//+-----------------------------------------------------------+
//| R. Banger,K. Bhattacharyya, OpenCL Programming by Example:|
//| A comprehensive guide on OpenCL programming with examples |
//| PACKT Publishing, 2013. |
//+-----------------------------------------------------------+
__kernel void BitonicSort_GPU(__global float *data,const uint stage,const uint pass)
{
uint id=get_global_id(0);
uint distance = 1<<(stage-pass);
uint left_id =(id &(distance-1));
left_id+=(id>>(stage-pass))*(distance<<1);
uint right_id=left_id+distance;
float left_value=data[left_id];
float right_value=data[right_id];
uint same_direction=(id>>stage)&0x1;
uint temp = same_direction?right_id:temp;
right_id = same_direction?left_id:right_id;
left_id = same_direction?temp:left_id;
int compare_res=(left_value<right_value);
float greater = compare_res?right_value:left_value;
float lesser = compare_res?left_value:right_value;
data[left_id] = lesser;
data[right_id]= greater;
};
//+------------------------------------------------------------------+
@@ -0,0 +1,153 @@
//+------------------------------------------------------------------+
//| fft_init OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_init(__global float2 *in_data,
__global float2 *out_data,
__local float2 *l_data,
uint points_per_group,uint size,int dir)
{
uint4 br,index;
uint points_per_item,g_addr,l_addr,i,fft_index,stage,N2;
float2 x1,x2,x3,x4,sum12,diff12,sum34,diff34;
points_per_item=points_per_group/get_local_size(0);
l_addr = get_local_id(0)*points_per_item;
g_addr = get_group_id(0)*points_per_group + l_addr;
//--- load data from bit-reversed addresses and perform 4-point FFTs
for(i=0; i<points_per_item; i+=4)
{
index=(uint4)(g_addr,g_addr+1,g_addr+2,g_addr+3);
fft_index=size/2;
stage=1;
N2 =(uint)log2((float)size)-1;
br =(index<< N2) & fft_index;
br|=(index>> N2) & stage;
//--- bit-reverse addresses
while(N2>1)
{
N2-=2;
fft_index>>=1;
stage<<=1;
br |= (index << N2) & fft_index;
br |= (index >> N2) & stage;
}
//--- load global data
x1 = in_data[br.s0];
x2 = in_data[br.s1];
x3 = in_data[br.s2];
x4 = in_data[br.s3];
sum12=x1+x2;
diff12= x1-x2;
sum34 = x3+x4;
diff34=(float2)(x3.s1-x4.s1,x4.s0-x3.s0)*dir;
l_data[l_addr]=sum12+sum34;
l_data[l_addr+1] = diff12 + diff34;
l_data[l_addr+2] = sum12 - sum34;
l_data[l_addr+3] = diff12 - diff34;
l_addr += 4;
g_addr += 4;
}
//--- perform initial stages of the FFT - each of length N2*2
for(N2=4; N2<points_per_item; N2<<=1)
{
l_addr=get_local_id(0)*points_per_item;
for(fft_index=0; fft_index<points_per_item; fft_index+=2*N2)
{
x1=l_data[l_addr];
l_data[l_addr]+=l_data[l_addr+N2];
l_data[l_addr+N2]=x1-l_data[l_addr+N2];
for(i=1; i<N2; i++)
{
x3.s0=cos(M_PI_F*i/N2);
x3.s1=dir*sin(M_PI_F*i/N2);
x2=(float2)(l_data[l_addr+N2+i].s0*x3.s0+l_data[l_addr+N2+i].s1*x3.s1,l_data[l_addr+N2+i].s1*x3.s0-l_data[l_addr+N2+i].s0*x3.s1);
l_data[l_addr+N2+i]=l_data[l_addr+i]-x2;
l_data[l_addr+i]+=x2;
}
l_addr+=2*N2;
}
}
barrier(CLK_LOCAL_MEM_FENCE);
//--- perform FFT with other items in group - each of length N2*2
stage=2;
for(N2=points_per_item; N2<points_per_group; N2<<=1)
{
br.s0=(get_local_id(0)+(get_local_id(0)/stage)*stage) *(points_per_item/2);
size = br.s0 % (N2*2);
for(i=br.s0; i<br.s0+points_per_item/2; i++)
{
x3.s0=cos(M_PI_F*size/N2);
x3.s1=dir*sin(M_PI_F*size/N2);
x2=(float2)(l_data[N2+i].s0*x3.s0+l_data[N2+i].s1*x3.s1,l_data[N2+i].s1*x3.s0-l_data[N2+i].s0*x3.s1);
l_data[N2+i]=l_data[i]-x2;
l_data[i]+=x2;
size++;
}
stage<<=1;
barrier(CLK_LOCAL_MEM_FENCE);
}
//--- store results in global memory
l_addr = get_local_id(0)*points_per_item;
g_addr = get_group_id(0)*points_per_group + l_addr;
for(i=0; i<points_per_item; i+=4)
{
out_data[g_addr]=l_data[l_addr];
out_data[g_addr+1] = l_data[l_addr+1];
out_data[g_addr+2] = l_data[l_addr+2];
out_data[g_addr+3] = l_data[l_addr+3];
g_addr += 4;
l_addr += 4;
}
}
//+------------------------------------------------------------------+
//| fft_stage OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_stage(__global float2 *g_data,uint stage,uint points_per_group,int dir)
{
uint points_per_item,addr,N,ang,i;
float c,s;
float2 input1,input2,w;
points_per_item=points_per_group/get_local_size(0);
addr=(get_group_id(0)+(get_group_id(0)/stage)*stage)*(points_per_group/2)+get_local_id(0)*(points_per_item/2);
N=points_per_group*(stage/2);
ang=addr%(N*2);
for(i=addr; i<addr+points_per_item/2; i++)
{
c = cos(M_PI_F*ang/N);
s = dir*sin(M_PI_F*ang/N);
input1 = g_data[i];
input2 = g_data[i+N];
w=(float2)(input2.s0*c+input2.s1*s,input2.s1*c-input2.s0*s);
g_data[i]=input1+w;
g_data[i+N]=input1-w;
ang++;
}
}
//+------------------------------------------------------------------+
//| fft_scale OpenCL kernel for Fast Fourier Transfrom |
//+------------------------------------------------------------------+
//| Matthew Scarpino, "OpenCL in Action: How to accelerate graphics |
//| and computations", Manning, 2012, Chapter 14. |
//+------------------------------------------------------------------+
__kernel void fft_scale(__global float2 *g_data,uint points_per_group,uint scale)
{
uint points_per_item,addr,i;
points_per_item=points_per_group/get_local_size(0);
addr=get_group_id(0)*points_per_group+get_local_id(0)*points_per_item;
for(i=addr; i<addr+points_per_item; i++)
{
g_data[i]/=scale;
}
}
//+------------------------------------------------------------------+
@@ -0,0 +1,66 @@
//+-----------------------------------------------------------+
//| OpenCL kernel for matrix multiplication |
//| using global work groups |
//+-----------------------------------------------------------+
//| http://gpgpu-computing4.blogspot.ru/2009/09/ |
//| /matrix-multiplication-2-opencl.html |
//+-----------------------------------------------------------+
__kernel void MatrixMult_GPU1(__global float *matrix_a,
__global float *matrix_b,
__global float *matrix_c,
int rows_a,int cols_a,int cols_b)
{
int i=get_global_id(0);
int j=get_global_id(1);
float sum=0.0;
for(int k=0; k<cols_a; k++)
{
sum+=matrix_a[cols_a*i+k]*matrix_b[cols_b*k+j];
}
matrix_c[cols_b*i+j]=sum;
}
#define BLOCK_SIZE 10
//+-----------------------------------------------------------+
//| OpenCL kernel for matrix multiplication |
//| using local groups with common local memory |
//+-----------------------------------------------------------+
//| http://gpgpu-computing4.blogspot.ru/2009/10/ |
//| /matrix-multiplication-3-opencl.html |
//+-----------------------------------------------------------+
__kernel void MatrixMult_GPU2(__global float *matrix_a,
__global float *matrix_b,
__global float *matrix_c,
int rows_a,int cols_a,int cols_b)
{
int group_i=get_group_id(0);
int group_j=get_group_id(1);
int i=get_local_id(0);
int j=get_local_id(1);
int offset_b=BLOCK_SIZE*group_i;
int offset_a_start=cols_a*BLOCK_SIZE*group_j;
float sum=(float)0.0;
for(int offset_a=offset_a_start;
offset_a<offset_a_start+cols_a;
offset_a+=BLOCK_SIZE,
offset_b+=BLOCK_SIZE*cols_b)
{
__local float submatrix_a[BLOCK_SIZE][BLOCK_SIZE];
__local float submatrix_b[BLOCK_SIZE][BLOCK_SIZE];
submatrix_a[i][j]=matrix_a[offset_a+cols_a*i+j];
submatrix_b[i][j]=matrix_b[offset_b+cols_b*i+j];
barrier(CLK_LOCAL_MEM_FENCE);
for(int k=0; k<BLOCK_SIZE; k++)
sum+=submatrix_a[i][k]*submatrix_b[k][j];
barrier(CLK_LOCAL_MEM_FENCE);
}
int offset_c=BLOCK_SIZE*(cols_b*group_j+group_i);
matrix_c[offset_c+cols_b*i+j]=sum;
};
//+------------------------------------------------------------------+
@@ -0,0 +1,48 @@
//+------------------------------------------------------------------+
//| Morlet wavelet function |
//+------------------------------------------------------------------+
float Morlet(const float t)
{
return exp(-t*t*0.5)*cos(M_2_PI*t);
}
//+------------------------------------------------------------------+
//| OpenCL kernel function |
//+------------------------------------------------------------------+
__kernel void Wavelet_GPU(__global float *data,int datacount,int x_size,int y_size,__global float *result)
{
size_t i = get_global_id(0);
size_t j = get_global_id(1);
float a1=(float)10e-10;
float a2=(float)15.0;
float da=(a2-a1)/(float)y_size;
float db=((float)datacount-(float)0.0)/x_size;
float a=a1+j*da;
float b=0+i*db;
uint norm=1;
float B=(float)1.0; //Morlet
float B_inv=(float)1.0/B;
float a_inv=(float)1.0/a;
float dt=(float)1.0;
float coef=(float)0.0;
if(norm==0)
coef=sqrt(a_inv);
else
{
for(int k=0; k<datacount; k++)
{
float arg=(dt*k-b)*a_inv;
arg=-B_inv*arg*arg;
coef=coef+exp(arg);
}
}
float sum=(float)0.0;
for(int k=0; k<datacount; k++)
{
float arg=(dt*k-b)*a_inv;
sum+=data[k]*Morlet(arg);
}
sum=sum/coef;
uint pos=(int)(j*x_size+i);
result[pos]=sum;
};
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,219 @@
//+------------------------------------------------------------------+
//| MatrixMult.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <OpenCL/OpenCL.mqh>
//--- OpenCL kernels
#resource "Kernels/matrixmult.cl" as string cl_program
#define BLOCK_SIZE 10
//+------------------------------------------------------------------+
//| MatrixMult_CPU |
//+------------------------------------------------------------------+
bool MatrixMult_CPU(const float &matrix_a[],const float &matrix_b[],float &matrix_c[],
const int rows_a,const int cols_a,const int cols_b,ulong &time_cpu)
{
int size=rows_a*cols_b;
if(ArrayResize(matrix_c,size)!=size)
return(false);
//--- CPU calculation started
time_cpu=GetMicrosecondCount();
for(int i=0; i<rows_a; i++)
{
for(int j=0; j<cols_b; j++)
{
float sum=0.0;
for(int k=0; k<cols_a; k++)
{
sum+=matrix_a[cols_a*i+k]*matrix_b[cols_b*k+j];
}
matrix_c[cols_b*i+j]=sum;
}
}
//--- CPU calculation finished
time_cpu=ulong((GetMicrosecondCount()-time_cpu)/1000);
//---
return(true);
}
//+------------------------------------------------------------------+
//| MatrixMult_GPU |
//+------------------------------------------------------------------+
bool MatrixMult_GPU(const float &matrix_a[],const float &matrix_b[],float &matrix1_c[],float &matrix2_c[],
const int rows_a,const int cols_a,const int cols_b,const int size_a,const int size_b,
const int size_c,ulong &time1_gpu,ulong &time2_gpu)
{
const int task_dimension=2;
//--- prepare matrices for result
if(ArrayResize(matrix1_c,size_c)!=size_c || ArrayResize(matrix2_c,size_c)!=size_c)
return(false);
ArrayFill(matrix1_c,0,size_c,(float)0.0);
ArrayFill(matrix2_c,0,size_c,(float)0.0);
//--- OpenCL
COpenCL OpenCL;
if(!OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//--- create kernels
OpenCL.SetKernelsCount(2);
OpenCL.KernelCreate(0,"MatrixMult_GPU1");
OpenCL.KernelCreate(1,"MatrixMult_GPU2");
//--- create buffers
OpenCL.SetBuffersCount(3);
//---
if(!OpenCL.BufferFromArray(0,matrix_a,0,size_a,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for matrix A. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferFromArray(1,matrix_b,0,size_b,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for matrix B. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferCreate(2,size_c*sizeof(float),CL_MEM_WRITE_ONLY))
{
PrintFormat("Error in BufferCreate for matrix C. Error code=%d",GetLastError());
return(false);
}
//--- prepare arguments for kernel 0
int kernel_index=0;
OpenCL.SetArgumentBuffer(kernel_index,0,0);
OpenCL.SetArgumentBuffer(kernel_index,1,1);
OpenCL.SetArgumentBuffer(kernel_index,2,2);
OpenCL.SetArgument(kernel_index,3,rows_a);
OpenCL.SetArgument(kernel_index,4,cols_a);
OpenCL.SetArgument(kernel_index,5,cols_b);
//--- set task dimension a_rows x b_cols
uint global_work_size[2];
//--- set dimensions
global_work_size[0]=rows_a;
global_work_size[1]=cols_b;
uint global_work_offset[2]={0,0};
//--- GPU calculation start kernel 0
time1_gpu=GetMicrosecondCount();
if(!OpenCL.Execute(kernel_index,task_dimension,global_work_offset,global_work_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferRead(2,matrix1_c,0,0,size_c))
{
PrintFormat("Error in BufferRead for matrix1 C. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finished
time1_gpu=ulong((GetMicrosecondCount()-time1_gpu)/1000);
//--- prepare arguments for kernel 1
kernel_index=1;
//--- set arguments
OpenCL.SetArgumentBuffer(kernel_index,0,0);
OpenCL.SetArgumentBuffer(kernel_index,1,1);
OpenCL.SetArgumentBuffer(kernel_index,2,2);
OpenCL.SetArgument(kernel_index,3,rows_a);
OpenCL.SetArgument(kernel_index,4,cols_a);
OpenCL.SetArgument(kernel_index,5,cols_b);
uint local_work_size[2];
local_work_size[0]=BLOCK_SIZE;
local_work_size[1]=BLOCK_SIZE;
//--- GPU calculation start, kernel1
time2_gpu=GetMicrosecondCount();
if(!OpenCL.Execute(kernel_index,task_dimension,global_work_offset,global_work_size,local_work_size))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!OpenCL.BufferRead(2,matrix2_c,0,0,size_c))
{
PrintFormat("Error in BufferRead for matrix2 C. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finished
time2_gpu=ulong((GetMicrosecondCount()-time2_gpu)/1000);
//--- remove OpenCL objects
OpenCL.Shutdown();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- matrix A 1000x2000
int rows_a=1000;
int cols_a=2000;
//--- matrix B 2000x1000
int rows_b=cols_a;
int cols_b=1000;
//--- matrix C 1000x1000
int rows_c=rows_a;
int cols_c=cols_b;
//--- matrix A: size=rows_a*cols_a
int size_a=rows_a*cols_a;
int size_b=rows_b*cols_b;
int size_c=rows_c*cols_c;
//--- prepare matrix A
float matrix_a[];
ArrayResize(matrix_a,rows_a*cols_a);
for(int i=0; i<rows_a; i++)
for(int j=0; j<cols_a; j++)
{
matrix_a[i*cols_a+j]=(float)(10*MathRand()/32767);
}
//--- prepare matrix B
float matrix_b[];
ArrayResize(matrix_b,rows_b*cols_b);
for(int i=0; i<rows_b; i++)
for(int j=0; j<cols_b; j++)
{
matrix_b[i*cols_b+j]=(float)(10*MathRand()/32767);
}
//--- CPU: calculate matrix product matrix_a*matrix_b
float matrix_c_cpu[];
ulong time_cpu=0;
if(!MatrixMult_CPU(matrix_a,matrix_b,matrix_c_cpu,rows_a,cols_a,cols_b,time_cpu))
{
PrintFormat("Error in calculation on CPU. Error code=%d",GetLastError());
return;
}
//--- calculate matrix product using GPU
float matrix_c_gpu_method1[];
float matrix_c_gpu_method2[];
ulong time_gpu_method1=0;
ulong time_gpu_method2=0;
if(!MatrixMult_GPU(matrix_a,matrix_b,matrix_c_gpu_method1,matrix_c_gpu_method2,rows_a,cols_a,cols_b,size_a,size_b,size_c,time_gpu_method1,time_gpu_method2))
{
PrintFormat("Error in calculation on GPU. Error code=%d",GetLastError());
return;
}
//--- calculate CPU/GPU ratio
double CPU_GPU_ratio1=0;
double CPU_GPU_ratio2=0;
if(time_gpu_method1!=0)
CPU_GPU_ratio1=1.0*time_cpu/time_gpu_method1;
if(time_gpu_method2!=0)
CPU_GPU_ratio2=1.0*time_cpu/time_gpu_method2;
PrintFormat("time CPU=%d ms, time GPU global work groups =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu_method1,CPU_GPU_ratio1);
PrintFormat("time CPU=%d ms, time GPU local work groups =%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu_method2,CPU_GPU_ratio2);
//--- check calculations
float total_error1=0;
float total_error2=0;
for(int i=0; i<rows_c; i++)
{
for(int j=0; j<cols_c; j++)
{
int pos=cols_c*i+j;
total_error1+=MathAbs(matrix_c_gpu_method1[pos]-matrix_c_cpu[pos]);
total_error2+=MathAbs(matrix_c_gpu_method2[pos]-matrix_c_cpu[pos]);
}
}
PrintFormat("Total error for method 1 = %f",total_error1);
PrintFormat("Total error for method 2 = %f",total_error2);
}
//+------------------------------------------------------------------+
Binary file not shown.
+436
View File
@@ -0,0 +1,436 @@
//+------------------------------------------------------------------+
//| Wavelet.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Math/Stat/Math.mqh>
#include <Graphics/Graphic.mqh>
#include <OpenCL/OpenCL.mqh>
#define CPU_DATA 1
#define GPU_DATA 2
#define SIZE_X 600
#define SIZE_Y 200
#resource "Kernels/wavelet.cl" as string cl_program
//+------------------------------------------------------------------+
//| CWavelet |
//+------------------------------------------------------------------+
class CWavelet
{
protected:
int m_xsize;
int m_ysize;
int m_maxcolor;
string m_res_name;
string m_label_name;
uchar m_palette[3*256];
//---
float m_data[];
float m_wavelet_data_CPU[];
float m_wavelet_data_GPU[];
uint m_bmp_buffer[];
COpenCL m_OpenCL;
float Morlet(const float t);
void ShowWaveletData(const float &m_wavelet_data[]);
int GetPalColor(const int index);
void Blend(const uint c1,const uint c2,const uint r1,const uint g1,const uint b1,const uint r2,const uint g2,const uint b2);
bool WaveletCPU(const float &data[],const int datacount,const int x_size,const int y_size,const int i,const int j,const bool norm,float &result[]);
public:
//---
void Create(const string name,const int x0,const int y0,const int x_size,const int y_size);
bool CalculateWavelet_CPU(const float &data[],uint &time);
bool CalculateWavelet_GPU(float &data[],uint &time);
void ShowWavelet(const int mode);
};
//+------------------------------------------------------------------+
//| Morlet wavelet function |
//+------------------------------------------------------------------+
float CWavelet::Morlet(const float t)
{
double v=t;
double res=MathExp(-v*v*0.5)*MathCos(M_2_PI*v);
return ((float)res);
}
//+------------------------------------------------------------------+
//| GetPalColor |
//+------------------------------------------------------------------+
int CWavelet::GetPalColor(const int index)
{
int ind=index;
if(ind<=0)
ind=0;
if(ind>255)
ind=255;
int idx=3*(ind);
uchar r=m_palette[idx];
uchar g=m_palette[idx+1];
uchar b=m_palette[idx+2];
//---
return(b+256*g+65536*r);
}
//+------------------------------------------------------------------+
//| Gradient palette |
//+------------------------------------------------------------------+
void CWavelet::Blend(const uint c1,const uint c2,const uint r1,const uint g1,const uint b1,const uint r2,const uint g2,const uint b2)
{
int n=int(c2-c1);
for(int i=0; i<=n; i++)
{
if((c1+i+2)<m_palette.Size())
{
m_palette[3*(c1+i)]=uchar(MathRound(1*(r1*(n-i)+r2*i)*1.0/n));
m_palette[3*(c1+i)+1]=uchar(MathRound(1*(g1*(n-i)+g2*i)*1.0/n));
m_palette[3*(c1+i)+2]=uchar(MathRound(1*(b1*(n-i)+b2*i)*1.0/n));
}
}
}
//+------------------------------------------------------------------+
//| Create |
//+------------------------------------------------------------------+
void CWavelet::Create(const string name,const int x0,const int y0,const int x_size,const int y_size)
{
//---
m_xsize=x_size;
m_ysize=y_size;
int size=m_xsize*m_ysize;
ArrayResize(m_bmp_buffer,size);
ArrayFill(m_bmp_buffer,0,size,0);
ArrayResize(m_wavelet_data_CPU,size);
ArrayResize(m_wavelet_data_GPU,size);
ArrayFill(m_wavelet_data_CPU,0,size,0);
ArrayFill(m_wavelet_data_GPU,0,size,0);
m_res_name=name;
m_label_name=m_res_name;
StringToUpper(m_label_name);
ResourceCreate(m_res_name,m_bmp_buffer,m_xsize,m_ysize,0,0,0,COLOR_FORMAT_XRGB_NOALPHA);
ObjectCreate(0,m_label_name,OBJ_BITMAP_LABEL,0,0,0);
ObjectSetInteger(0,m_label_name,OBJPROP_XDISTANCE,x0);
ObjectSetInteger(0,m_label_name,OBJPROP_YDISTANCE,y0);
ObjectSetString(0,m_label_name,OBJPROP_BMPFILE,NULL);
ObjectSetString(0,m_label_name,OBJPROP_BMPFILE,"::"+m_label_name);
m_maxcolor=100;
//Blend(0,100,0,0,0,255,255,255);
Blend(0,20,0,0,95,0,0,246);
Blend(21,40,0,0,246,0,236,226);
Blend(41,60,0,236,226,226,246,0);
Blend(61,80,226,246,0,226,0,0);
Blend(81,100,226,0,0,123,0,0);
}
//+------------------------------------------------------------------+
//| WaveletCPU |
//+------------------------------------------------------------------+
bool CWavelet::WaveletCPU(const float &data[],const int datacount,const int x_size,const int y_size,const int i,const int j,const bool norm,float &result[])
{
float a1=(float)10e-10;
float a2=(float)15.0;
float da=(float)(a2-a1)/y_size;
float db=(float)(datacount-0)/x_size;
int pos=j*x_size+i;
//---
float a=a1+j*da;
float b=i*db;
float B=(float)1.0; //Morlet
float B_inv=(float)1.0/B;
float a_inv=(float)1/a;
float dt=(float)1.0;
float coef=(float)0.0;
if(!norm)
coef=(float)MathSqrt(a_inv);
else
{
for(int k=0; k<datacount; k++)
{
float arg=(dt*k-b)*a_inv;
arg=-B_inv*arg*arg;
coef+=(float)MathExp(arg);
}
}
float sum=0.0;
for(int k=0; k<datacount; k++)
{
float arg=(dt*k-b)*a_inv;
sum+=data[k]*Morlet(arg);
}
sum/=coef;
result[pos]=sum;
//---
return(true);
}
//+------------------------------------------------------------------+
//| CalculateWavelet_CPU |
//+------------------------------------------------------------------+
bool CWavelet::CalculateWavelet_CPU(const float &data[],uint &time)
{
time=GetTickCount();
int datacount=ArraySize(data);
ArrayCopy(m_data,data,0,0,WHOLE_ARRAY);
for(int i=0; i<m_xsize; i++)
{
for(int j=0; j<m_ysize; j++)
{
WaveletCPU(m_data,datacount,m_xsize,m_ysize,i,j,true,m_wavelet_data_CPU);
}
}
time=GetTickCount()-time;
//---
return(true);
}
//+------------------------------------------------------------------+
//| CalculateWavelet_GPU |
//+------------------------------------------------------------------+
bool CWavelet::CalculateWavelet_GPU(float &data[],uint &time)
{
int datacount=ArraySize(data);
if(!m_OpenCL.Initialize(cl_program,true))
{
PrintFormat("Error in OpenCL initialization. Error code=%d",GetLastError());
return(false);
}
//---
m_OpenCL.SetKernelsCount(1);
m_OpenCL.KernelCreate(0,"Wavelet_GPU");
//---
m_OpenCL.SetBuffersCount(2);
if(!m_OpenCL.BufferFromArray(0,data,0,datacount,CL_MEM_READ_ONLY))
{
PrintFormat("Error in BufferFromArray for data array. Error code=%d",GetLastError());
return(false);
}
if(!m_OpenCL.BufferCreate(1,m_xsize*m_ysize*sizeof(float),CL_MEM_READ_WRITE))
{
PrintFormat("Error in BufferCreate for data array. Error code=%d",GetLastError());
return(false);
}
m_OpenCL.SetArgumentBuffer(0,0,0);
m_OpenCL.SetArgumentBuffer(0,4,1);
//---
ArrayResize(m_wavelet_data_GPU,m_xsize*m_ysize);
uint work[2];
uint offset[2]={0,0};
//--- set dimensions
work[0]=m_xsize;
work[1]=m_ysize;
//--- set parameters and write data to buffer
m_OpenCL.SetArgument(0,1,datacount);
m_OpenCL.SetArgument(0,2,m_xsize);
m_OpenCL.SetArgument(0,3,m_ysize);
time=GetTickCount();
//--- GPU calculation start
if(!m_OpenCL.Execute(0,2,offset,work))
{
PrintFormat("Error in Execute. Error code=%d",GetLastError());
return(false);
}
if(!m_OpenCL.BufferRead(1,m_wavelet_data_GPU,0,0,m_xsize*m_ysize))
{
PrintFormat("Error in BufferRead for m_wavelet_data_GPU array. Error code=%d",GetLastError());
return(false);
}
//--- GPU calculation finish
time=GetTickCount()-time;
//---
m_OpenCL.Shutdown();
return(true);
}
//+------------------------------------------------------------------+
//| ShowWavelet |
//+------------------------------------------------------------------+
void CWavelet::ShowWavelet(const int mode)
{
if(mode==CPU_DATA)
ShowWaveletData(m_wavelet_data_CPU);
else
if(mode==GPU_DATA)
ShowWaveletData(m_wavelet_data_GPU);
}
//+------------------------------------------------------------------+
//| ShowWaveletData |
//+------------------------------------------------------------------+
void CWavelet::ShowWaveletData(const float &m_wavelet_data[])
{
//--- calculate min/max and range
int count=ArraySize(m_wavelet_data);
float min_value=m_wavelet_data[0];
float max_value=m_wavelet_data[0];
for(int i=1; i<count; i++)
{
min_value=MathMin(min_value,m_wavelet_data[i]);
max_value=MathMax(max_value,m_wavelet_data[i]);
}
float range=max_value-min_value;
if(range>0)
{
for(int j=0; j<m_ysize; j++)
{
for(int i=0; i<m_xsize; i++)
{
int pos=j*m_xsize+i;
int colindex=int(m_maxcolor*(m_wavelet_data[pos]-min_value)/range);
m_bmp_buffer[pos]=GetPalColor(colindex);
}
}
//--- show image
ResourceCreate(m_res_name,m_bmp_buffer,m_xsize,m_ysize,0,0,0,COLOR_FORMAT_XRGB_NOALPHA);
ChartRedraw();
}
}
//+------------------------------------------------------------------+
//| Weirstrass function |
//+------------------------------------------------------------------+
float Weirstrass(float x,float a,float b)
{
float sum=0.0;
float b0=b;
float a0=a;
for(int n=0; n<35; n++)
{
float v=b0*(float)MathCos(a0*M_PI*x);
sum=sum+v;
a0=a0*a;
b0=b0*b;
}
return(sum);
}
//+------------------------------------------------------------------+
//| PrepareModelData |
//+------------------------------------------------------------------+
void PrepareModelData(float &price_data[],const int datacount)
{
ArrayResize(price_data,datacount);
//--- Weirstrass function
float x1=0;
float x2=2;
float dx=(x2-x1)/datacount;
for(int i=0; i<datacount; i++)
{
price_data[i]=Weirstrass(x1+dx*i,(float)3,(float)0.62);
}
}
//+------------------------------------------------------------------+
//| PreparePriceData |
//+------------------------------------------------------------------+
void PreparePriceData(const string symbol,ENUM_TIMEFRAMES timeframe,float &price_data[],const int datacount)
{
ArrayResize(price_data,datacount);
double price_data_double[];
CopyClose(symbol,timeframe,0,datacount,price_data_double);
int size=ArraySize(price_data_double);
for(int i=0; i<size; i++)
{
price_data[i]=(float)price_data_double[i];
}
}
//+------------------------------------------------------------------+
//| PrepareMomentumData |
//+------------------------------------------------------------------+
void PrepareMomentumData(float &price_data[],float &momentum_data[],const int momentum_period)
{
int size=ArraySize(price_data);
int datacount=size-momentum_period;
//---
ArrayResize(momentum_data,datacount);
for(int i=0; i<datacount; i+=1)
{
momentum_data[i]=price_data[i+momentum_period]-price_data[i];
}
ArrayCopy(price_data,price_data,momentum_period,0,datacount);
ArrayResize(price_data,datacount);
//--- rescale momentum data
float min_value=momentum_data[0];
float max_value=momentum_data[0];
for(int i=1; i<datacount; i++)
{
float value=momentum_data[i];
if(momentum_data[i]>max_value)
max_value=value;
if(momentum_data[i]<min_value)
min_value=value;
}
float range=max_value-min_value;
for(int i=0; i<datacount; i+=1)
momentum_data[i]=-1+2*(momentum_data[i]-min_value)/range;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int momentum_period=8;
float price_data[];
float momentum_data[];
PrepareModelData(price_data,SIZE_X+momentum_period);
//PreparePriceData("EURUSD",PERIOD_M1,price_data,SIZE_X+momentum_period);
PrepareMomentumData(price_data,momentum_data,momentum_period);
double price_data_double[];
double momentum_data_double[];
int datacount=ArraySize(price_data);
ArrayResize(price_data_double,datacount);
for(int i=0; i<datacount; i++)
{
price_data_double[i]=(double)price_data[i];
}
datacount=ArraySize(momentum_data);
ArrayResize(momentum_data_double,datacount);
for(int i=0; i<datacount; i++)
{
momentum_data_double[i]=(double)momentum_data[i];
}
CGraphic graph_price;
CGraphic graph_momentum;
graph_price.Create(0,"price",0,0,0,SIZE_X+130+6,SIZE_Y);
graph_price.XAxis().MaxGrace(0);
graph_price.HistorySymbolSize(10);
graph_price.CurveAdd(price_data_double,ColorToARGB(clrRed,255),CURVE_LINES,"Price");
graph_price.CurvePlotAll();
graph_price.Redraw(true);
graph_price.Update();
//---
graph_momentum.Create(0,"momentum",0,0,SIZE_Y,SIZE_X+130+6,SIZE_Y+SIZE_Y);
graph_momentum.XAxis().MaxGrace(0);
graph_momentum.HistorySymbolSize(10);
graph_momentum.CurveAdd(momentum_data_double,ColorToARGB(clrBlue,255),CURVE_LINES,"Momentum");
graph_momentum.CurvePlotAll();
graph_momentum.Redraw(true);
graph_momentum.Update();
//---
uint time_cpu=0;
CWavelet wavelet;
wavelet.Create("Wavelet",50,2*SIZE_Y,SIZE_X,SIZE_Y);
if(!wavelet.CalculateWavelet_CPU(momentum_data,time_cpu))
{
PrintFormat("Error in calculation on CPU. Error code=%d",GetLastError());
return;
}
//wavelet.ShowWavelet(CPU_DATA);
uint time_gpu=0;
if(!wavelet.CalculateWavelet_GPU(momentum_data,time_gpu))
{
PrintFormat("Error in calculation on GPU. Error code=%d",GetLastError());
return;
}
wavelet.ShowWavelet(GPU_DATA);
//---
double CPU_GPU_ratio=0;
if(time_gpu!=0)
CPU_GPU_ratio=1.0*time_cpu/time_gpu;
//---
PrintFormat("time CPU=%d ms, time GPU=%d ms, CPU/GPU ratio: %f",time_cpu,time_gpu,CPU_GPU_ratio);
//--- Sleep 10 seconds
Sleep(10000);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,223 @@
//+------------------------------------------------------------------+
//| OpenCL code |
//+------------------------------------------------------------------+
//| Based on pixel shader by Alexander Alekseev aka TDM-2014 |
//| https://www.shadertoy.com/view/Ms2SD1 |
//+------------------------------------------------------------------+
#define NUM_STEPS (int)8
#define PI (float)3.1415
#define EPSILON (float)1e-3
#define EPSILON_NRM ((float)0.1/iResolution.x)
#define ITER_GEOMETRY (int)3
#define ITER_FRAGMENT (int)5
#define SEA_HEIGHT (float)0.6
#define SEA_CHOPPY (float)4.0
#define SEA_SPEED (float)0.8
#define SEA_FREQ (float)0.16
#define SEA_BASE vec3(0.1,0.19,0.22)
#define SEA_WATER_COLOR vec3(0.8,0.9,0.6)
#define SEA_TIME ((float)1.0 + iGlobalTime * SEA_SPEED)
float max1(float v1,float v2) { if (v1>v2) return v1; return v2; }
float dot2(float2 v1,float2 v2) { return v1.x*v2.x+v1.y*v2.y; }
float dot3(float3 v1,float3 v2) { return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; }
float fract1(float p) { return p-floor(p); }
float2 fract2(float2 p) { return p-floor(p); }
float mix1(float x1,float x2,float a) { return(x1+(x2-x1)*a); }
float2 mix2(float2 x1,float2 x2,float2 a) { float2 r={x1.x+(x2.x-x1.x)*a.x,x1.y+(x2.y-x1.y)*a.y }; return(r); }
float3 mix3(float3 x1,float3 x2,float3 a) { float3 r={x1.x+(x2.x-x1.x)*a.x,x1.y+(x2.y-x1.y)*a.y,x1.z+(x2.z-x1.z)*a.z }; return(r); }
float3 vec31(float x) { float3 r={x,x,x}; return(r); }
float3 vec3(float x,float y,float z) { float3 r={x,y,z}; return(r); }
float2 vec2(float x,float y) { float2 r={x,y}; return(r); }
float4 vec4(float3 x,float y) { float4 r={x.x,x.y,x.z,y}; return(r); }
float3 reflect3(float3 I,float3 N) { return(I-(float)2.0*dot3(N,I)*N); }
float diffuse(float3 n,float3 l,float p) { return pow(dot3(n,l) * (float)0.4 + (float)0.6,p); }
float2 abs2(float2 f) { if(f.x<0) f.x=-f.x; if(f.y<0) f.y=-f.y; return(f); }
float hash(float2 p) { return fract1(sin(dot2(p,vec2((float)127.1,(float)311.7)))*43758.5453123); }
float specular(float3 n,float3 l,float3 e,float s) { return pow(max1(dot3(reflect3(e,n),l),0.0),s)*((s+(float)8.0)/(float)(3.1415 * 8.0)); }
float3 getSkyColor(float3 e)
{
e.y=max1(e.y,0.0);
float3 r2;
r2.x = (float)1.0-e.y;
r2.y = r2.x;
r2.z = (float)0.6+r2.x *(float)0.4;
r2.x = r2.x * r2.x;
return r2;
}
void fromEuler(float3 ang,float3 *r1,float3 *r2,float3 *r3)
{
float2 a1 = vec2(sin(ang.x),cos(ang.x));
float2 a2 = vec2(sin(ang.y),cos(ang.y));
float2 a3 = vec2(sin(ang.z),cos(ang.z));
*r1 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
*r2 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
*r3 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
}
float noise(float2 p)
{
float2 i = floor(p);
float2 f = fract2(p);
float2 u = f * f * ((float)3.0 - (float)2.0 * f);
float mx1=mix1(hash(i+vec2(0.0,0.0)),hash(i+vec2(1.0,0.0)),u.x);
float mx2=mix1(hash(i+vec2(0.0,1.0)),hash(i+vec2(1.0,1.0)),u.x);
return (float)-1.0 + (float)2.0*mix(mx1,mx2,u.y);
}
float sea_octave(float2 uv, float choppy)
{
uv += noise(uv);
float2 wv = (float)1.0-abs2(sin(uv));
float2 swv = abs2(cos(uv));
wv = mix2(wv,swv,wv);
return pow((float)1.0-pow(wv.x * wv.y,(float)0.65),choppy);
}
float map(float3 p,float iGlobalTime)
{
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
float2 uv = p.xz; uv.x *= (float)0.75;
float d, h = 0.0;
for(int i = 0; i < ITER_GEOMETRY; i++)
{
d = sea_octave((uv+SEA_TIME)*freq,choppy);
d += sea_octave((uv-SEA_TIME)*freq,choppy);
h += d * amp;
float2 uvt={(float)1.6*uv.x+(float)1.2*uv.y, (float)-1.2*uv.x+(float)1.6*uv.y };
uv = uvt;
freq *= (float)1.9; amp *= (float)0.22;
choppy = mix1(choppy,(float)1.0,(float)0.2);
}
return p.y - h;
}
float map_detailed(float3 p,float iGlobalTime)
{
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
float2 uv = p.xz; uv.x *= (float)0.75;
float d, h = 0.0;
for(int i = 0; i < ITER_FRAGMENT; i++)
{
d =sea_octave((uv+SEA_TIME)*freq,choppy);
d+=sea_octave((uv-SEA_TIME)*freq,choppy);
h+=d * amp;
float2 uvt={ (float)1.6*uv.x+(float)1.2*uv.y, (float)-1.2*uv.x+(float)1.6*uv.y };
uv = uvt;
freq *= (float)1.9; amp *= (float)0.22;
choppy = mix1(choppy,(float)1.0,(float)0.2);
}
return p.y - h;
}
float3 getSeaColor(float3 p, float3 n, float3 l, float3 eye, float3 dist)
{
float fresnel = clamp((float)1.0 - dot3(n,-eye), (float)0.0, (float)1.0);
fresnel = pow(fresnel,(float)3.0) * (float)0.65;
float3 reflected = getSkyColor(reflect3(eye,n));
float3 refracted = SEA_BASE + diffuse(n,l,(float)80.0) * SEA_WATER_COLOR * (float)0.12;
float3 color = mix3(refracted,reflected,fresnel);
float atten = max1((float)1.0 - dot(dist,dist) * (float)0.001, (float)0.0);
color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * (float)0.18 * atten;
color += vec31(specular(n,l,eye,(float)60.0));
if(isnan(color.x))
color.x=0.0;
if(isnan(color.y))
color.y=0.0;
if(isnan(color.z))
color.z=0.0;
return color;
}
float3 getNormal(float3 p, float eps,float iGlobalTime)
{
float3 n;
n.y = map_detailed(p,iGlobalTime);
n.x = map_detailed(vec3(p.x+eps,p.y,p.z),iGlobalTime) - n.y;
n.z = map_detailed(vec3(p.x,p.y,p.z+eps),iGlobalTime) - n.y;
n.y = eps;
return normalize(n);
}
float heightMapTracing(float3 ori, float3 dir,float3 *p,float iGlobalTime)
{
float tm = (float)0.0;
float tx = (float)1000.0;
float hx = map(ori + dir * tx,iGlobalTime);
if(hx > (float)0.0) return tx;
float hm = map(ori + dir * tm,iGlobalTime);
float tmid = (float)0.0;
for(int i = 0; i < NUM_STEPS; i++)
{
tmid = mix(tm,tx, hm/(hm-hx));
*p = ori + dir * tmid;
float hmid = map(*p,iGlobalTime);
if(hmid < (float)0.0)
{
tx = tmid;
hx = hmid;
}
else
{
tm = tmid;
hm = hmid;
}
}
return tmid;
}
float4 mainImage(float2 fragCoord,float iGlobalTime,float2 iResolution)
{
float4 fragColor;
float2 iMouse= {0,0};
float2 uv = fragCoord.xy / iResolution;
uv = uv * (float)2.0 - (float)1.0;
uv.x *= iResolution.x / iResolution.y;
float time = iGlobalTime * (float)0.3 + iMouse.x*(float)0.01;
float3 ang = vec3(sin(time*(float)3.0)*(float)0.1,sin(time)*(float)0.2+(float)0.3,time);
float3 ori = vec3(0.0,3.5,time*(float)5.0);
float3 dir = normalize(vec3(uv.x,uv.y,(float)-2.0)); dir.z += length(uv) * (float)0.15;
dir = normalize(dir);
float3 r1,r2,r3;
fromEuler(ang,&r1,&r2,&r3);
float3 r;
r.x=r1.x*dir.x+r1.y*dir.y+r1.z*dir.z;
r.y=r2.x*dir.x+r2.y*dir.y+r2.z*dir.z;
r.z=r3.x*dir.x+r3.y*dir.y+r3.z*dir.z;
dir=r;
float3 p;
heightMapTracing(ori,dir,&p,iGlobalTime);
float3 dist = p - ori;
float3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM,iGlobalTime);
float3 light = normalize(vec3((float)0.0,(float)1.0,(float)0.8));
float3 seacol=getSeaColor(p,n,light,dir,dist);
float3 color = mix(getSkyColor(dir),seacol,pow(smoothstep((float)0.0,(float)-0.05,dir.y),(float)0.3));
fragColor = vec4(pow(color,vec31((float)0.75)),(float)1.0);
return(fragColor);
}
__kernel void Seascape(float iGlobalTime,__global uint *out)
{
size_t w = get_global_size(0);
size_t h = get_global_size(1);
float2 iRes = {(float)w,(float)h};
size_t gx = get_global_id(0);
size_t gy = get_global_id(1);
float2 coord={gx,gy};
float4 res=mainImage(coord,iGlobalTime,iRes);
uint b=(uint)(res.z*255);
uint g=(uint)(res.y*255);
uint r=(uint)(res.x*255);
if(b>255) b=255;
if(r>255) r=255;
if(g>255) g=255;
out[w*((uint)(iRes.y-1)-gy)+gx] = (r<<16)|(g<<8)|b;
};
Binary file not shown.
@@ -0,0 +1,193 @@
//+------------------------------------------------------------------+
//| Seascape.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#resource "seascape.cl" as string ExtCL
uint ExtSizeX=640; // Width
uint ExtSizeY=360; // Height
//+------------------------------------------------------------------+
//| Initialize OpenCL engine |
//+------------------------------------------------------------------+
bool ModelInitialize(int &cl_ctx,int &cl_prg,int &cl_krn,int &cl_mem)
{
//--- initializing OpenCL objects
if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
{
Print("OpenCL not found");
return(false);
}
//--- compile the program
string build_log;
if((cl_prg=CLProgramCreate(cl_ctx,ExtCL,build_log))==INVALID_HANDLE)
{
//--- free
CLContextFree(cl_ctx);
cl_ctx=INVALID_HANDLE;
//---
Print("OpenCL program create failed: ",build_log);
return(false);
}
//--- kernel
if((cl_krn=CLKernelCreate(cl_prg,"Seascape"))==INVALID_HANDLE)
{
//--- free
CLProgramFree(cl_prg);
cl_prg=INVALID_HANDLE;
CLContextFree(cl_ctx);
cl_ctx=INVALID_HANDLE;
//---
Print("OpenCL kernel create failed");
return(false);
}
//--- create buffer
ExtSizeX=(uint)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
ExtSizeY=(uint)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
if((cl_mem=CLBufferCreate(cl_ctx,ExtSizeX*ExtSizeY*sizeof(uint),CL_MEM_READ_WRITE))==INVALID_HANDLE)
{
//--- free objects
CLKernelFree(cl_krn);
cl_krn=INVALID_HANDLE;
CLProgramFree(cl_prg);
cl_prg=INVALID_HANDLE;
CLContextFree(cl_ctx);
cl_ctx=INVALID_HANDLE;
//---
Print("OpenCL buffer create failed");
return(false);
}
CLSetKernelArgMem(cl_krn,1,cl_mem);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Check and resize the window |
//+------------------------------------------------------------------+
bool ModelResize(const int cl_ctx,const int cl_krn,int &cl_mem)
{
uint width =(uint)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
uint height=(uint)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//--- correction
width=(width + 7) & ~7; // align to 8
if(width<8)
width=8;
if(height<8)
height=8;
//--- the same size?
if(ExtSizeX!=width || ExtSizeY!=height)
{
ExtSizeX=width;
ExtSizeY=height;
//--- create buffer
if(cl_mem!=INVALID_HANDLE)
CLBufferFree(cl_mem);
if((cl_mem=CLBufferCreate(cl_ctx,ExtSizeX*ExtSizeY*sizeof(uint),CL_MEM_READ_WRITE))!=INVALID_HANDLE)
{
CLSetKernelArgMem(cl_krn,1,cl_mem);
return(true);
}
}
//--- no changes
return(false);
}
//+------------------------------------------------------------------+
//| Shutdown OpenCL engine |
//+------------------------------------------------------------------+
void ModelShutdown(int cl_ctx,int cl_prg,int cl_krn,int cl_mem)
{
//--- remove OpenCL objects
if(cl_mem!=INVALID_HANDLE)
{
CLBufferFree(cl_mem);
cl_mem=INVALID_HANDLE;
}
if(cl_krn!=INVALID_HANDLE)
{
CLKernelFree(cl_krn);
cl_krn=INVALID_HANDLE;
}
if(cl_prg!=INVALID_HANDLE)
{
CLProgramFree(cl_prg);
cl_prg=INVALID_HANDLE;
}
if(cl_ctx!=INVALID_HANDLE)
{
CLContextFree(cl_ctx);
cl_ctx=INVALID_HANDLE;
}
//---
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int cl_ctx=INVALID_HANDLE,cl_prg=INVALID_HANDLE;
int cl_krn=INVALID_HANDLE,cl_mem=INVALID_HANDLE;
//--- prepare the chart
ChartSetInteger(0,CHART_SHOW,false);
ChartRedraw();
//--- initializing OpenCL objects
if(ModelInitialize(cl_ctx,cl_prg,cl_krn,cl_mem))
{
uint buf[];
uint work[2];
uint offset[2]={0,0};
string objname="OpenCL_"+IntegerToString(ChartID());
string resname="::Seascape_"+IntegerToString(ChartID());
//--- create object and empty picture
ObjectCreate(0,objname,OBJ_BITMAP_LABEL,0,0,0);
ObjectSetInteger(0,objname,OBJPROP_XDISTANCE,0);
ObjectSetInteger(0,objname,OBJPROP_YDISTANCE,0);
ArrayResize(buf,ExtSizeX*ExtSizeY);
ResourceCreate(resname,buf,ExtSizeX,ExtSizeY,0,0,ExtSizeX,COLOR_FORMAT_XRGB_NOALPHA);
ObjectSetString(0,objname,OBJPROP_BMPFILE,resname);
//--- render
work[0]=ExtSizeX;
work[1]=ExtSizeY;
for(float time=0;!IsStopped();time+=0.04f)
{
//--- check the resolution
if(ModelResize(cl_ctx,cl_krn,cl_mem))
{
work[0]=ExtSizeX;
work[1]=ExtSizeY;
ArrayResize(buf,ExtSizeX*ExtSizeY);
}
//--- rendering the frame
CLSetKernelArg(cl_krn,0,time);
CLExecute(cl_krn,2,offset,work);
//--- take the frame data, save in memory and draw it
CLBufferRead(cl_mem,buf);
ResourceCreate(resname,buf,ExtSizeX,ExtSizeY,0,0,ExtSizeX,COLOR_FORMAT_XRGB_NOALPHA);
ChartRedraw();
Sleep(0);
}
//--- remove OpenCL objects
ModelShutdown(cl_ctx,cl_prg,cl_krn,cl_mem);
//--- remove object
ObjectDelete(0,objname);
}
//---
ChartSetInteger(0,CHART_SHOW,true);
}
//+------------------------------------------------------------------+
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,200 @@
//+------------------------------------------------------------------+
//| OrderInfoSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#include <Trade\OrderInfo.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//---
#include "OrderInfoSampleInit.mqh"
//+------------------------------------------------------------------+
//| Script to testing the use of class COrderInfo. |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Order Info Sample script class |
//+------------------------------------------------------------------+
class COrderInfoSample
{
protected:
COrderInfo m_order;
//--- chart objects
CChartObjectButton m_button_prev;
CChartObjectButton m_button_next;
CChartObjectLabel m_label[20];
CChartObjectLabel m_label_info[20];
//---
int m_curr_ord;
int m_total_ord;
public:
COrderInfoSample(void);
~COrderInfoSample(void);
//---
bool Init(void);
void Deinit(void);
void Processing(void);
private:
void InfoToChart(void);
};
//---
COrderInfoSample ExtScript;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
COrderInfoSample::COrderInfoSample(void) : m_curr_ord(-1),
m_total_ord(-1)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
COrderInfoSample::~COrderInfoSample(void)
{
}
//+------------------------------------------------------------------+
//| Method Init. |
//+------------------------------------------------------------------+
bool COrderInfoSample::Init(void)
{
int i,sy=10;
int dy=16;
color color_label;
color color_info;
//--- tuning colors
color_info =(color)(ChartGetInteger(0,CHART_COLOR_BACKGROUND)^0xFFFFFF);
color_label=(color)(color_info^0x202020);
//---
if(ChartGetInteger(0,CHART_SHOW_OHLC))
sy+=16;
//--- creation Buttons
m_button_prev.Create(0,"ButtonPrev",0,10,sy,100,20);
m_button_prev.Description("Prev Order");
m_button_prev.Color(clrRed);
m_button_prev.FontSize(8);
//---
m_button_next.Create(0,"ButtonNext",0,110,sy,100,20);
m_button_next.Description("Next Order");
m_button_next.Color(clrRed);
m_button_next.FontSize(8);
//---
sy+=20;
//--- creation Labels[]
for(i=0;i<20;i++)
{
m_label[i].Create(0,"Label"+IntegerToString(i),0,20,sy+dy*i);
m_label[i].Description(init_str[i]);
m_label[i].Color(color_label);
m_label[i].FontSize(8);
//---
m_label_info[i].Create(0,"LabelInfo"+IntegerToString(i),0,120,sy+dy*i);
m_label_info[i].Description(" ");
m_label_info[i].Color(color_info);
m_label_info[i].FontSize(8);
}
InfoToChart();
//--- redraw chart
ChartRedraw();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method Deinit. |
//+------------------------------------------------------------------+
void COrderInfoSample::Deinit(void)
{
}
//+------------------------------------------------------------------+
//| Method Processing. |
//+------------------------------------------------------------------+
void COrderInfoSample::Processing(void)
{
ulong ticket;
//---
if(m_total_ord!=OrdersTotal())
{
m_total_ord=OrdersTotal();
if(m_total_ord==0)
{
m_label_info[0].Description("0");
m_label_info[1].Description("");
m_curr_ord=-1;
return;
}
else
{
m_label_info[0].Description(IntegerToString(m_total_ord));
if(m_curr_ord==-1)
m_curr_ord=0;
if(m_curr_ord>=m_total_ord)
m_curr_ord=m_total_ord-1;
m_label_info[1].Description(IntegerToString(m_curr_ord));
}
}
if(m_button_prev.State())
{
m_button_prev.State(false);
if(m_curr_ord>=0)
m_label_info[1].Description(IntegerToString(--m_curr_ord));
}
if(m_button_next.State())
{
m_button_next.State(false);
if(m_curr_ord<m_total_ord-1)
m_label_info[1].Description(IntegerToString(++m_curr_ord));
}
ticket=OrderGetTicket(m_curr_ord);
if(OrderSelect(ticket))
{
m_label_info[2].Description(IntegerToString(ticket));
InfoToChart();
}
//--- redraw chart
ChartRedraw();
Sleep(250);
}
//+------------------------------------------------------------------+
//| Method InfoToChart. |
//+------------------------------------------------------------------+
void COrderInfoSample::InfoToChart(void)
{
m_label_info[3].Description(m_order.Symbol());
m_label_info[4].Description(TimeToString(m_order.TimeSetup()));
m_label_info[5].Description(m_order.TypeDescription());
m_label_info[6].Description(m_order.StateDescription());
m_label_info[7].Description(TimeToString(m_order.TimeExpiration()));
m_label_info[8].Description(TimeToString(m_order.TimeDone()));
m_label_info[9].Description(m_order.TypeFillingDescription());
m_label_info[10].Description(m_order.TypeTimeDescription());
m_label_info[11].Description(IntegerToString(m_order.Magic()));
m_label_info[12].Description(DoubleToString(m_order.VolumeInitial()));
m_label_info[13].Description(DoubleToString(m_order.VolumeCurrent()));
m_label_info[14].Description(DoubleToString(m_order.PriceOpen()));
m_label_info[15].Description(DoubleToString(m_order.StopLoss()));
m_label_info[16].Description(DoubleToString(m_order.TakeProfit()));
m_label_info[17].Description(DoubleToString(m_order.PriceCurrent()));
m_label_info[18].Description(DoubleToString(m_order.PriceStopLimit()));
m_label_info[19].Description(m_order.Comment());
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
//--- call init function
if(ExtScript.Init())
{
//--- cycle until the script is not halted
while(!IsStopped())
ExtScript.Processing();
}
//--- call deinit function
ExtScript.Deinit();
//---
return(0);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,17 @@
//+------------------------------------------------------------------+
//| OrderInfoSampleInit.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Arrays to initialize graphics objects OrderInfoSample. |
//+------------------------------------------------------------------+
string init_str[]=
{
"Total","Current","Ticket","Symbol","TimeSetup",
"Type","State","TimeExpiration","TimeDone","TypeFilling",
"TypeTime","Expert","VolumeInit","VolumeCurr","PriceOpen",
"StopLoss","TakeProfit","PriceCurr","PriceStopLimit","Comment"
};
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,196 @@
//+------------------------------------------------------------------+
//| PositionInfoSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#include <Trade\PositionInfo.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//---
#include "PositionInfoSampleInit.mqh"
//+------------------------------------------------------------------+
//| Script to testing the use of class CPositionInfo. |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Position Info Sample script class |
//+------------------------------------------------------------------+
class CPositionInfoSample
{
protected:
CPositionInfo m_position;
//--- chart objects
CChartObjectButton m_button_prev;
CChartObjectButton m_button_next;
CChartObjectLabel m_label[19];
CChartObjectLabel m_label_info[19];
//---
int curr_pos;
int total_pos;
public:
CPositionInfoSample(void);
~CPositionInfoSample(void);
//---
bool Init();
void Deinit();
void Processing();
private:
void CheckButtons();
void InfoToChart();
};
//---
CPositionInfoSample ExtScript;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CPositionInfoSample::CPositionInfoSample(void) : curr_pos(-1),
total_pos(-1)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CPositionInfoSample::~CPositionInfoSample(void)
{
}
//+------------------------------------------------------------------+
//| Method Init. |
//+------------------------------------------------------------------+
bool CPositionInfoSample::Init(void)
{
int i,sy=10;
int dy=16;
color color_label;
color color_info;
//--- tuning colors
color_info =(color)(ChartGetInteger(0,CHART_COLOR_BACKGROUND)^0xFFFFFF);
color_label=(color)(color_info^0x202020);
//---
if(ChartGetInteger(0,CHART_SHOW_OHLC))
sy+=16;
//--- creation Buttons
m_button_prev.Create(0,"ButtonPrev",0,10,sy,100,20);
m_button_prev.Description("Prev Position");
m_button_prev.Color(clrRed);
m_button_prev.FontSize(8);
//---
m_button_next.Create(0,"ButtonNext",0,110,sy,100,20);
m_button_next.Description("Next Position");
m_button_next.Color(clrRed);
m_button_next.FontSize(8);
//---
sy+=20;
//--- creation Labels[]
for(i=0;i<13;i++)
{
m_label[i].Create(0,"Label"+IntegerToString(i),0,20,sy+dy*i);
m_label[i].Description(init_str[i]);
m_label[i].Color(color_label);
m_label[i].FontSize(8);
//---
m_label_info[i].Create(0,"LabelInfo"+IntegerToString(i),0,120,sy+dy*i);
m_label_info[i].Description(" ");
m_label_info[i].Color(color_info);
m_label_info[i].FontSize(8);
}
InfoToChart();
//--- redraw chart
ChartRedraw();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method Deinit. |
//+------------------------------------------------------------------+
void CPositionInfoSample::Deinit(void)
{
}
//+------------------------------------------------------------------+
//| Method Processing. |
//+------------------------------------------------------------------+
void CPositionInfoSample::Processing(void)
{
if(total_pos!=PositionsTotal())
{
total_pos=PositionsTotal();
if(total_pos==0)
{
m_label_info[0].Description("0");
m_label_info[1].Description("");
curr_pos=-1;
return;
}
else
{
m_label_info[0].Description(IntegerToString(total_pos));
if(curr_pos==-1)
curr_pos=0;
if(curr_pos>=total_pos)
curr_pos=total_pos-1;
m_label_info[1].Description(IntegerToString(curr_pos));
}
}
CheckButtons();
PositionSelect(PositionGetSymbol(curr_pos));
InfoToChart();
//--- redraw chart
ChartRedraw();
Sleep(250);
}
//+------------------------------------------------------------------+
//| Method InfoToChart. |
//+------------------------------------------------------------------+
void CPositionInfoSample::CheckButtons(void)
{
if(m_button_prev.State())
{
m_button_prev.State(false);
if(curr_pos>0)
m_label_info[1].Description(IntegerToString(--curr_pos));
}
if(m_button_next.State())
{
m_button_next.State(false);
if(curr_pos<total_pos-1)
m_label_info[1].Description(IntegerToString(++curr_pos));
}
}
//+------------------------------------------------------------------+
//| Function for display position info |
//+------------------------------------------------------------------+
void CPositionInfoSample::InfoToChart(void)
{
m_label_info[2].Description(m_position.Symbol());
m_label_info[3].Description(TimeToString(m_position.Time()));
m_label_info[4].Description(m_position.TypeDescription());
m_label_info[5].Description(DoubleToString(m_position.Volume()));
m_label_info[6].Description(DoubleToString(m_position.PriceOpen()));
m_label_info[7].Description(DoubleToString(m_position.StopLoss()));
m_label_info[8].Description(DoubleToString(m_position.TakeProfit()));
m_label_info[9].Description(DoubleToString(m_position.PriceCurrent()));
m_label_info[10].Description(DoubleToString(m_position.Commission()));
m_label_info[11].Description(DoubleToString(m_position.Swap()));
m_label_info[12].Description(DoubleToString(m_position.Profit()));
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
//--- call init function
if(ExtScript.Init())
{
//--- cycle until the script is not halted
while(!IsStopped())
ExtScript.Processing();
}
//--- call deinit function
ExtScript.Deinit();
//---
return(0);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,16 @@
//+------------------------------------------------------------------+
//| PositionInfoSampleInit.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Arrays to initialize graphics objects PositionInfoSample. |
//+------------------------------------------------------------------+
string init_str[]=
{
"Total","Current","Symbol","Time","Type",
"Volume","PriceOpen","StopLoss","TakeProfit","PriceCurrent",
"Commission","Swap","Profit"
};
//+------------------------------------------------------------------+
Binary file not shown.
+136
View File
@@ -0,0 +1,136 @@
//+------------------------------------------------------------------+
//| Remnant3D.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#resource "Shaders/vertex.hlsl" as string ExtShaderVS;
#resource "Shaders/pixel.hlsl" as string ExtShaderPS;
//+------------------------------------------------------------------+
//| Vertex shader input vertex type |
//+------------------------------------------------------------------+
struct VSInputVertex
{
//--- data
float position[4];
//--- data layout
static const DXVertexLayout s_layout[1];
};
const DXVertexLayout VSInputVertex::s_layout[1]=
{
{"POSITION", 0, DX_FORMAT_R32G32B32A32_FLOAT }
};
//+------------------------------------------------------------------+
//| Pixel shader input buffer type |
//+------------------------------------------------------------------+
struct PSInputBuffer
{
float resolution[2];
float time;
float dummy;
};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- prepare the chart
ChartSetInteger(0,CHART_SHOW,false);
ChartRedraw();
//--- get chart window size
int width=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//---
uint image[];
string objname="Reinmant3D_"+IntegerToString(ChartID());
string resname="::Reinmant3D_"+IntegerToString(ChartID());
//--- create object and empty picture
ObjectCreate(0,objname,OBJ_BITMAP_LABEL,0,0,0);
ObjectSetInteger(0,objname,OBJPROP_XDISTANCE,0);
ObjectSetInteger(0,objname,OBJPROP_YDISTANCE,0);
//--- create resource and assign to image buffer
ArrayResize(image,width*height);
ResourceCreate(resname,image,width,height,0,0,width,COLOR_FORMAT_XRGB_NOALPHA);
ObjectSetString(0,objname,OBJPROP_BMPFILE,resname);
//--- initialize DX context
int context=DXContextCreate(width,height);
//--- prepare vertices for rectangle from [-1;-1] to [1;1] in screen space
VSInputVertex vertices[]= {{{-1,-1,0.5,1.0}},{{-1,1,0.5,1.0}},{{1,1,0.5,1.0}},{{1,-1,0.5,1.0}}};
//--- prepare indices for two triangles
uint indices[]= {0,1,2, 2,3,0};
//--- create vertex and index buffer
int buffer_v=DXBufferCreate(context,DX_BUFFER_VERTEX,vertices);
int buffer_i=DXBufferCreate(context,DX_BUFFER_INDEX, indices);
//--- create shaders from sources
string str="";
int shader_v=DXShaderCreate(context,DX_SHADER_VERTEX,ExtShaderVS,"VSMain",str);
int shader_p=DXShaderCreate(context,DX_SHADER_PIXEL, ExtShaderPS,"PSMain",str);
//--- set vertex layout for vertex shader
DXShaderSetLayout(shader_v,VSInputVertex::s_layout);
//--- create input buffer and set it to pixel shader
int inputs_p[1];
inputs_p[0]=DXInputCreate(context,sizeof(PSInputBuffer));
DXShaderInputsSet(shader_p,inputs_p);
//--- update input buffer data
PSInputBuffer frame_data;
frame_data.resolution[0]=(float)width;
frame_data.resolution[1]=(float)height;
//--- set topology, buffers and shaders
DXPrimiveTopologySet(context,DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
DXBufferSet(context,buffer_v);
DXBufferSet(context,buffer_i);
DXShaderSet(context,shader_v);
DXShaderSet(context,shader_p);
//--- initialize fps counter
float fps=25.0;
//--- main loop
while(!IsStopped())
{
//--- check if ESC pressed
if((TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)&0x8000)!=0)
break;
//--- get current chart window size
int w=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
int h=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//--- update size everywhere it needed
if(w!=width || h!=height)
{
width=w;
height=h;
frame_data.resolution[0]=(float)width;
frame_data.resolution[1]=(float)height;
ArrayResize(image,width*height);
DXContextSetSize(context,width,height);
}
//--- clear depth buffer
DXContextClearDepth(context);
//--- update time in shder's input buffer
frame_data.time=GetMicrosecondCount()/1000000.0f;
DXInputSet(inputs_p[0],frame_data);
//--- draw call
DXDrawIndexed(context);
//--- get result into buffer
DXContextGetColors(context,image);
//--- calculate delta time and smoothed FPS count
float delta=GetMicrosecondCount()/1000000.0f-frame_data.time;
fps=0.95f*fps+0.05f/delta;
TextOut(StringFormat("FPS: %.0f",fps),10,10,0,image,width,height,clrWhite,COLOR_FORMAT_ARGB_NORMALIZE);
//--- update resource and redraw chart
ResourceCreate(resname,image,width,height,0,0,width,COLOR_FORMAT_XRGB_NOALPHA);
ChartRedraw();
//---
Sleep(1);
}
//--- release handles
DXRelease(inputs_p[0]);
DXRelease(shader_p);
DXRelease(shader_v);
DXRelease(buffer_v);
DXRelease(buffer_i);
DXRelease(context);
//--- release resource and object
ResourceFree(resname);
ObjectDelete(0,objname);
//--- revert chart showing mode
ChartSetInteger(0,CHART_SHOW,true);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,328 @@
// Remnant X
// by David Hoskins.
// Thanks to boxplorer and the folks at 'Fractalforums.com'
// HD Video:- https://www.youtube.com/watch?v=BjkK9fLXXo0
// https://www.shadertoy.com/view/4sjSW1
struct PSInput
{
float4 position : SV_POSITION;
};
cbuffer Input
{
float2 iResolution;
float iTime;
float iDummy;
};
#define PI 3.14159265f
#define SCALE 2.8
#define MINRAD2 .25
#define scale (float4(SCALE, SCALE, SCALE, abs(SCALE)) / minRad2)
static const float minRad2 = clamp(MINRAD2, 1.0e-9, 1.0);
static const float absScalem1 = abs(SCALE - 1.0);
static const float AbsScaleRaisedTo1mIters = pow(abs(SCALE), float(1-10));
static const float3 surfaceColour1 = float3(.8, .0, 0.);
static const float3 surfaceColour2 = float3(.4, .4, 0.5);
static const float3 surfaceColour3 = float3(.5, 0.3, 0.00);
static const float3 fogCol = float3(0.4, 0.4, 0.4);
static const float3 sunDir=normalize(float3(0.35,0.1,0.3));
static const float4 sunColour=float4(1.0,0.95,0.8,0.2);
float2 Rand(float2 p)
{
return(float2(frac(sin(dot(p,float2(12.9898,78.233)))*6.7416516),frac(sin(dot(p,float2(58.6542,22.6546)))*6.5465145)));
}
float2 Texture(float2 p)
{
float2 p1=Rand(floor(p*256+float2(0,0)));
float2 p2=Rand(floor(p*256+float2(0,1)));
float2 p3=Rand(floor(p*256+float2(1,0)));
float2 p4=Rand(floor(p*256+float2(1,1)));
float2 f =frac(p*256);
return lerp(lerp(p1,p2,f.y),lerp(p3,p4,f.y),f.x);
}
//----------------------------------------------------------------------------------------
float Noise(in float3 x)
{
float3 p=floor(x);
float3 f=frac(x);
f=f*f*(3.0-2.0*f);
float2 uv=(p.xy+float2(37.0,17.0)*p.z)+f.xy;
float2 rg=Rand((uv+0.5)/256.0).yx;//texture(iChannel0,(uv+0.5)/256.0,-99.0).yx;
return lerp(rg.x,rg.y,f.z);
}
//----------------------------------------------------------------------------------------
float Map(float3 pos)
{
float4 p=float4(pos,1);
float4 p0=p; // p.w is the distance estimate
for(int i = 0; i < 9; i++)
{
p.xyz=clamp(p.xyz,-1.0,1.0)*2.0-p.xyz;
float r2=dot(p.xyz,p.xyz);
p*=clamp(max(minRad2/r2,minRad2),0.0,1.0);
// scale, translate
p=p*scale+p0;
}
return ((length(p.xyz)-absScalem1)/p.w-AbsScaleRaisedTo1mIters);
}
//----------------------------------------------------------------------------------------
float3 Colour(float3 pos, float sphereR)
{
float3 p=pos;
float3 p0=p;
float trap=1.0;
for(int i = 0; i < 6; i++)
{
p.xyz=clamp(p.xyz,-1.0,1.0)*2.0-p.xyz;
float r2 = dot(p.xyz,p.xyz);
p*=clamp(max(minRad2/r2,minRad2), 0.0, 1.0);
p=p*scale.xyz+p0.xyz;
trap=min(trap,r2);
}
// |c.x|: log final distance (fractional iteration count)
// |c.y|: spherical orbit trap at (0,0,0)
float2 c=clamp(float2(0.3333*log(dot(p,p))-1.0,sqrt(trap)),0.0, 1.0);
float t=fmod(length(pos)-iTime*1.5,16.0);
float3 surfaceColour=lerp(surfaceColour1,float3(0.4,3.0,5.0),pow(smoothstep(0.0,0.3,t)*smoothstep(0.6,.3,t),10.0));
return lerp(lerp(surfaceColour,surfaceColour2,c.y),surfaceColour3,c.x);
}
//----------------------------------------------------------------------------------------
float3 GetNormal(float3 pos, float distance)
{
distance*=0.001+.0001;
float2 eps=float2(distance,0.0);
float3 nor=float3(Map(pos+eps.xyy) - Map(pos-eps.xyy),
Map(pos+eps.yxy) - Map(pos-eps.yxy),
Map(pos+eps.yyx) - Map(pos-eps.yyx));
return normalize(nor);
}
//----------------------------------------------------------------------------------------
float GetSky(float3 pos)
{
pos*=0.02;
float2 t=0.5 *Texture(pos.xy*2.1) +0.5*Texture(pos.yz*2.3-(float2)0.53) +0.5*Texture(pos.zx*1.9+(float2)0.47)+
0.25 *Texture(pos.xy*4.7) +0.25*Texture(pos.yz*4.1+(float2)0.71) +0.25*Texture(pos.zx*4.3+(float2)0.59)+
0.125*Texture(pos.xy*8.7)+0.125*Texture(pos.yz*8.6-(float2)0.69)+0.125*Texture(pos.zx*8.3+(float2)0.95);
return(pow(t.x*t.y,0.5));
}
//----------------------------------------------------------------------------------------
float BinarySubdivision(in float3 rO, in float3 rD, float2 t)
{
float halfwayT;
for(int i = 0; i < 6; i++)
{
halfwayT=dot(t,float2(0.5,0.5));
float d = Map(rO + halfwayT*rD);
//if (abs(d) < 0.001) break;
t=lerp(float2(t.x,halfwayT),float2(halfwayT,t.y),step(0.0005, d));
}
return halfwayT;
}
//----------------------------------------------------------------------------------------
float2 Scene(in float3 rO, in float3 rD, in float2 fragCoord)
{
float t=.05+0.05*Texture(fragCoord.xy/256).y;//texture(iChannel0, fragCoord.xy / iChannelResolution[0].xy).y;
float3 p=float3(0.0,0.0,0.0);
float oldT=0.0;
bool hit=false;
float glow=0.0;
float2 dist;
for(int j=0; j < 100; j++)
{
if(t > 12.0)
break;
p=rO+t*rD;
float h=Map(p);
if(h<0.0005)
{
dist=float2(oldT,t);
hit=true;
break;
}
glow+=clamp(.05-h,0.0,.4);
oldT=t;
t+=h+t*0.001;
}
if(!hit)
t=1000.0;
else
t=BinarySubdivision(rO, rD, dist);
return float2(t,clamp(glow*.25, 0.0, 1.0));
}
//----------------------------------------------------------------------------------------
float Hash(float2 p)
{
return frac(sin(dot(p,float2(12.9898,78.233)))*33758.5453)-.5;
}
//----------------------------------------------------------------------------------------
float3 PostEffects(float3 rgb, float2 xy)
{
// Gamma first...
// Then...
#define CONTRAST 1.08
#define SATURATION 1.5
#define BRIGHTNESS 1.5
float tmp=dot(float3(.2125, .7154, .0721),rgb*BRIGHTNESS);
rgb=lerp(float3(0.5,0.5,0.5),lerp(float3(tmp,tmp,tmp),rgb*BRIGHTNESS,SATURATION),CONTRAST);
// Noise...
//rgb = clamp(rgb+Hash(xy*iTime)*.1, 0.0, 1.0);
// Vignette...
rgb*=.5+0.5*pow(20.0*xy.x*xy.y*(1.0-xy.x)*(1.0-xy.y), 0.2);
rgb=pow(rgb,float3(0.47,0.47,0.47));
return rgb;
}
//----------------------------------------------------------------------------------------
float Shadow(in float3 ro, in float3 rd)
{
float res=1.0;
float t=0.05;
float h;
for(int i = 0; i < 8; i++)
{
h=Map(ro+rd*t);
res=min(6.0*h/t,res);
t+=h;
}
return max(res, 0.0);
}
//----------------------------------------------------------------------------------------
float3x3 RotationMatrix(float3 axis, float angle)
{
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;
return float3x3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s,
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c);
}
//----------------------------------------------------------------------------------------
float3 LightSource(float3 spotLight, float3 dir, float dis)
{
float g=0.0;
if(length(spotLight) < dis)
{
g=pow(max(dot(normalize(spotLight),dir),0.0),200.0);
}
return(g*sunColour.rgb*sunColour.a);
}
//----------------------------------------------------------------------------------------
float3 CameraPath(float t)
{
float3 p=float3(-0.78+3.0*sin(2.14*t),0.05+2.5*sin(0.942*t+1.3),.05+3.5*cos(3.594*t));
return p;
}
//----------------------------------------------------------------------------------------
float4 mainImage(float2 fragCoord)
{
//float m=(iMouse.x/iResolution.x)*300.0;
//gTime = iTime+m*.01 + 15.00;
float gTime=iTime*0.01;
float2 xy =fragCoord/iResolution;
float2 uv =(-1.0+2.0*xy)*float2(iResolution.x/iResolution.y,1.0);
//return(float4(uv,0.0,1.0));
float3 cameraPos=CameraPath(gTime);
float3 camTar =CameraPath(gTime+.01);
float roll=13.0*sin(gTime*.5+.4);
float3 cw=normalize(camTar-cameraPos);
float3 cp=float3(sin(roll),cos(roll),0.0);
float3 cu=normalize(cross(cw,cp));
float3 cv=normalize(cross(cu,cw));
cw=mul(cw,RotationMatrix(cv,sin(-gTime*20.0)*.7));
float3 dir=normalize(uv.x*cu+uv.y*cv+1.3*cw);
float3 spotLight=CameraPath(gTime+.03)+float3(sin(gTime*18.4),cos(gTime*17.98),sin(gTime*22.53))*.2;
float3 col=float3(0.0,0.0,0.0);
float3 sky=float3(0.03,.04,.05)*GetSky(dir);
float2 ret=Scene(cameraPos,dir,fragCoord);
if(ret.x<900.0)
{
float3 p=cameraPos+ret.x*dir;
float3 nor=GetNormal(p,ret.x);
float3 spot=spotLight-p;
float atten=length(spot);
spot/=atten;
float shaSpot=Shadow(p,spot);
float shaSun=Shadow(p,sunDir);
float bri=max(dot(spot,nor),0.0)/pow(atten,1.5)*.15;
float briSun=max(dot(sunDir,nor),0.0)*.3;
col=Colour(p,ret.x);
col=(col*bri*shaSpot)+(col*briSun*shaSun);
float3 ref=reflect(dir,nor);
col+=pow(max(dot(spot,ref),0.0), 10.0)*2.0*shaSpot*bri;
col+=pow(max(dot(sunDir,ref),0.0),10.0)*2.0*shaSun *bri;
}
col=lerp(sky,col,min(exp(-ret.x+1.5),1.0));
col+=(float3)pow(abs(ret.y),2.) * float3(.02, .04, .1);
col+=LightSource(spotLight-cameraPos,dir,ret.x);
col=PostEffects(col, xy);
return(float4(col,1.0));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
float4 PSMain(PSInput input) : SV_TARGET
{
return(mainImage(input.position.xy));
}
//+------------------------------------------------------------------+
@@ -0,0 +1,18 @@
struct VSInput
{
float4 position : POSITION;
};
struct PSInput
{
float4 position : SV_POSITION;
};
PSInput VSMain(VSInput input)
{
PSInput output;
output.position=(input.position);
return(output);
}
Binary file not shown.
@@ -0,0 +1,217 @@
//+------------------------------------------------------------------+
//| SymbolInfoSample.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//---
#property script_show_inputs
//---
input bool InpMarketWatch=true;
//---
#include <Trade\SymbolInfo.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//---
#include "SymbolInfoSampleInit.mqh"
//+------------------------------------------------------------------+
//| Script to sample the use of class CSymbolInfo. |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Symbol Info Sample script class |
//+------------------------------------------------------------------+
class CSymbolInfoSample
{
protected:
CSymbolInfo m_symbol;
//--- chart objects
CChartObjectButton m_buttons[];
int m_num_symbols;
CChartObjectLabel m_label[40];
CChartObjectLabel m_label_info[40];
//---
int m_symbol_idx;
public:
CSymbolInfoSample(void);
~CSymbolInfoSample(void);
//---
bool Init(void);
void Deinit(void);
void Processing(void);
private:
void InfoToChart(void);
};
//---
CSymbolInfoSample ExtScript;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSymbolInfoSample::CSymbolInfoSample(void) : m_symbol_idx(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSymbolInfoSample::~CSymbolInfoSample(void)
{
}
//+------------------------------------------------------------------+
//| Method Init. |
//+------------------------------------------------------------------+
bool CSymbolInfoSample::Init(void)
{
int i,sy=10;
int dy=16;
color color_label;
color color_info;
//--- tuning colors
color_info =(color)(ChartGetInteger(0,CHART_COLOR_BACKGROUND)^0xFFFFFF);
color_label=(color)(color_info^0x202020);
//---
if(ChartGetInteger(0,CHART_SHOW_OHLC))
sy+=16;
//---
m_num_symbols=SymbolsTotal(InpMarketWatch);
if(!m_num_symbols)
return(false);
ArrayResize(m_buttons,m_num_symbols);
//--- creation Button[]
for(i=0;i<m_num_symbols;i++)
{
m_buttons[i].Create(0,"Button"+IntegerToString(i),0,10+50*(i%10),sy+20*(i/10),50,20);
m_buttons[i].Description(SymbolName(i,InpMarketWatch));
m_buttons[i].Color(clrRed);
m_buttons[i].FontSize(8);
}
m_symbol_idx=0;
m_buttons[0].State(true);
m_symbol.Name(m_buttons[0].Description());
sy+=20*(1+i/10);
//--- creation Labels[]
for(i=0;i<40;i++)
{
m_label[i].Create(0,"Label"+IntegerToString(i),0,init_l_x[i],sy+dy*init_l_y[i]);
m_label[i].Description(init_l_str[i]);
m_label[i].Color(color_label);
m_label[i].FontSize(8);
//---
m_label_info[i].Create(0,"LabelInfo"+IntegerToString(i),0,init_li_x[i],sy+dy*init_l_y[i]);
m_label_info[i].Description(" ");
m_label_info[i].Color(color_info);
m_label_info[i].FontSize(8);
}
InfoToChart();
//--- redraw chart
ChartRedraw();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method Deinit. |
//+------------------------------------------------------------------+
void CSymbolInfoSample::Deinit(void)
{
}
//+------------------------------------------------------------------+
//| Method Processing. |
//+------------------------------------------------------------------+
void CSymbolInfoSample::Processing(void)
{
int i;
//---
if(!m_buttons[m_symbol_idx].State())
m_buttons[m_symbol_idx].State(true);
for(i=0;i<m_num_symbols;i++)
{
if(m_buttons[i].State() && m_symbol_idx!=i)
{
m_buttons[m_symbol_idx].State(false);
m_symbol_idx=i;
m_symbol.Name(m_buttons[i].Description());
}
}
m_symbol.RefreshRates();
InfoToChart();
//--- redraw chart (with the processing of events)
ChartRedraw();
Sleep(50);
}
//+------------------------------------------------------------------+
//| Method InfoToChart. |
//+------------------------------------------------------------------+
void CSymbolInfoSample::InfoToChart(void)
{
int digits=m_symbol.Digits();
//--- display volumes
m_label_info[0].Description((string)m_symbol.Volume());
m_label_info[1].Description((string)m_symbol.VolumeHigh());
m_label_info[2].Description((string)m_symbol.VolumeLow());
//--- display miscellaneous
m_label_info[5].Description(TimeToString(m_symbol.Time()));
m_label_info[6].Description((string)m_symbol.Digits());
m_label_info[7].Description((string)m_symbol.Spread());
m_label_info[8].Description((string)m_symbol.TicksBookDepth());
//--- display terms of trade
m_label_info[9].Description(m_symbol.TradeCalcModeDescription());
m_label_info[10].Description(m_symbol.TradeModeDescription());
//--- display trade levels
m_label_info[11].Description((string)m_symbol.StopsLevel());
m_label_info[12].Description((string)m_symbol.FreezeLevel());
//--- display execution terms of trade
m_label_info[13].Description(m_symbol.TradeExecutionDescription());
//--- display swap terms of trade
m_label_info[14].Description(m_symbol.SwapModeDescription());
m_label_info[15].Description(m_symbol.SwapRollover3daysDescription());
//--- display bid
m_label_info[16].Description(DoubleToString(m_symbol.Bid(),digits));
m_label_info[17].Description(DoubleToString(m_symbol.BidHigh(),digits));
m_label_info[18].Description(DoubleToString(m_symbol.BidLow(),digits));
//--- display ask
m_label_info[19].Description(DoubleToString(m_symbol.Ask(),digits));
m_label_info[20].Description(DoubleToString(m_symbol.AskHigh(),digits));
m_label_info[21].Description(DoubleToString(m_symbol.AskLow(),digits));
//--- display last
m_label_info[22].Description(DoubleToString(m_symbol.Last(),digits));
m_label_info[23].Description(DoubleToString(m_symbol.LastHigh(),digits));
m_label_info[24].Description(DoubleToString(m_symbol.LastLow(),digits));
//--- display tick
m_label_info[25].Description(DoubleToString(m_symbol.Point(),digits));
m_label_info[26].Description(DoubleToString(m_symbol.TickValue()));
m_label_info[27].Description(DoubleToString(m_symbol.TickSize()));
m_label_info[28].Description(DoubleToString(m_symbol.ContractSize()));
//--- display lots
m_label_info[29].Description(DoubleToString(m_symbol.LotsMin(),2));
m_label_info[30].Description(DoubleToString(m_symbol.LotsMax(),2));
m_label_info[31].Description(DoubleToString(m_symbol.LotsStep(),2));
//--- display swaps
m_label_info[32].Description(DoubleToString(m_symbol.SwapLong(),2));
m_label_info[33].Description(DoubleToString(m_symbol.SwapShort(),2));
//--- display currency
m_label_info[34].Description(m_symbol.CurrencyBase());
m_label_info[35].Description(m_symbol.CurrencyProfit());
m_label_info[36].Description(m_symbol.CurrencyMargin());
//--- display another
m_label_info[37].Description(m_symbol.Bank());
m_label_info[38].Description(m_symbol.Description());
m_label_info[39].Description(m_symbol.Path());
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
int OnStart(void)
{
//--- call init function
if(ExtScript.Init())
{
//--- cycle until the script is not halted
while(!IsStopped())
ExtScript.Processing();
}
//--- call deinit function
ExtScript.Deinit();
//---
return(0);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,40 @@
//+------------------------------------------------------------------+
//| TestSymbolInfoInit.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//---
//+------------------------------------------------------------------+
//| Arrays to initialize graphics objects SymbolInfoSample. |
//+------------------------------------------------------------------+
//--- for ExtLabel[]
int init_l_x[]=
{
20,220,420,220,420,20,20,220,20,20,
20,20,220,20,20,20,20,220,420,20,
220,420,20,220,420,20,20,220,20,20,
220,420,20,220,20,220,420,20,20,20
};
int init_l_y[]=
{
1,1,1,2,2,3,4,4,5,6,
7,8,8,9,10,11,12,12,12,13,
13,13,14,14,14,15,16,16,17,18,
18,18,19,19,20,20,20,21,22,23
};
string init_l_str[]=
{
"Volume","VolumeHigh","VolumeLow","VolumeBid","VolumeAsk","Time","Digits","Spread","TicksBookDepth","TradeCalcMode",
"TradeMode","StopsLevel","FreezeLevel","TradeExecution","SwapMode","SwapRollover3days","Bid","BidHigh","BidLow","Ask",
"AskHigh","AskLow","Last","LastHigh","LastLow","Point","TickValue","TickSize","ContractSize","VolumeMin",
"VolumeMax","VolumeStep","SwapLong","SwapShort","CurrencyBase","CurrencyProfit","CurrencyMargin","Bank","Description","Path"
};
//--- for ExtLabelInfo[]
int init_li_x[]=
{
120,320,520,320,520,120,120,320,120,120,
120,120,320,120,120,120,120,320,520,120,
320,520,120,320,520,120,120,320,120,120,
320,520,120,320,120,320,520,120,120,120
};
//+------------------------------------------------------------------+