Article-13244-MQL5-Template.../TestOscillatorATR.mq5

326 lines
31 KiB
MQL5
Raw Permalink Normal View History

2026-03-20 00:20:09 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| TestOscillatorATR.mq5 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//--- includes
#include "Dashboard.mqh"
2026-03-20 00:20:09 +07:00
//--- enums
enum ENUM_LINE_STATE
{
LINE_STATE_NONE, // 5>?@545;Q==>5 A>AB>O=85
LINE_STATE_UP, // 0?@02;5=85 225@E
LINE_STATE_DOWN, // 0?@02;5=85 2=87
LINE_STATE_TURN_UP, // 072>@>B 225@E
LINE_STATE_TURN_DOWN, // 072>@>B 2=87
LINE_STATE_STOP_UP, // AB0=>2:0 =0?@02;5=8O 225@E
LINE_STATE_STOP_DOWN, // AB0=>2:0 =0?@02;5=8O 2=87
LINE_STATE_ABOVE, // 04 7=0G5=85<
LINE_STATE_UNDER, // >4 7=0G5=85<
LINE_STATE_CROSS_UP, // 5@5A5G5=85 7=0G5=8O 225@E
LINE_STATE_CROSS_DOWN, // 5@5A5G5=85 7=0G5=8O 2=87
LINE_STATE_TOUCH_BELOW, // 0A0=85 7=0G5=8O A=87C
LINE_STATE_TOUCH_ABOVE, // 0A0=85 7=0G5=8O A25@EC
LINE_STATE_EQUALS, // 02=> 7=0G5=8N
};
//--- input parameters
input uint InpPeriod = 14; /* ATR Period */ // 5@8>4 @0AGQB0 ATR
//--- global variables
int handle=INVALID_HANDLE; // %M=4; 8=48:0B>@0
int period=0; // 5@8>4 @0AGQB0 ATR
int ind_digits=0; // >;8G5AB2> 7=0:>2 ?>A;5 70?OB>9 2 7=0G5=88 8=48:0B>@0
string ind_title; // ?8A0=85 8=48:0B>@0
//--- ?5@5<5==K5 4;O ?0=5;8
int mouse_bar_index; // =45:A 10@0, A :>B>@>3> 15@CBAO 40==K5
CDashboard *panel=NULL; // #:070B5;L =0 >1J5:B ?0=5;8
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- create timer
EventSetTimer(60);
//--- =48:0B>@
//--- #AB0=02;8205< 8 :>@@5:B8@C5< ?@8 =5>1E>48<>AB8 ?5@8>4 @0AGQB0
period=int(InpPeriod<1 ? 14 : InpPeriod);
//--- #AB0=02;8205< =08<5=>20=85 8=48:0B>@0 8 :>;8G5AB2> 7=0:>2 ?>A;5 70?OB>9
ind_title=StringFormat("ATR(%lu)",period);
ind_digits=Digits();
//--- !>740Q< EM=4; 8=48:0B>@0
ResetLastError();
handle=iATR(Symbol(),PERIOD_CURRENT,period);
if(handle==INVALID_HANDLE)
{
PrintFormat("%s: Failed to create indicator handle %s. Error %ld",__FUNCTION__,ind_title,GetLastError());
return INIT_FAILED;
}
//--- 0=5;L
//--- !>740Q8 ?0=5;L
panel=new CDashboard(1,20,20,199,225);
if(panel==NULL)
{
Print("Error. Failed to create panel object");
return INIT_FAILED;
}
//--- #AB0=02;8205< ?0@0<5B@K H@8DB0
panel.SetFontParams("Calibri",9);
//--- B>1@0605< ?0=5;L A B5:AB>< 2 703>;>2:5 "!8<2>;, ?8A0=85 B09<D@59<0"
panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
//--- !>740Q< B01;8FC A 845=B8D8:0B>@>< 0 4;O >B>1@065=8O 2 =59 40==KE 10@0
panel.CreateNewTable(0);
//--- 8AC5< B01;8FC A 845=B8D8:0B>@>< 0 =0 D>=5 ?0=5;8
panel.DrawGrid(0,2,20,6,2,18,97);
//--- !>740Q< B01;8FC A 845=B8D8:0B>@>< 1 4;O >B>1@065=8O 2 =59 40==KE 8=48:0B>@0
panel.CreateNewTable(1);
//--- >;CG05< :>>@48=0BC Y2 B01;8FK A 845=B8D8:0B>@>< 0 8
//--- CAB0=02;8205< :>>@48=0BC Y1 4;O B01;8FK A 845=B8D8:0B>@>< 1
int y1=panel.TableY2(0)+22;
//--- 8AC5< B01;8FC A 845=B8D8:0B>@>< 1 =0 D>=5 ?0=5;8
panel.DrawGrid(1,2,y1,3,2,18,97);
//--- K2>48< 2 6C@=0; B01;8G=K5 40==K5
panel.GridPrint(0,2);
panel.GridPrint(1,2);
//--- =8F80;878@C5< ?5@5<5==CN A 8=45:A>< 10@0 C:070B5;O <KH:8
mouse_bar_index=0;
//--- K2>48< =0 ?0=5;L 40==K5 B5:CI53> 10@0
DrawData(mouse_bar_index,TimeCurrent());
//--- #A?5H=0O 8=8F80;870F8O
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- destroy timer
EventKillTimer();
//--- A2>1>6405< EM=4; 8=48:0B>@0
ResetLastError();
if(!IndicatorRelease(handle))
PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError());
//--- G8I05< 2A5 :><<5=B0@88 =0 3@0D8:5
Comment("");
//--- A;8 >1J5:B ?0=5;8 ACI5AB2C5B - C40;O5< 53>
if(panel!=NULL)
delete panel;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- 01>B0 A ?0=5;LN
//--- K7K205< >1@01>BG8: A>1KB89 ?0=5;8
panel.OnChartEvent(id,lparam,dparam,sparam);
//--- A;8 :C@A>@ ?5@5<5I05BAO 8;8 I5;G>: ?> 3@0D8:C
if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
{
//--- 1JO2;O5< ?5@5<5==K5 4;O 70?8A8 2 =8E :>>@48=0B 2@5<5=8 8 F5=K
datetime time=0;
double price=0;
int wnd=0;
//--- A;8 :>>@48=0BK :C@A>@0 ?@5>1@07>20=K 2 40BC 8 2@5<O
if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
{
//--- 70?8AK205< 8=45:A 10@0, 345 @0A?>;>65= :C@A>@ 2 3;>10;L=CN ?5@5<5==CN
mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
//--- K2>48< 40==K5 10@0 ?>4 :C@A>@>< =0 ?0=5;L
DrawData(mouse_bar_index,time);
}
}
//--- A;8 ?>;CG8;8 ?>;L7>20B5;LA:>5 A>1KB85 - 2K2>48< >1 MB>< A>>1I5=85 2 6C@=0;
if(id>CHARTEVENT_CUSTOM)
{
//--- 45AL <>65B 1KBL >1@01>B:0 I5;G:0 ?> :=>?:5 70:@KB8O =0 ?0=5;8
PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
}
}
//+------------------------------------------------------------------+
//| >72@0I05B 40==K5 8=48:0B>@0 =0 C:070==>< 10@5 |
//+------------------------------------------------------------------+
double IndicatorValue(const int ind_handle,const int index,const int buffer_num)
{
double array[1]={0};
ResetLastError();
if(CopyBuffer(ind_handle,buffer_num,index,1,array)!=1)
{
PrintFormat("%s: CopyBuffer failed. Error %ld",__FUNCTION__,GetLastError());
return EMPTY_VALUE;
}
return array[0];
}
//+------------------------------------------------------------------+
//| >72@0I05B A>AB>O=85 ;8=88 8=48:0B>@0 |
//+------------------------------------------------------------------+
ENUM_LINE_STATE LineState(const int ind_handle,const int index,const int buffer_num)
{
//--- >;CG05< 7=0G5=8O ;8=88 8=48:0B>@0 A> A<5I5=85< (0,1,2) >B=>A8B5;L=> ?5@540==>3> 8=45:A0
const double value0=IndicatorValue(ind_handle,index, buffer_num);
const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
const double value2=IndicatorValue(ind_handle,index+2,buffer_num);
//--- A;8 E>BL >4=> 87 7=0G5=89 ?>;CG8BL =5 C40;>AL - 2>72@0I05< =5>?@545;Q==>5 7=0G5=85
if(value0==EMPTY_VALUE || value1==EMPTY_VALUE || value2==EMPTY_VALUE)
return LINE_STATE_NONE;
//--- 072>@>B ;8=88 225@E (value2>value1 && value0>value1)
if(NormalizeDouble(value2-value1,ind_digits)>0 && NormalizeDouble(value0-value1,ind_digits)>0)
return LINE_STATE_TURN_UP;
//--- 0?@02;5=85 ;8=88 225@E (value2<=value1 && value0>value1)
else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)>0)
return LINE_STATE_UP;
//--- AB0=>2:0 =0?@02;5=8O ;8=88 225@E (value2<=value1 && value0==value1)
else if(NormalizeDouble(value2-value1,ind_digits)<=0 && NormalizeDouble(value0-value1,ind_digits)==0)
return LINE_STATE_STOP_UP;
//--- 072>@>B ;8=88 2=87 (value2<value1 && value0<value1)
if(NormalizeDouble(value2-value1,ind_digits)<0 && NormalizeDouble(value0-value1,ind_digits)<0)
return LINE_STATE_TURN_DOWN;
//--- 0?@02;5=85 ;8=88 2=87 (value2>=value1 && value0<value1)
else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)<0)
return LINE_STATE_DOWN;
//--- AB0=>2:0 =0?@02;5=8O ;8=88 2=87 (value2>=value1 && value0==value1)
else if(NormalizeDouble(value2-value1,ind_digits)>=0 && NormalizeDouble(value0-value1,ind_digits)==0)
return LINE_STATE_STOP_DOWN;
//--- 5>?@545;Q==>5 A>AB>O=85
return LINE_STATE_NONE;
}
//+------------------------------------------------------------------+
//| >72@0I05B A>AB>O=85 ;8=88 >B=>A8B5;L=> C:070==>3> C@>2=O |
//+------------------------------------------------------------------+
ENUM_LINE_STATE LineStateRelative(const int ind_handle,const int index,const int buffer_num,const double level0,const double level1=EMPTY_VALUE)
{
//--- >;CG05< 7=0G5=8O ;8=88 8=48:0B>@0 A> A<5I5=85< (0,1) >B=>A8B5;L=> ?5@540==>3> 8=45:A0
const double value0=IndicatorValue(ind_handle,index, buffer_num);
const double value1=IndicatorValue(ind_handle,index+1,buffer_num);
//--- A;8 E>BL >4=> 87 7=0G5=89 ?>;CG8BL =5 C40;>AL - 2>72@0I05< =5>?@545;Q==>5 7=0G5=85
if(value0==EMPTY_VALUE || value1==EMPTY_VALUE)
return LINE_STATE_NONE;
//--- ?@545;O5< 2B>@>9 A@02=8205<K9 C@>25=L
double level=(level1==EMPTY_VALUE ? level0 : level1);
//--- 8=8O =0E>48BAO ?>4 C@>2=5< (value1<level && value0<level0)
if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)<0)
return LINE_STATE_UNDER;
//--- 8=8O =0E>48BAO =04 C@>2=5< (value1>level && value0>level0)
if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)>0)
return LINE_STATE_ABOVE;
//--- 8=8O ?5@5A5:;0 C@>25=L A=87C-225@E (value1<=level && value0>level0)
if(NormalizeDouble(value1-level,ind_digits)<=0 && NormalizeDouble(value0-level0,ind_digits)>0)
return LINE_STATE_CROSS_UP;
//--- 8=8O ?5@5A5:;0 C@>25=L A25@EC-2=87 (value1>=level && value0<level0)
if(NormalizeDouble(value1-level,ind_digits)>=0 && NormalizeDouble(value0-level0,ind_digits)<0)
return LINE_STATE_CROSS_DOWN;
//--- 8=8O :>A=C;0AL C@>2=O A=87C (value1<level0 && value0==level0)
if(NormalizeDouble(value1-level,ind_digits)<0 && NormalizeDouble(value0-level0,ind_digits)==0)
return LINE_STATE_TOUCH_BELOW;
//--- 8=8O :>A=C;0AL C@>2=O A25@EC (value1>level0 && value0==level0)
if(NormalizeDouble(value1-level,ind_digits)>0 && NormalizeDouble(value0-level0,ind_digits)==0)
return LINE_STATE_TOUCH_BELOW;
//--- 8=8O @02=0 7=0G5=8N C@>2=O (value1==level0 && value0==level0)
if(NormalizeDouble(value1-level,ind_digits)==0 && NormalizeDouble(value0-level0,ind_digits)==0)
return LINE_STATE_EQUALS;
//--- 5>?@545;Q==>5 A>AB>O=85
return LINE_STATE_NONE;
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 A>AB>O=8O ;8=88 8=48:0B>@0 |
//+------------------------------------------------------------------+
string LineStateDescription(const ENUM_LINE_STATE state)
{
switch(state)
{
case LINE_STATE_UP : return "Up";
case LINE_STATE_STOP_UP : return "Stop Up";
case LINE_STATE_TURN_UP : return "Turn Up";
case LINE_STATE_DOWN : return "Down";
case LINE_STATE_STOP_DOWN : return "Stop Down";
case LINE_STATE_TURN_DOWN : return "Turn Down";
case LINE_STATE_ABOVE : return "Above level";
case LINE_STATE_UNDER : return "Under level";
case LINE_STATE_CROSS_UP : return "Crossing Up";
case LINE_STATE_CROSS_DOWN : return "Crossing Down";
case LINE_STATE_TOUCH_BELOW: return "Touch from Below";
case LINE_STATE_TOUCH_ABOVE: return "Touch from Above";
case LINE_STATE_EQUALS : return "Equals";
default : return "Unknown";
}
}
//+------------------------------------------------------------------+
//| K2>48B 40==K5 A C:070==>3> 8=45:A0 B09<A5@88 =0 ?0=5;L |
//+------------------------------------------------------------------+
void DrawData(const int index,const datetime time)
{
//--- 1JO2;O5< ?5@5<5==K5 4;O ?>;CG5=8O 2 =8E 40==KE
MqlTick tick={0};
MqlRates rates[1];
//--- A;8 B5:CI85 F5=K ?>;CG8BL =5 C40;>AL - CE>48<
if(!SymbolInfoTick(Symbol(),tick))
return;
//--- A;8 40==K5 10@0 ?> C:070==><C 8=45:AC ?>;CG8BL =5 C40;>AL - CE>48<
if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
return;
//--- #AB0=02;8205< ?0@0<5B@K H@8DB0 4;O 703>;>2:>2 40==KE 10@0 8 8=48:0B>@0
int size=0;
uint flags=0;
uint angle=0;
string name=panel.FontParams(size,flags,angle);
panel.SetFontParams(name,9,FW_BOLD);
panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
panel.DrawText("Indicator data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
//--- #AB0=02;8205< ?0@0<5B@K H@8DB0 4;O 40==KE 10@0 8 8=48:0B>@0
panel.SetFontParams(name,9);
//--- K2>48< =0 ?0=5;L 40==K5 C:070==>3> 10@0 2 B01;8FC 0
panel.DrawText("Date", panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString( rates[0].time,TIME_DATE), panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
panel.DrawText("Time", panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString( rates[0].time,TIME_MINUTES), panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
panel.DrawText("Open", panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()), panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
panel.DrawText("High", panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()), panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
panel.DrawText("Low", panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()), panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()), panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
//--- K2>48< =0 ?0=5;L 40==K5 8=48:0B>@0 A C:070==>3> 10@0 2 B01;8FC 1
panel.DrawText(ind_title, panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
double value=IndicatorValue(handle,index,0);
string value_str=(value!=EMPTY_VALUE ? DoubleToString(value,ind_digits) : "");
panel.DrawText(value_str,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,90);
//--- K2>48< >?8A0=85 A>AB>O=8O ;8=88 8=48:0B>@0
panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
ENUM_LINE_STATE state=LineState(handle,index,0);
panel.DrawText(LineStateDescription(state),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,90);
//--- 5@5@8A>2K205< 3@0D8: 4;O =5<54;5==>3> >B>1@065=8O 2A5E 87<5=5=89 =0 ?0=5;8
ChartRedraw(ChartID());
}
//+------------------------------------------------------------------+