MultiSymbolSignals/Indicators/MultiSymbol/ATR_MS.mq5

1208 lines
106 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:10:44 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| ATR_MS.mq5 |
//| Copyright 2013, https://login.mql5.com/ru/users/tol64 |
//| Site, http://tol64.blogspot.com/2013/05/216.html |
//+------------------------------------------------------------------+
//--- !2>9AB20 8=48:0B>@0
#property copyright "Copyright 2013, http://tol64.blogspot.com"
#property link "https://www.mql5.com/de/articles/752"
#property description "email: hello.tol64@gmail.com"
#property version "1.0"
#property indicator_separate_window // =48:0B>@ 2 >B45;L=>< ?>4>:=5
#property indicator_minimum 0 // 8=8<0;L=>5 7=0G5=85 8=48:0B>@0
#property indicator_buffers 6 // >;8G5AB2> 1CD5@>2 4;O @0AGQB0 8=48:0B>@0
#property indicator_plots 6 // >;8G5AB2> 3@0D8G5A:8E A5@89
//--- >=AB0=B0 4;O 2>72@0B0 B5@<8=0;C :><0=4K =0 ?5@5AGQB 8=48:0B>@0
#define RESET 0
#define LEVELS 6 // >;8G5AB2> C@>2=59
#define SYMBOLS 6 // >;8G5AB2> A8<2>;>2
//--- >4:;NG8< :;0AA 4;O @01>BK A :0=2>9
#include <Canvas\Canvas.mqh>
//--- =5H=85 ?0@0<5B@K
input int IndicatorPeriod=14; // Indicator Period
sinput string dlm01=""; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
input string Symbol02 ="GBPUSD"; // Symbol 02
input string Symbol03 ="AUDUSD"; // Symbol 03
input string Symbol04 ="NZDUSD"; // Symbol 04
input string Symbol05 ="USDCAD"; // Symbol 05
input string Symbol06 ="USDCHF"; // Symbol 06
sinput string dlm02=""; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
input int Level01 =10; // Level 01
input int Level02 =50; // Level 02
input int Level03 =100; // Level 03
input int Level04 =200; // Level 04
input int Level05 =400; // Level 05
input int Level06 =600; // Level 06
//--- ;>10;L=K5 ?5@5<5==K5 8 <0AA82K
CCanvas canvas; // 03@C7:0 :;0AA0
//--- 5@5<5==K5/<0AA82K 4;O :>?8@>20=8O 40==KE 87 OnCalculate()
int on_calc_rates_total =0; // 07<5@ 2E>4=KE B09<A5@89
int on_calc_prev_calculated =0; // 1@01>B0=> 10@>2 =0 ?@54K4CI5< 2K7>25
datetime on_calc_time[]; // @5<O >B:@KB8O
double on_calc_open[]; // &5=K >B:@KB8O
double on_calc_high[]; // 0:A8<0;L=K5 F5=K
double on_calc_low[]; // 8=8<0;L=K5 F5=K
double on_calc_close[]; // &5=K 70:@KB8O
long on_calc_tick_volume[]; // "8:>2K5 >1JQ<K
long on_calc_volume[]; // 50;L=K5 >1JQ<K
int on_calc_spread[]; // !?@54
//--- !B@C:BC@0 <0AA82>2 1CD5@>2
// 4;O >B@8A>2:8 7=0G5=89 8=48:0B>@0
struct buffers { double data[]; };
buffers buffer_atr[SYMBOLS];
//--- !B@C:BC@K <0AA82>2 4;O ?>43>B>2:8 40==KE
struct temp_time { datetime time[]; };
temp_time temp_symbol_time[SYMBOLS];
struct temp_atr { double value[]; };
temp_atr temp_atr_values[SYMBOLS];
//--- ;O E@0=5=8O 8 ?@>25@:8 2@5<5=8 ?5@2>3> 10@0 2 B5@<8=0;5
datetime series_first_date[SYMBOLS];
datetime series_first_date_last[SYMBOLS];
//--- 0AA82 2@5<5=8 10@0, >B :>B>@>3> =0G8=0BL >B@8A>2:C
datetime limit_time[SYMBOLS];
//--- 0AA82 C@>2=59 8=48:0B>@0
int levels[LEVELS];
//--- 0AA82 =0720=89 A8<2>;>2
string symbols_names[SYMBOLS];
//--- %M=4;K A8<2>;>2
int handle_symbol[SYMBOLS];
//--- &25B0 ;8=89 8=48:0B>@0
color line_color[SYMBOLS]=
{clrRed,clrDodgerBlue,clrLimeGreen,clrGold,clrAqua,clrMagenta};
//--- !B@>:0 A8<2>;878@CNI0O >BACBAB285 A8<2>;0
string empty_symbol="EMPTY";
//--- !2>9AB20 ?>4>:=0 8=48:0B>@0
int number_subwindow =WRONG_VALUE; // ><5@ ?>4>:=0
int chart_width =0; // (8@8=0 3@0D8:0
int subwindow_height =0; // KA>B0 ?>4>:=0
int last_chart_width =0; // >A;54=OO 2 ?0<OB8 H8@8=0 3@0D8:0
int last_subwindow_height =0; // >A;54=OO 2 ?0<OB8 2KA>B0 ?>4>:=0
int subwindow_center =0; // &5=B@ ?>4>:=0 ?> 3>@87>=B0;8
int subwindow_vcenter =0; // &5=B@ ?>4>:=0 ?> 25@B8:0;8
string shortname_subwindow ="ATR_MS"; // >@>B:>5 8<O 8=48:0B>@0
string prefix =shortname_subwindow+"_"; // @5D8:A 4;O >1J5:B>2
//--- !2>9AB20 :0=2K
string canvas_name =prefix+"canvas"; // 0720=85 :0=2K
color canvas_bg_color =clrBlack; // &25B D>=0 :0=2K
uchar canvas_opacity =190; // !B5?5=L ?@>7@0G=>AB8
int font_size =16; // 07<5@ H@8DB0
string font_name ="Calibri"; // (@8DB
ENUM_COLOR_FORMAT clr_format =COLOR_FORMAT_ARGB_RAW; // ><?>=5=BK F25B0 =5 >1@010BK20NBAO B5@<8=0;><
//--- !>>1I5=8O :0=2K
string message_invalid_handle ="520;84=K9 EM=4; 8=48:0B>@0! >4>648B5 ?>60;C9AB0...";
string message_data_available =">43>B>2:0 40==KE! >4>648B5 ?>60;C9AB0...";
string message_number_data ="0==KE <5=LH5, G5< ?5@8>4 8=48:0B>@0! >?@>1C9B5 C<5=LH8BL 7=0G5=85.";
string message_is_synchronized ="0==K5 =5 A8=E@>=878@>20=K! >4>648B5 ?>60;C9AB0...";
string message_formation_data ="";
string message_synchro_update ="";
string message_last ="";
//--- 0:A8<0;L=>5 :>;8G5AB2> 10@>2 CAB0=>2;5==>5 2 =0AB@>9:0E B5@<8=0;0
int terminal_max_bars=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- @>25@8< :>@@5:B=>ABL 2E>4=KE ?0@0<5B@>2
if(!CheckInputParameters())
return(INIT_PARAMETERS_INCORRECT);
//--- :;NG8< B09<5@ A 8=B5@20;>< 1 A5:C=40
EventSetMillisecondTimer(1000);
//--- #AB0=>28< H@8DB 4;O >B>1@065=8O 2 :0=25
canvas.FontSet(font_name,font_size,FW_NORMAL);
//--- =8F80;870F8O <0AA82>2
InitArrays();
//--- =8F80;878@C5< <0AA82 A8<2>;>2
InitSymbolsNames();
//--- =8F80;878@C5< <0AA82 C@>2=59
InitLevels();
//--- >;CG8< EM=4;K 8=48:0B>@>2
GetHandles();
//--- #AB0=>28< A2>9AB20 8=48:0B>@0
SetPropertiesIndicator();
//--- >;CG8< :>;8G5AB2> 10@>2 CAB0=>2;5==>5 2 =0AB@>9:0E B5@<8=0;0
terminal_max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
//--- G8AB8< :><<5=B0@89
Comment("");
//--- 1=>28< 3@0D8:
ChartRedraw();
//--- =8F80;870F8O ?@>H;0 CA?5H=>
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 58=8F80;870F8O |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(reason==REASON_REMOVE || // A;8 8=48:0B>@ C40;Q= A 3@0D8:0 8;8
reason==REASON_CHARTCHANGE || // A8<2>; 8;8 ?5@8>4 1K; 87<5=Q= 8;8
reason==REASON_RECOMPILE || // ?@>3@0<<0 1K;0 ?5@5:><?8;8@>20=0 8;8
reason==REASON_CHARTCLOSE || // 3@0D8: 1K; 70:@KB 8;8
reason==REASON_CLOSE || // B5@<8=0; 1K; 70:@KB 8;8
reason==REASON_PARAMETERS) // ?0@0<5B@K 1K;8 87<5=5=K
{
//--- B:;NG8< B09<5@
EventKillTimer();
//--- #40;8< C@>2=8
DeleteLevels();
//--- #40;8< 25@B8:0;L=K5 ;8=88
DeleteVerticalLines();
//--- #40;8< :0=2C
DeleteCanvas();
//--- A2>1>48< @0AGQB=CN G0ABL 8=48:0B>@0
for(int s=0; s<SYMBOLS; s++)
IndicatorRelease(handle_symbol[s]);
//--- G8AB8< :><<5=B0@89
Comment("");
}
//--- 1=>28< 3@0D8:
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, // @07<5@ 2E>4=KE B09<A5@89
const int prev_calculated, // >1@01>B0=> 10@>2 =0 ?@54K4CI5< 2K7>25
const datetime &time[], // @5<O >B:@KB8O
const double &open[], // &5=K >B:@KB8O
const double &high[], // 0:A8<0;L=K5 F5=K
const double &low[], // 8=8<0;L=K5 F5=K
const double &close[], // &5=K 70:@KB8O
const long &tick_volume[], // "8:>2K5 >1JQ<K
const long &volume[], // 50;L=K5 >1JQ<K
const int &spread[]) // !?@54
{
//--- ;O >?@545;5=8O, A :0:>3> 10@0 ?@>872>48BL @0AGQB
// To determine which bar to calculate
int limit=0;
//--- !45;05< :>?8N ?0@0<5B@>2 OnCalculate()
// Make a copy of the OnCalculate() parameters
CopyDataOnCalculate(rates_total,prev_calculated,
time,open,high,low,close,
tick_volume,volume,spread);
//--- #AB0=>28< @07<5@ <0AA820< 4;O ?>43>B>2:8 40==KE
// Set size for arrays for data preparation
ResizeCalculateArrays();
//--- A;8 MB> ?5@2K9 @0AGQB 8;8 703@C65=0 1>;55 3;C1>:0O 8AB>@8O 8;8 1K;8 70?>;=5=K ?@>?CA:8 8AB>@88
// If this is the FIRST calculation or DOWNLOAD of deeper history or FILLING of history gaps
if(prev_calculated==0)
{
//--- 1=C;8< <0AA82K 4;O ?>43>B>2:8 40==KE
// Zero the arrays for data preparation.
ZeroCalculateArrays();
//--- 1=C;8< 8=48:0B>@=K5 1CD5@K
// Zero indicator buffers
ZeroIndicatorBuffers();
//--- >;CG8< A2>9AB20 ?>4>:=0
SetSubwindowProperties();
//--- #AB0=>28< :0=2C
SetCanvas();
//--- rf. https://www.mql5.com/en/docs/series/timeseries_access
// LoadFormationData() - SERIES_FIRSTDATE, SERIES_SERVER_FIRSTDATE
// CheckAvailableData() - CopyTime() and CopyBuffer() from SERIES_TERMINAL_FIRSTDATE to TimeCurrent()
// CheckEventLoadHistory() -
// CheckSymbolIsSynchronized() - SERIES_SYNCHRONIZED, TERMINAL_CONNECTED
// DetermineBeginForCalculate() -
//--- 03@C78< 8 AD>@<8@C5< =5>1E>48<>5/8<5NI55AO :>;8G5AB2> 40==KE
// Load and generate the necessary / available amount of data
LoadFormationData();
//--- A;8 5ABL =520;84=K9 EM=4;, ?>?@>1C5< ?>;CG8BL 53> A=>20
// If there is an invalid handle, try to get it again.
if(!GetHandles())
return(RESET);
//--- @>25@O5B :>;8G5AB2> 4>ABC?=KE 40==KE C 2A5E A8<2>;>2
// Checks the amount of data available for all symbols.
if(!CheckAvailableData())
return(RESET);
//--- A;8 703@C65=0 1>;55 3;C1>:0O 8AB>@8O
// if loading a deeper history
if(!CheckEventLoadHistory())
return(RESET);
//--- @>25@8< A8=E@>=878@>20==>ABL 40==KE ?> A8<2>;C/?5@8>4C =0 40==K9 <><5=B
// Check the synchronization of data on the symbol / period at the moment
if(!CheckSymbolIsSynchronized())
return(RESET);
//--- ?@545;8< 4;O :064>3> A8<2>;0, A :0:>3> 10@0 =0G8=0BL >B@8A>2:C
// Determine for each symbol, from which bar to start drawing
if(!DetermineBeginForCalculate())
return(RESET);
//--- A;8 4>H;8 4> MB>3> <><5=B0, B> 7=0G8B OnCalculate() 25@=QB =5=C;52>5 7=0G5=85 8
// MB> =C6=> 70?><=8BL
// If you have reached this point, it means OnCalculate () returns a nonzero value and
// you need to remember this.
on_calc_prev_calculated=rates_total;
}
//--- A;8 =C6=> ?5@5AG8B0BL B>;L:> ?>A;54=85 7=0G5=8O
// If you need to recount only the last values
else
limit=prev_calculated-1;
//--- >43>B>28< 40==K5 4;O >B@8A>2:8
// Prepare data for rendering
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 A8<2>; ACI5AB2C5B
// If symbol exists
if(symbols_names[s]!=empty_symbol)
{
double percent=0.0; // ;O @0AGQB0 ?@>F5=B0 ?@>3@5AA0 - To calculate the percentage of progress
message_last=message_synchro_update=">43>B>2:0 40==KE ("+IntegerToString(rates_total)+" 10@>2) : "+
symbols_names[s]+"("+IntegerToString(s+1)+"/"+IntegerToString(SYMBOLS)+") - 00% ... ";
//--- K2545< A>>1I5=85 - Display message
ShowCanvasMessage(message_synchro_update);
//--- @>:>=B@>;8@C5< :064>5 7=0G5=85 <0AA820
// We control each array value
for(int i=limit; i<rates_total; i++)
{
PreparationData(i,s,time);
//--- 064K5 1000 10@>2 >1=>2;O5< A>>1I5=85
// Every 1000 bars update message
if(!(i%1000))
{
//--- @>F5=B ?@>3@5AA0 - percentage of progress
PercentProgress(i,s,percent);
//--- K2545< A>>1I5=85 - We will display the message
ShowCanvasMessage(message_synchro_update);
}
//--- 064K5 2000 10@>2 ?@>25@O5< @07<5@K ?>4>:=0
// 8 5A;8 @07<5@ 87<5=8;AO ?>43>=8< ?>4 =53> @07<5@ :0=2K
// Every 2000 bars we check the dimensions of the subwindow
// and if the size has changed we will fit the size of the canvas
if(!(i%2000))
EventChartChange();
}
}
}
//--- 0?>;=8< 8=48:0B>@=K5 1CD5@K
// We will fill indicator buffers
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 C:070==>3> A8<2>;0 =5 ACI5AB2C5B, >1=C;8< 1CD5@
// If the specified character does not exist, zero the buffer
if(symbols_names[s]==empty_symbol)
ArrayInitialize(buffer_atr[s].data,EMPTY_VALUE);
else
{
//--- !D>@<8@C5< A>>1I5=85 - We will form a message
message_last=message_synchro_update="1=>2;5=85 40==KE 8=48:0B>@0: "+
symbols_names[s]+"("+IntegerToString(s+1)+"/"+IntegerToString(SYMBOLS)+") ... ";
//--- K2545< A>>1I5=85 - We will display the message
ShowCanvasMessage(message_synchro_update);
//--- 0?>;=8< 8=48:0B>@=K5 1CD5@K 7=0G5=8O<8
// Fill indicator buffers with values
for(int i=limit; i<rates_total; i++)
{
FillIndicatorBuffers(i,s,time);
//--- 064K5 2000 10@>2 ?@>25@O5< @07<5@K ?>4>:=0
// 8 5A;8 @07<5@ 87<5=8;AO ?>43>=8< ?>4 =53> @07<5@ :0=2K
// Every 2000 bars we check the dimensions of the subwindow
// and if the size has changed we will fit the size of the canvas
if(!(i%2000))
EventChartChange();
}
}
}
//--- #40;8< :0=2C
DeleteCanvas();
//--- #AB0=>28< C@>2=8 8=48:0B>@0
SetLevels();
//--- 1=C;8< ?5@5<5==K5
message_last="";
message_synchro_update="";
//--- 1=>28< 3@0D8:
ChartRedraw();
//--- 5@=Q< @07<5@ <0AA820 40==KE B5:CI53> A8<2>;0
return(rates_total);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- A;8 1K;0 703@C65=0 1>;55 3;C1>:0O 8AB>@8O
if(!CheckEventLoadHistory())
on_calc_prev_calculated=0;
//--- A;8 ?> :0:>9-B> ?@8G8=5 @0AGQBK =5 1K;8 7025@H5=K 8;8
// ?>4:0G0=0 1>;55 3;C1>:0O 8AB>@8O 8;8
// 1K;8 70?>;=5=K ?@>?CA:8 8AB>@88, B>
// =5 4>6840OAL B8:0 A45;05< 5IQ >4=C ?>?KB:C
if(on_calc_prev_calculated==0)
{
OnCalculate(on_calc_rates_total,on_calc_prev_calculated,
on_calc_time,on_calc_open,on_calc_high,on_calc_low,on_calc_close,
on_calc_tick_volume,on_calc_volume,on_calc_spread);
}
}
//+------------------------------------------------------------------+
//| @>25@O5B 2E>4=K5 ?0@0<5B@K =0 :>@@5:B=>ABL |
//+------------------------------------------------------------------+
bool CheckInputParameters()
{
if(IndicatorPeriod>500)
{
Comment("#<5=LH8B5 ?5@8>4 8=48:0B>@0! Indicator Period: ",IndicatorPeriod,"; Limit: 500;");
printf("#<5=LH8B5 ?5@8>4 8=48:0B>@0! Indicator Period: %d; Limit: %d;",IndicatorPeriod,500);
return(false);
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B A2>9AB20 8=48:0B>@0 |
//+------------------------------------------------------------------+
void SetPropertiesIndicator()
{
//--- #AB0=>28< :>@>B:>5 8<O
IndicatorSetString(INDICATOR_SHORTNAME,shortname_subwindow);
//--- #AB0=>28< :>;8G5AB2> 7=0:>2
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- ?@545;8< 1CD5@K 4;O >B@8A>2:8
for(int s=0; s<SYMBOLS; s++)
SetIndexBuffer(s,buffer_atr[s].data,INDICATOR_DATA);
//--- #AB0=>28< <5B:8 4;O B5:CI53> B09<D@59<0
for(int s=0; s<SYMBOLS; s++)
PlotIndexSetString(s,PLOT_LABEL,
"ATR ("+IntegerToString(s)+", "+symbols_names[s]+")");
//--- #AB0=>28< B8? ;8=89
for(int s=0; s<SYMBOLS; s++)
PlotIndexSetInteger(s,PLOT_DRAW_TYPE,DRAW_LINE);
//--- #AB0=>28< B>;I8=C ;8=89
for(int s=0; s<SYMBOLS; s++)
PlotIndexSetInteger(s,PLOT_LINE_WIDTH,1);
//--- #AB0=>28< F25B ;8=89
for(int s=0; s<SYMBOLS; s++)
PlotIndexSetInteger(s,PLOT_LINE_COLOR,line_color[s]);
//--- CAB>5 7=0G5=85 4;O ?>AB@>5=8O, 4;O :>B>@>3> =5B >B@8A>2:8
for(int s=0; s<SYMBOLS; s++)
PlotIndexSetDouble(s,PLOT_EMPTY_VALUE,EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| 5@20O 8=8F80;870F8O <0AA82>2 |
//+------------------------------------------------------------------+
void InitArrays()
{
ArrayInitialize(limit_time,NULL);
ArrayInitialize(series_first_date,NULL);
ArrayInitialize(series_first_date_last,NULL);
ArrayInitialize(handle_symbol,INVALID_HANDLE);
//---
for(int s=0; s<SYMBOLS; s++)
ArrayInitialize(buffer_atr[s].data,EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| =8F80;878@C5B <0AA82 A8<2>;>2 |
//+------------------------------------------------------------------+
void InitSymbolsNames()
{
symbols_names[0]=CheckGetSymbol(_Symbol);
symbols_names[1]=CheckGetSymbol(Symbol02);
symbols_names[2]=CheckGetSymbol(Symbol03);
symbols_names[3]=CheckGetSymbol(Symbol04);
symbols_names[4]=CheckGetSymbol(Symbol05);
symbols_names[5]=CheckGetSymbol(Symbol06);
}
//+------------------------------------------------------------------+
//| =8F80;878@C5B <0AA82 C@>2=59 |
//+------------------------------------------------------------------+
void InitLevels()
{
levels[0]=Level01;
levels[1]=Level02;
levels[2]=Level03;
levels[3]=Level04;
levels[4]=Level05;
levels[5]=Level06;
}
//+------------------------------------------------------------------+
//| 03@C605B 8 D>@<8@C5< =5>1E>48<>5/8<5NI55AO :>;-2> 40==KE |
//| It loads and we form the necessary / available amount of data |
//+------------------------------------------------------------------+
void LoadFormationData()
{
int number_bars=100; // >;8G5AB2> ?>43@C605<KE 10@>2
//---
for(int s=0; s<SYMBOLS; s++)
{
int count_try =0; // !GQBG8: ?>?KB>: :>?8@>20=8O 40==KE
int array_size =0; // 07<5@ <0AA820
datetime server_firstdate =NULL; // @5<O ?5@2>3> 10@0 =0 A5@25@5
datetime series_firstdate =NULL; // @5<O ?5@2>3> 10@0 2 1075 B5@<8=0;0
//--- >;CG8< ?5@2CN 40BC A8<2>;0-?5@8>40 2 1075 B5@<8=0;0
// Get the first date of the symbol-period in the terminal base
SeriesInfoInteger(symbols_names[s],Period(),SERIES_FIRSTDATE,series_firstdate);
//--- >;CG8< ?5@2CN 40BC A8<2>;0-?5@8>40 =0 A5@25@5
// Get the first date of the symbol-period on the server
SeriesInfoInteger(symbols_names[s],Period(),SERIES_SERVER_FIRSTDATE,server_firstdate);
//--- K2545< A>>1I5=85 - We will display the message
message_last=message_formation_data="@>F5AA 703@C7:8 8 D>@<8@>20=8O 40==KE: "+
symbols_names[s]+"("+IntegerToString(s+1)+"/"+IntegerToString(SYMBOLS)+") ... ";
ShowCanvasMessage(message_formation_data);
//--- 03@C78</AD>@<8@C5< 40==K5, 5A;8 @07<5@ <0AA820 <5=LH5, G5< <0:A8<0;L=>5 :>;8G5AB2> 10@>2 2 B5@<8=0;5,
// 0 B0:65 <564C ?5@2>9 40B>9 A5@88 2 B5@<8=0;5 8 ?5@2>9 40B>9 A5@88 =0 A5@25@5
// 1>;LH5 C:070==>3> :>;8G5AB20 10@>2
//--- Load / generate data if the size of the array is less than the maximum number of bars in the terminal,
// as well as between the first date of the series in the terminal and the first date of the series
// on the server more than the specified number of bars
while(array_size<on_calc_rates_total &&
series_firstdate-server_firstdate>PeriodSeconds()*number_bars)
{
datetime copied_time[];
//--- >;CG8< ?5@2CN 40BC A8<2>;0-?5@8>40 2 1075 B5@<8=0;0
// Get the first date of the symbol-period in the terminal base
SeriesInfoInteger(symbols_names[s],Period(),SERIES_FIRSTDATE,series_firstdate);
//--- 03@C78</A:>?8@C5< 5IQ C:070==>5 :>;8G5AB2> 10@>2
// Download / copy another specified number of bars
if(CopyTime(symbols_names[s],Period(),0,array_size+number_bars,copied_time))
{
//--- A;8 2@5<O ?5@2>3> 10@0 <0AA820 A 2KG5B>< :>;-20 ?>43@C605<KE 10@>2 @0=LH5,
// G5< 2@5<O ?5@2>3> 10@0 =0 3@0D8:5, >AB0=>28< F8:;
// If the time of the first bar of the array minus the number of loaded bars
// is earlier than the time of the first bar on the chart, we stop the cycle
if(copied_time[0]-PeriodSeconds()*number_bars<on_calc_time[0])
break;
//--- A;8 @07<5@ <0AA820 =5 C25;8G8;AO, C25;8G8< AGQBG8:
// If the size of the array has not increased, we will increase the counter
if(ArraySize(copied_time)==array_size)
count_try++;
//--- =0G5 ?>;CG8< B5:CI89 @07<5@ <0AA820
// Otherwise, we will get the current size of the array
else
array_size=ArraySize(copied_time);
//--- A;8 @07<5@ <0AA820 =5 C25;8G8205BAO 2 B5G5=88 100 ?>?KB>:, >AB0=>28< F8:;
// If the size of the array does not increase within 100 attempts, stop the loop
if(count_try==100)
{
count_try=0;
break;
}
}
//--- 064K5 2000 10@>2 ?@>25@O5< @07<5@K ?>4>:=0
// 8 5A;8 @07<5@ 87<5=8;AO ?>43>=8< ?>4 =53> @07<5@ :0=2K
// Every 2000 bars we check the dimensions of the subwindow
// and if the size has changed we will fit the size of the canvas
if(!(array_size%2000))
EventChartChange();
}
}
}
//+------------------------------------------------------------------+
//| >;CG05B EM=4;K |
//+------------------------------------------------------------------+
bool GetHandles()
{
//--- @87=0: B>3>, GB> 2A5 EM=4;K 20;84=K
bool invalid=true;
//--- @>94Q<AO 2 F8:;5 ?> 2A5< A8<2>;0< 8 ...
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 A8<2>; 5ABL 8 ...
if(symbols_names[s]!=empty_symbol)
{
// ...EM=4; B5:CI53> B09<D@59<0 =520;845=, ?>;CG8< 53>
if(handle_symbol[s]==INVALID_HANDLE)
{
handle_symbol[s]=iATR(symbols_names[s],Period(),IndicatorPeriod);
//--- A;8 =5 C40;>AL ?>;CG8BL EM=4;
if(handle_symbol[s]==INVALID_HANDLE)
invalid=false; // >?@>1C5< 2 A;54CNI89 @07
}
}
}
//--- K2545< A>>1I5=85, 5A;8 EM=4; 4;O >4=>3> 87 A8<2>;>2 =5 ?>;CG5=
// We will display the message if the handle for one of the symbols is not received
if(!invalid)
{
message_last=message_invalid_handle;
ShowCanvasMessage(message_invalid_handle);
}
//---
return(invalid);
}
//+------------------------------------------------------------------+
//| @>25@O5B :>;8G5AB2> 4>ABC?=KE 40==KE C 2A5E A8<2>;>2 |
//+------------------------------------------------------------------+
bool CheckAvailableData()
{
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 B0:>9 A8<2>; 5ABL
if(symbols_names[s]!=empty_symbol)
{
double data[]; // 0AA82 4;O ?@>25@:8 :>;8G5AB20 40==KE 8=48:0B>@0
datetime time[]; // 0AA82 4;O ?@>25@:8 :>;8G5AB20 10@>2
int calculated_values =0; // >;8G5AB2> 40==KE 8=48:0B>@0
int total_period_bars =0; // >;8G5AB2> 10@>2 B5:CI53> ?5@8>40
datetime terminal_first_date =NULL; // 5@20O 40B0 8<5NI8EAO 40==KE B5:CI53> ?5@8>40 2 B5@<8=0;5
//--- >;CG8< :>;-2> @0AAG8B0==KE 7=0G5=89 8=48:0B>@0
// Get the number of calculated indicator values
calculated_values=BarsCalculated(handle_symbol[s]);
//--- >;CG8< ?5@2CN 40BC 40==KE B5:CI53> ?5@8>40 2 B5@<8=0;5
// Get the first date of the current period data in the terminal
terminal_first_date=(datetime)SeriesInfoInteger(symbols_names[s],Period(),SERIES_TERMINAL_FIRSTDATE);
//--- >;CG8< :>;8G5AB2> 4>ABC?=KE 10@>2 >B C:070==>9 40BK
// Get the number of available bars from the specified date.
total_period_bars=Bars(symbols_names[s],Period(),terminal_first_date,TimeCurrent());
//--- @>25@8< 3>B>2=>ABL 40==KE 10@>2
for(int i=0; i<5; i++)
{
//--- !:>?8@C5< C:070==>5 :>;8G5AB2> 40==KE
// Copy the specified amount of time data (all between terminal_first_date and TimeCurrent())
if(CopyTime(symbols_names[s],Period(),0,total_period_bars,time))
{
//--- A;8 A:>?8@>20;>AL =C6=>5 :>;8G5AB2>, >AB0=>28< F8:;
// If the required amount has been copied, stop the cycle
if(ArraySize(time)>=total_period_bars)
break;
}
}
//--- @>25@8< 3>B>2=>ABL 40==KE 8=48:0B>@0
for(int i=0; i<5; i++)
{
//--- !:>?8@C5< C:070==>5 :>;8G5AB2> 40==KE
// Copy the specified amount of time data (all calculated for the indicator)
if(CopyBuffer(handle_symbol[s],0,0,calculated_values,data))
{
//--- A;8 A:>?8@>20;>AL =C6=>5 :>;8G5AB2>, >AB0=>28< F8:;
// If the required amount has been copied, stop the cycle
if(ArraySize(data)>=calculated_values)
break;
}
}
//--- A;8 A:>?8@>20=> <5=LH5 40==KE
// 7=0G8B =C6=> A>25@H8BL 5IQ >4=C ?>?KB:C
if(ArraySize(time)<total_period_bars || ArraySize(data)<calculated_values)
{
message_last=message_data_available;
ShowCanvasMessage(message_data_available);
on_calc_prev_calculated=0;
return(false);
}
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| @>25@:0 A>1KB8O 703@C7:8 1>;55 3;C1>:>9 8AB>@88 |
//| Check the event of loading a deeper history if there is a symbol |
//| such that |
//+------------------------------------------------------------------+
bool CheckEventLoadHistory()
{
bool load=false;
//---
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 B0:>9 A8<2>; 5ABL
if(symbols_names[s]!=empty_symbol)
{
//--- A;8 =C6=> >1=>28BL A5@88
if(on_calc_prev_calculated==0)
{
//--- >;CG8< ?5@2CN 40BC A8<2>;0-?5@8>40
// Get the first date of the period symbol
series_first_date[s]=(datetime)SeriesInfoInteger(symbols_names[s],Period(),SERIES_FIRSTDATE);
//--- A;8 745AL 2 ?5@2K9 @07 (>BACBAB2C5B 7=0G5=85), B>
if(series_first_date_last[s]==NULL)
//--- 0?><=8< ?5@2CN 40BC A8<2>;0-?5@8>40 4;O ?>A;54CNI8E A@02=5=89 A F5;LN >?@545;5=8O 703@C7:8
// 1>;55 3;C1>:>9 8AB>@88
// Remember the first date of the symbol-period for subsequent comparisons to determine the load
// of a deeper history.
series_first_date_last[s]=series_first_date[s];
}
else
{
//--- >;CG8< ?5@2CN 40BC A8<2>;0-?5@8>40
// Get the first date of the period symbol
series_first_date[s]=(datetime)SeriesInfoInteger(symbols_names[s],Period(),SERIES_FIRSTDATE);
//--- A;8 40BK >B;8G0NBAO, B> 5ABL 40B0 2 ?0<OB8 1>;55 ?>74=OO, G5< B0, :>B>@CN ?>;CG8;8 A59G0A, B>
// 7=0G8B 1K;0 703@C7:0 1>;55 3;C1>:>9 8AB>@88
// If the dates are different, then there is a date in memory later than the one that we received
// now, then it means that there was a deeper loading
if(series_first_date_last[s]>series_first_date[s])
{
//--- K2545< A>>1I5=85 2 6C@=0;
Print("(",symbols_names[s],",",TimeframeToString(Period()),
") > K;0 703@C65=0/AD>@<8@>20=0 1>;55 3;C1>:0O 8AB>@8O: ",
series_first_date_last[s]," > ",series_first_date[s]);
//--- 0?><=8< 40BC
series_first_date_last[s]=series_first_date[s];
load=true;
}
}
}
}
//--- A;8 1K;0 703@C65=0/AD>@<8@>20=0 1>;55 3;C1>:0O 8AB>@8O, B>
// >B?@028< :><0=4C =0 >1=>2;5=85 3@0D8G5A:8E A5@89 8=48:0B>@0
//--- If a deeper history has been loaded / formed, then
// send a command to update the graphic series of the indicator
if(load)
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| @>25@O5B A8=E@>=878@>20==>ABL ?> A8<2>;C/?5@8>4C |
//+------------------------------------------------------------------+
bool CheckSymbolIsSynchronized()
{
//--- A;8 5ABL A>548=5=85 A A5@25@><, B> ?@>25@8< A8=E@>=878@>20==>ABL 40==KE
// If there is a connection to the server, then we will check the data synchronization.
if(TerminalInfoInteger(TERMINAL_CONNECTED))
{
for(int s=0; s<SYMBOLS; s++)
{
//--- A;8 A8<2>; 5ABL
if(symbols_names[s]!=empty_symbol)
{
//--- A;8 40==K5 =5 A8=E@>=878@>20=K, B> A>>1I8< >1 MB>< 8 ?>?@>1C5< A=>20
// If the data is not synchronized, then let us know and try again.
if(!SeriesInfoInteger(symbols_names[s],Period(),SERIES_SYNCHRONIZED))
{
message_last=message_is_synchronized;
ShowCanvasMessage(message_is_synchronized);
return(false);
}
}
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| ?@545;5=85 2@5<5=8 ?5@2>3> 8AB8==>3> 10@0 4;O >B@8A>2:8 |
//+------------------------------------------------------------------+
bool DetermineBeginForCalculate()
{
for(int s=0; s<SYMBOLS; s++)
{
datetime time[]; // 0AA82 2@5<5=8 10@>2
int total_period_bars=0; // >;8G5AB2> 10@>2
//--- A;8 B0:>3> A8<2>;0 =5B, ?5@59B8 : A;54CNI5<C
if(symbols_names[s]==empty_symbol)
continue;
//--- >;CG8< >1I55 :>;8G5AB2> 10@>2 A8<2>;0
// Get the total number of bars of the symbol
total_period_bars=Bars(symbols_names[s],Period());
//--- !:>?8@C5< <0AA82 2@5<5=8 10@>2. A;8 =5 ?>;CG8;>AL, ?>?@>1C5< 5IQ @07
// Copy the array of time bars. If not, try again.
if(CopyTime(symbols_names[s],Period(),0,total_period_bars,time)<total_period_bars)
return(false);
//--- >;CG8< 2@5<O ?5@2>3> 8AB8==>3> 10@0, :>B>@K9 A>>B25BAB2C5B B5:CI5<C B09<D@59<C
// Get the time of the first true bar that corresponds to the current timeframe
limit_time[s]=GetFirstTruePeriodBarTime(time);
//--- #AB0=>28< 25@B8:0;L=CN ;8=8N =0 8AB8==>< 10@5
CreateVerticalLines(0,0,limit_time[s],prefix+symbols_names[s]+": begin time series",
2,STYLE_SOLID,line_color[s],false,TimeToString(limit_time[s]),"\n");
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| >72@0I05B 2@5<O ?5@2>3> 8AB8==>3> 10@0 B5:CI53> ?5@8>40 |
//| Returns the time of the first true bar of the current period |
//+------------------------------------------------------------------+
datetime GetFirstTruePeriodBarTime(datetime &time[])
{
datetime true_period =NULL; // @5<O ?5@2>3> 8AB8==>3> 10@0 - Time of the first true bar
int array_size =0; // 07<5@ <0AA820
//--- >;CG8< @07<5@ <0AA820 - We will have got the size of the array
array_size=ArraySize(time);
ArraySetAsSeries(time,false);
//--- >>G5@Q4=> ?@>25@O5< :064K9 10@
for(int i=1; i<array_size; i++)
{
//--- A;8 10@ A>>B25BAB2C5B B5:CI5<C B09<D@59<C
if(time[i]-time[i-1]==PeriodSeconds())
{
//--- 0?><=8< 8 >AB0=>28< F8:;
true_period=time[i-1];
break;
}
}
//--- 5@=Q< 2@5<O ?5@2>3> 8AB8==>3> 10@0
return(true_period);
}
//+------------------------------------------------------------------+
//| >43>B>2:0 40==KE ?5@54 @8A>20=85< |
//+------------------------------------------------------------------+
void PreparationData(int i,int symbol_number,datetime const &time[])
{
int try
=100; // >;8G5AB2> ?>?KB>: :>?8@>20=8O
//--- @5<O 10@0 C:070==>3> A8<2>;0 8 BD
datetime symbol_time[];
//--- 0AA82 4;O :>?8@>20=8O 7=0G5=8O 8=48:0B>@0
double atr_value[];
//--- A;8 2 7>=5 10@>2 B5:CI53> B09<D@59<0
if(time[i]>=limit_time[symbol_number])
{
//--- !:>?8@C5< 2@5<O
for(int k=0; k<try
; k++)
{
if(CopyTime(symbols_names[symbol_number],0,time[i],1,symbol_time)==1)
{
temp_symbol_time[symbol_number].time[i]=symbol_time[0];
break;
}
}
//--- !:>?8@C5< 7=0G5=85 8=48:0B>@0
for(int k=0; k<try
; k++)
{
if(CopyBuffer(handle_symbol[symbol_number],0,time[i],1,atr_value)==1)
{
temp_atr_values[symbol_number].value[i]=atr_value[0];
break;
}
}
}
//--- A;8 2=5 7>=K 10@>2 B5:CI53> B09<D@59<0,
// CAB0=>28< ?CAB>5 7=0G5=85
else
temp_atr_values[symbol_number].value[i]=EMPTY_VALUE;
}
//+------------------------------------------------------------------+
//| 0?>;=O5B 8=48:0B>@=K5 1CD5@K |
//+------------------------------------------------------------------+
void FillIndicatorBuffers(int i,int symbol_number,datetime const &time[])
{
//--- ;O ?@>25@:8 ?>;CG5==>3> 7=0G5=8O 8=48:0B>@0
bool check_value=false;
//--- !GQBG8: 10@>2 B5:CI53> B09<D@59<0
static int count_current_period=0;
//--- 1=C;8< AGQBG8: 10@>2 B5:CI53> B09<D@59<0
// 2 =0G0;5 B09<A5@88 A8<2>;0
if(i==0)
count_current_period=0;
//--- A;8 2 7>=5 10@>2 B5:CI53> B09<D@59<0 8
// AGQBG8: <5=LH5 C:070==>3> ?5@8>40 8=48:0B>@0, B>
// C25;8G8< AGQBG8:
if(count_current_period<IndicatorPeriod &&
time[i]>=limit_time[symbol_number])
count_current_period++;
//--- A;8 2 7>=5 8=48:0B>@0 8
// 2@5<O B5:CI53> A8<2>;0 8 2@5<O C:070==>3> A8<2>;0 A>2?040NB
if(count_current_period>=IndicatorPeriod &&
time[i]==temp_symbol_time[symbol_number].time[i])
{
//--- A;8 ?>;CG5==>5 7=0G5=85 =5 ?CAB>5
// If the received value is not empty
if(temp_atr_values[symbol_number].value[i]!=EMPTY_VALUE)
{
check_value=true;
buffer_atr[symbol_number].data[i]=temp_atr_values[symbol_number].value[i];
}
}
//--- #AB0=>28< ?CAB>5 7=0G5=85, 5A;8 =5 ?>;CG8;>AL CAB0=>28BL 2KH5
if(!check_value)
buffer_atr[symbol_number].data[i]=EMPTY_VALUE;
}
//+------------------------------------------------------------------+
//| >102;O5B C:070==K9 A8<2>; 2 >:=> >17>@ @K=:0 |
//+------------------------------------------------------------------+
string CheckGetSymbol(string symbol)
{
int symbol_total =0; // >;8G5AB2> A8<2>;>2
string nm_symbol =""; // <O A8<2>;0
//--- A;8 ?5@540;8 ?CABCN AB@>:C, B> 25@=CBL ?CABCN AB@>:C
if(symbol=="")
return(empty_symbol);
//--- A53> A8<2>;>2 =0 A5@25@5
symbol_total=SymbolsTotal(false);
//--- @>9B8AL ?> 2A5<C A?8A:C A8<2>;>2
for(int s=symbol_total-1; s>=0; s--)
{
//--- <O A8<2>;0 =0 A5@25@5
nm_symbol=SymbolName(s,false);
//--- A;8 5ABL B0:>9 A8<2>;, B>
if(nm_symbol==symbol)
{
//--- CAB0=>28< 53> 2 >:=> 17>@ K=:0 8
SymbolSelect(nm_symbol,true);
//--- 25@=Q< 53> 8<O
return(symbol);
}
}
//--- A;8 B0:>3> A8<2>;0 =5B, B>
// 25@=Q< AB@>:C A8<2>;878@CNICN >BACBAB285 A8<2>;0
return(empty_symbol);
}
//+------------------------------------------------------------------+
//| #AB0=>28< A2>9AB20 ?>4>:=0 |
//+------------------------------------------------------------------+
void SetSubwindowProperties()
{
//--- >;CG8< =><5@ ?>4>:=0 8=48:0B>@0
number_subwindow=ChartWindowFind(0,shortname_subwindow);
//--- >;CG8< H8@8=C 8 2KA>BC ?>4>:=0
chart_width=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
subwindow_height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,number_subwindow);
//--- >;CG8< F5=B@ ?>4>:=0
subwindow_center=chart_width/2;
subwindow_vcenter=subwindow_height/2;
}
//+------------------------------------------------------------------+
//| >?8@C5B 40==K5 87 OnCalculate |
//+------------------------------------------------------------------+
void CopyDataOnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
on_calc_rates_total=rates_total;
on_calc_prev_calculated=prev_calculated;
ArrayCopy(on_calc_time,time);
ArrayCopy(on_calc_open,open);
ArrayCopy(on_calc_high,high);
ArrayCopy(on_calc_low,low);
ArrayCopy(on_calc_close,close);
ArrayCopy(on_calc_tick_volume,tick_volume);
ArrayCopy(on_calc_volume,volume);
ArrayCopy(on_calc_spread,spread);
}
//+------------------------------------------------------------------+
//| 7<5=O5B @07<5@ <0AA82>2 ?>4 @07<5@ >A=>2=>3> <0AA820 |
//+------------------------------------------------------------------+
void ResizeCalculateArrays()
{
for(int s=0; s<SYMBOLS; s++)
{
ArrayResize(temp_symbol_time[s].time,on_calc_rates_total);
ArrayResize(temp_atr_values[s].value,on_calc_rates_total);
}
}
//+------------------------------------------------------------------+
//| 1=C;5=85 <0AA82>2 4;O ?>43>B>2:8 40==KE |
//+------------------------------------------------------------------+
void ZeroCalculateArrays()
{
for(int s=0; s<SYMBOLS; s++)
{
ArrayInitialize(temp_symbol_time[s].time,NULL);
ArrayInitialize(temp_atr_values[s].value,EMPTY_VALUE);
}
}
//+------------------------------------------------------------------+
//| 1=C;5=85 8=48:0B>@=KE 1CD5@>2 |
//+------------------------------------------------------------------+
void ZeroIndicatorBuffers()
{
for(int s=0; s<SYMBOLS; s++)
ArrayInitialize(buffer_atr[s].data,EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| !;548B 70 @07<5@0<8 :0=2K |
//+------------------------------------------------------------------+
void EventChartChange()
{
//--- >;CG8< A2>9AB20 ?>4>:=0
SetSubwindowProperties();
//--- A;8 @07<5@K ?>4>:=0 =5 87<5=8;8AL, 2K945<
if(!CheckSubwindowSize())
return;
//--- A;8 @07<5@ ?>4>:=0 <5=LH5 >4=>3> ?8:A5;O 8;8
// F5=B@ @0AAG8B0= =5:>@@5:B=>, 2K945<
if(subwindow_height<1 || subwindow_vcenter<1)
return;
//--- #AB0=>28< =>2K9 @07<5@ :0=25
ResizeCanvas();
//--- >:065< ?>A;54=55 A>>1I5=85
ShowCanvasMessage(message_last);
}
//+------------------------------------------------------------------+
//| @>25@8< @07<5@K ?>4>:=0 |
//+------------------------------------------------------------------+
bool CheckSubwindowSize()
{
//--- A;8 @07<5@K ?>4>:=0 =5 87<5=8;8AL, 2K945<
if(last_chart_width==chart_width &&
last_subwindow_height==subwindow_height)
return(false);
//--- A;8 65 87<5=8;8AL, B> 70?><=8< 8E
else
{
last_chart_width=chart_width;
last_subwindow_height=subwindow_height;
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| #AB0=>28BL :0=2C |
//+------------------------------------------------------------------+
void SetCanvas()
{
//--- A;8 :0=2K =5B, CAB0=>28< 5Q
if(ObjectFind(0,canvas_name)<0)
{
//--- !>74048< :0=2C
canvas.CreateBitmapLabel(0,number_subwindow,canvas_name,0,0,chart_width,subwindow_height,clr_format);
//--- !45;05< :0=2C ?>;=>ABLN ?@>7@0G=>9
canvas.Erase(ColorToARGB(canvas_bg_color,0));
//--- 1=>28< :0=2C
canvas.Update();
}
}
//+------------------------------------------------------------------+
//| 7<5=O5B @07<5@ :0=2K |
//+------------------------------------------------------------------+
void ResizeCanvas()
{
//--- A;8 :0=20 5ABL 2 ?>4>:=5 8=48:0B>@0, CAB0=>28< =>2K9 @07<5@
if(ObjectFind(0,canvas_name)==number_subwindow)
canvas.Resize(chart_width,subwindow_height);
}
//+------------------------------------------------------------------+
//| K2>48B A>>1I5=85 2 :0=25 |
//+------------------------------------------------------------------+
void ShowCanvasMessage(string message_text)
{
SetSubwindowProperties();
//--- A;8 :0=20 5ABL 2 ?>4>:=5 8=48:0B>@0
if(ObjectFind(0,canvas_name)==number_subwindow)
{
//--- B>1@078< A>>1I5=85,
// 5A;8 ?5@540=0 =5 ?CAB0O AB@>:0 8 :>>@48=0BK ?>;CG5=K
if(message_text!="" && subwindow_center>0 && subwindow_vcenter>0)
{
canvas.Erase(ColorToARGB(canvas_bg_color,canvas_opacity));
canvas.TextOut(subwindow_center,subwindow_vcenter,message_text,ColorToARGB(clrRed),TA_CENTER|TA_VCENTER);
canvas.Update();
}
}
}
//+------------------------------------------------------------------+
//| #40;O5B :0=2C |
//+------------------------------------------------------------------+
void DeleteCanvas()
{
//--- #40;8< :0=2C, 5A;8 >=0 5ABL
if(ObjectFind(0,canvas_name)>0)
{
//--- 5@54 C40;5=85< ?@>87254Q< MDD5:B 8AG570=8O
for(int i=canvas_opacity; i>0; i-=5)
{
canvas.Erase(ColorToARGB(canvas_bg_color,(uchar)i));
canvas.Update();
}
//--- #40;5=85 :0=2K
canvas.Destroy();
}
}
//+------------------------------------------------------------------+
//| @>F5=B ?@>3@5AA0 |
//+------------------------------------------------------------------+
void PercentProgress(int i,int symbols_number,double &percent)
{
string message_text="";
percent=(double(i)/on_calc_rates_total)*100;
//---
if(percent<=9.99)
message_text="0"+DoubleToString(percent,0);
else
if(percent<99)
message_text=DoubleToString(percent,0);
else
message_text="99";
//---
message_last=message_synchro_update=">43>B>2:0 40==KE ("+IntegerToString(on_calc_rates_total)+" 10@>2) : "+
symbols_names[symbols_number]+
"("+IntegerToString(symbols_number+1)+"/"+IntegerToString(SYMBOLS)+") - "+message_text+"% ... ";
}
//+------------------------------------------------------------------+
//| #AB0=>2:0 C@>2=59 |
//+------------------------------------------------------------------+
void SetLevels()
{
//--- >;CG8< =><5@ ?>4>:=0 8=48:0B>@0
number_subwindow=ChartWindowFind(0,shortname_subwindow);
//--- #AB0=>28< C@>2=8
for(int s=0; s<LEVELS; s++)
CreateHorizontalLines(0,number_subwindow,
prefix+"level_0"+IntegerToString(s+1)+"",
CorrectValueBySymbolDigits(levels[s]*_Point),
1,STYLE_DOT,clrLightSteelBlue,false,false,false,"\n");
}
//+------------------------------------------------------------------+
//| #40;O5B C@>2=8 |
//+------------------------------------------------------------------+
void DeleteLevels()
{
for(int i=0; i<LEVELS; i++)
DeleteObjectByName(prefix+"level_0"+IntegerToString(i+1)+"");
}
//+------------------------------------------------------------------+
//| #40;O5B 25@B8:0;L=K5 ;8=88 =0G0;0 A5@89 |
//+------------------------------------------------------------------+
void DeleteVerticalLines()
{
for(int s=0; s<SYMBOLS; s++)
DeleteObjectByName(prefix+symbols_names[s]+": begin time series");
}
//+------------------------------------------------------------------+
//| #40;O5B >1J5:B ?> 8<5=8 |
//+------------------------------------------------------------------+
void DeleteObjectByName(string Name)
{
//--- A;8 5ABL B0:>9 >1J5:B
if(ObjectFind(0,Name)>=0)
{
//--- A;8 1K;0 >H81:0 ?@8 C40;5=88, A>>1I8< >1 MB><
if(!ObjectDelete(0,Name))
Print("H81:0 ("+IntegerToString(GetLastError())+") ?@8 C40;5=88 >1J5:B0!");
}
}
//+------------------------------------------------------------------+
//| !>740=85 3>@87>=B0;L=>9 ;8=88 |
//+------------------------------------------------------------------+
void CreateHorizontalLines(long chart_id, // id 3@0D8:0
int number_window, // =><5@ >:=0
string name_line, // 8<O >1J5:B0
double price, // C@>25=L F5=K
int width_line, // B>;I8=0 ;8=88
ENUM_LINE_STYLE style_line, // AB8;L ;8=88
color color_line, // F25B ;8=88
bool selectable, // =5;L7O 2K45;8BL >1J5:B, 5A;8 FALSE
bool select, // 2K45;5=85
bool back, // D>=>2>5 @0A?>;>65=85
string tooltip) // =5B 2A?;K20NI59 ?>4A:07:8, 5A;8 "\n"
{
//--- A;8 >1J5:B CA?5H=> A>740=...
if(ObjectCreate(chart_id,name_line,OBJ_HLINE,number_window,0,price))
{
// ...CAB0=>28< 5<C A2>9AB20
ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTABLE,selectable);
ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTED,select);
ObjectSetInteger(chart_id,name_line,OBJPROP_BACK,back);
ObjectSetInteger(chart_id,name_line,OBJPROP_STYLE,style_line);
ObjectSetInteger(chart_id,name_line,OBJPROP_WIDTH,width_line);
ObjectSetInteger(chart_id,name_line,OBJPROP_COLOR,color_line);
ObjectSetString(chart_id,name_line,OBJPROP_TOOLTIP,tooltip);
}
}
//+------------------------------------------------------------------+
//| !>740=85 25@B8:0;L=>9 ;8=88 |
//+------------------------------------------------------------------+
void CreateVerticalLines(long chart_id, // id 3@0D8:0
int number_window, // =><5@ >:=0
datetime time, // 2@5<O
string name_line, // 8<O >1J5:B0
int width_line, // B>;I8=0 ;8=88
ENUM_LINE_STYLE style_line, // AB8;L ;8=88
color color_line, // F25B ;8=88
bool selectable, // =5;L7O 2K45;8BL >1J5:B, 5A;8 FALSE
string description_text, // B5:AB >?8A0=8O
string tooltip) // =5B 2A?;K20NI59 ?>4A:07:8, 5A;8 "\n"
{
//--- A;8 >1J5:B CA?5H=> A>740=...
if(ObjectCreate(chart_id,name_line,OBJ_VLINE,number_window,time,0))
{
// ...CAB0=>28< 5<C A2>9AB20
ObjectSetInteger(chart_id,name_line,OBJPROP_TIME,time);
ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTABLE,selectable);
ObjectSetInteger(chart_id,name_line,OBJPROP_STYLE,style_line);
ObjectSetInteger(chart_id,name_line,OBJPROP_WIDTH,width_line);
ObjectSetInteger(chart_id,name_line,OBJPROP_COLOR,color_line);
ObjectSetString(chart_id,name_line,OBJPROP_TEXT,description_text);
ObjectSetString(chart_id,name_line,OBJPROP_TOOLTIP,tooltip);
}
}
//+------------------------------------------------------------------+
//| >@@5:F8O 7=0G5=8O ?> :>;8G5AB2C 7=0:>2 2 F5=5 (double) |
//+------------------------------------------------------------------+
double CorrectValueBySymbolDigits(double value)
{
return(_Digits==3 || _Digits==5) ? value*=10 : value;
}
//+------------------------------------------------------------------+
//| @5>1@07C5B B09<D@59< 2 AB@>:C |
//+------------------------------------------------------------------+
string TimeframeToString(ENUM_TIMEFRAMES timeframe)
{
string str="";
//--- A;8 ?5@540==>5 7=0G5=85 =5:>@@5:B=>, 15@5< B09<D@59< B5:CI53> 3@0D8:0
if(timeframe==WRONG_VALUE || timeframe== NULL)
timeframe= Period();
switch(timeframe)
{
case PERIOD_M1 :
str="M1";
break;
case PERIOD_M2 :
str="M2";
break;
case PERIOD_M3 :
str="M3";
break;
case PERIOD_M4 :
str="M4";
break;
case PERIOD_M5 :
str="M5";
break;
case PERIOD_M6 :
str="M6";
break;
case PERIOD_M10 :
str="M10";
break;
case PERIOD_M12 :
str="M12";
break;
case PERIOD_M15 :
str="M15";
break;
case PERIOD_M20 :
str="M20";
break;
case PERIOD_M30 :
str="M30";
break;
case PERIOD_H1 :
str="H1";
break;
case PERIOD_H2 :
str="H2";
break;
case PERIOD_H3 :
str="H3";
break;
case PERIOD_H4 :
str="H4";
break;
case PERIOD_H6 :
str="H6";
break;
case PERIOD_H8 :
str="H8";
break;
case PERIOD_H12 :
str="H12";
break;
case PERIOD_D1 :
str="D1";
break;
case PERIOD_W1 :
str="W1";
break;
case PERIOD_MN1 :
str="MN1";
break;
}
//---
return(str);
}
//+------------------------------------------------------------------+