Группа "Стол заказов MQL"

Рейтинг 2156



РЕКОМЕНДУЮ



Добавить сигнал к индикатору

Не могли бы вы добавить сигнал к индикатору?

Оповещение о максимальных значениях на предыдущих 1 или 2 барах
В начале бара первая половина / быки должны иметь максимальные значения внизу, а медведи — максимальные значения вверху /
Сигналы на покупку для быков и на продажу для медведей.

Orderflow теория.

добро пожаловать поручителем!

//+------------------------------------------------------------------+
//|                                                clusterbox_ad.mq4 |
//|                                        Copyright 2015, Scriptong |
//|                                          http://advancetools.net |
//+------------------------------------------------------------------+
#property copyright "Scriptong"
#property link      "http://advancetools.net"
#property description "English: Displays the ticks volume of candles in the form of clusters.\nRussian: Отображение тиковых объемов свечи в виде кластеров."
#property strict

#property indicator_chart_window
#property indicator_buffers 1

#define MAX_POINTS_IN_CANDLE 30000                                                                 // Increase for points of the monthly chart of five-digit
#define MAX_TICKS_IN_CANDLE 1000000                                                                // Increase for the ticks of the monthly chart of five-digit
#define MAX_VOLUMES_SHOW      5                                                                    // The number of maximum volume levels that should be displayed
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct LevelVolumeColor                                                                            // Structure of correspondence of volume levels, the achievement of which is displayed at the price level  
 
{                                                                                                 // with the appropriate color
   color             levelColor
;
   
int               levelMinVolume;
 
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct TickStruct                                                                                  // Structure for writing data about one tick
 
{
   datetime          time
;
   
double            bid;
   
double            ask;
 
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_YESNO
 
{
   YES
,                                                                                           // Yes / Да
   NO                                                                                            
// No / Нет
 
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_CHARTSCALE
 
{
   SCALE_SMALLER
,                                                                                  // Smallest / Наименьший
   SCALE_SMALL
,                                                                                    // Small / Малый
   SCALE_MEDIUM
,                                                                                   // Medium / Средний
   SCALE_BIG
,                                                                                      // Big / Большой
   SCALE_BIGGEST
,                                                                                  // Greater / Больший
   SCALE_LARGE                                                                                    
// Biggest / Наибольший
 
};

//--- Настроечные параметры индикатора / Setting parameters of the indicator
input
int      i_pointsInBox           = 50;                                                       // Points in one cluster / Количество пунктов в одном кластере
input
string   i_string1               = "Min volumes and colors / Мин. объемы и цвета";           // ==============================================
input
int      i_minVolumeLevel1       = 1;                                                        // Minimal volume. Level 1 / Минимальный объем. Уровень 1
input color    i_colorLevel1          
= clrSkyBlue;                                               // Color of level 1 / Цвет уровня 1
input
int      i_minVolumeLevel2       = 250;                                                      // Minimal volume. Level 2 / Минимальный объем. Уровень 2
input color    i_colorLevel2          
= clrTurquoise;                                             // Color of level 2 / Цвет уровня 2
input
int      i_minVolumeLevel3       = 500;                                                      // Minimal volume. Level 3 / Минимальный объем. Уровень 3
input color    i_colorLevel3          
= clrRoyalBlue;                                             // Color of level 3 / Цвет уровня 3
input
int      i_minVolumeLevel4       = 1000;                                                     // Minimal volume. Level 4 / Минимальный объем. Уровень 4
input color    i_colorLevel4          
= clrBlue;                                                  // Color of level 4 / Цвет уровня 4
input
int      i_minVolumeLevel5       = 2000;                                                     // Minimal volume. Level 5 / Минимальный объем. Уровень 5
input color    i_colorLevel5          
= clrMagenta;                                               // Color of level 5 / Цвет уровня 5
input
string   i_string2               = "Параметры графика";                                      // ==============================================
input ENUM_YESNO i_useNeededScale      
= YES;                                                      // Use the specific chart scale? / Задать масштаб графика?
input ENUM_CHARTSCALE i_chartScale    
= SCALE_LARGE;                                              // Chart scale / Масштаб
input ENUM_YESNO i_showClusterGrid    
= YES;                                                      // Display the cluster grid / Показывать сетку кластеров
input color    i_gridColor            
= clrDarkGray;                                              // Color of clusters lines / Цвет линий кластеров

input
int      i_indBarsCount=10000;                                                    // Number of bars to display / Кол-во баров отображения

//--- Прочие глобальные переменные индикатора/Other global indicator variables
bool g_activate,                                                                              // Sign of successful indicator initialization
g_isShowInfo
,                                                                                 // Sign of the need to display indicator data
g_chartForeground
,                                                                            // Indicator of the presence of candles in the foreground
g_init
;                                                                                       // A variable for initializing static variables inside functions at the time of execution ..
                                                                                             
// ..reinitialize
int g_currentScale,// Chart scale effective at the moment of attaching the indicator
g_volumePriceArray
[MAX_POINTS_IN_CANDLE];                                                      // A working array of levels, which records the number of ticks that hit
                                                                                               
// the corresponding candle price. Number of filled array elements - candle height
double g_ticksPrice[MAX_TICKS_IN_CANDLE];                                                      // Array for temporary storage of a set of ticks per one candlestick

double g_point,
g_tickSize
;

TickStruct        g_ticks[];                                                                       // Array for storing ticks received after the indicator started working                  
LevelVolumeColor g_volumeLevelsColor[MAX_VOLUMES_SHOW];                                            // Array of volumes and corresponding level colors

#define PREFIX                                  "CLSTRBX_"                                         // Prefix of graphical objects displayed by the indicator

#define SIGN_BUTTON                             "INFO_BUTTON_"                                     // Root of the name of the "button" graphic object
#define BUTTON_FONT_NAME                        "MS Sans Serif"                                    // Font name for displaying button text
#define BUTTON_TOOLTIP                          "Toggle on / off the display of clusters and grid"           // Hint for the purpose of the button
#define BUTTON_XCOORD                           2                                                  // X-coordinate of the upper left corner of the button
#define BUTTON_YCOORD                           14                                                 // Y-coordinate of the upper left corner of the button
#define BUTTON_WIDTH                            110                                                // Button width
#define BUTTON_HEIGHT                           20                                                 // Button height
#define BUTTON_FONT_SIZE                        7                                                  // Font size for button text
#define BUTTON_TEXT_COLOR                       clrBlack                                           // The font color of the text in the button
#define BUTTON_BORDER_COLOR                     clrNONE                                            // Button border color
#define BUTTON_BACKGROUND_COLOR                 clrLightGray                                       // Button fill color

#define FONT_NAME                               "MS Sans Serif"
#define FONT_SIZE                               7
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
 
{
   g_activate
=false;                                                                             // Indicator is not initialized
   g_init
=true;

   
if(!IsTuningParametersCorrect()) // Incorrectly specified values ​​of tuning parameters - the reason for unsuccessful initialization
     
return INIT_FAILED;

   
if(!IsLoadTempTicks()) // Load data about ticks saved for the previous period of the indicator operation  
     
return INIT_FAILED;

   
CreateVolumeColorsArray();                                                                    // Copy data about color and level values ​​into an array
   
SetChartView();                                                                               // Setting a specific type of chart

   g_activate
=true;                                                                              // The indicator has been successfully initialized
   
return INIT_SUCCEEDED;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the correctness of the tuning parameters / Проверка корректности настроечных параметров                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTuningParametersCorrect()
 
{
   
string name=WindowExpertName();

   
int period= Period();
   
if(period == 0)
     
{
     
Alert(name,": fatal terminal error - period 0 minutes. The indicator is off / фатальная ошибка терминала - период 0 минут. Индикатор отключен.");
     
return (false);
     
}

   g_point
=Point;
   
if(g_point==0)
     
{
     
Alert(name,": fatal terminal error - the point value is zero. The indicator is off / фатальная ошибка терминала - величина пункта равна нулю. Индикатор отключен.");
     
return (false);
     
}

   g_tickSize
=MarketInfo(Symbol(),MODE_TICKSIZE);
   
if(g_tickSize==0)
     
{
     
Alert(name,": fatal terminal error - the point value is zero. The indicator is off / фатальная ошибка терминала - величина шага одного тика равна нулю. Индикатор отключен.");
     
return (false);
     
}

   
if(i_pointsInBox<1)
     
{
     
Alert(name,": the number of points in the cluster must be positive. The indicator is off / количество пунктов в кластере должно быть положительным. Индикатор отключен.");
     
return (false);
     
}

   
return (true);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Reading data about ticks accumulated during the previous working session of the program / Чтение данных о тиках, накопленных в течение предыдущей рабочей сессии программы                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsLoadTempTicks()
 
{
//--- Open the tick history file
   
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
   
if(hTicksFile<1)
     
return true;

//--- Memory allocation for the g_ticks array
   
int recSize=(int)(FileSize(hTicksFile)/sizeof(TickStruct));
   
if(ArrayResize(g_ticks,recSize,1000)<0)
     
{
     
Alert(WindowExpertName(),": не удалось распределить память для подкачки данных из временного файла тиков. Индикатор отключен.");
     
FileClose(hTicksFile);
     
return false;
     
}

//--- Read the file
   
int i=0;
   
while(i<recSize)
     
{
     
if(FileReadStruct(hTicksFile,g_ticks[i])==0)
       
{
         
Alert(WindowExpertName(),": ошибка чтения данных из временного файла. Индикатор отключен.");
         
return false;
       
}
      i
++;
     
}

   
FileClose(hTicksFile);
   
return true;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Formation of an array of volume values ​​and levels corresponding to them colors / Формирование массива значений объемов и соответствующих им цветам уровней                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void CreateVolumeColorsArray()
 
{
   g_volumeLevelsColor
[0].levelMinVolume = i_minVolumeLevel1;
   g_volumeLevelsColor
[1].levelMinVolume = i_minVolumeLevel2;
   g_volumeLevelsColor
[2].levelMinVolume = i_minVolumeLevel3;
   g_volumeLevelsColor
[3].levelMinVolume = i_minVolumeLevel4;
   g_volumeLevelsColor
[4].levelMinVolume = i_minVolumeLevel5;

   g_volumeLevelsColor
[0].levelColor = i_colorLevel1;
   g_volumeLevelsColor
[1].levelColor = i_colorLevel2;
   g_volumeLevelsColor
[2].levelColor = i_colorLevel3;
   g_volumeLevelsColor
[3].levelColor = i_colorLevel4;
   g_volumeLevelsColor
[4].levelColor = i_colorLevel5;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Formation of an array of volume values ​​and levels corresponding to them colors / Установка нужного масштаба графика для работы индикатора                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SetChartView()
 
{
//--- Position of a candlestick chart relative to other charts
   g_chartForeground
=(bool)ChartGetInteger(0,CHART_FOREGROUND);
   
ChartSetInteger(0,CHART_FOREGROUND,false);

   
if(i_useNeededScale==NO)
     
return;

//--- Chart scale
   g_currentScale
=(int)ChartGetInteger(0,CHART_SCALE);
   
ChartSetInteger(0,CHART_SCALE,(long)i_chartScale);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator deinitialization function                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
 
{
   
if(!IsSavedFile())    // If none of the connected indicators has saved the data, the current indicator will save them.
     
SaveTempTicks();   // Saving data on ticks accumulated during the current period of the indicator operation
   
DeleteAllObjects();
   
RestoreChartView();
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the presence of recorded data with another indicator                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsSavedFile()
 
{
//--- Getting the arrival time of the last recorded tick
   
int lastTickIndex=ArraySize(g_ticks)-1;
   
if(lastTickIndex<0) // No ticks were received. No data recording required
     
return true;

//--- Opening a tick history file
   
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
   
if(hTicksFile<1)
     
return false;

//--- Move to the last entry in the file
   
if(!FileSeek(hTicksFile,-sizeof(TickStruct),SEEK_END))
     
{
     
FileClose(hTicksFile);
     
return false;
     
}

//--- Reading the last record and closing the file
   
TickStruct tick;
   
uint readBytes=FileReadStruct(hTicksFile,tick);
   
FileClose(hTicksFile);
   
if(readBytes==0)
     
return false;

//--- Comparison of the date of the tick recorded in the file and the date of the last received tick
   
return tick.time >= g_ticks[lastTickIndex].time;                                                // The date / time of the last tick recorded in the file is greater than or equal to the date / time ..
                                                                                                   
// .. of the registered tick. This means that the file has already been written, and rewriting is not required
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Saving data on ticks accumulated during the current working session of the program / Сохранение данных о тиках, накопленных за текущую рабочую сессию программы                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SaveTempTicks()
 
{
//--- Creating a tick history file
   
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE);
   
if(hTicksFile<1)
     
return;

//--- File recording
   
int total=ArraySize(g_ticks),i=0;
   
while(i<total)
     
{
     
if(FileWriteStruct(hTicksFile,g_ticks[i])==0)
       
{
         
Print("Ошибка сохранения данных во временный файл...");
         
return;
       
}
      i
++;
     
}

   
FileClose(hTicksFile);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| On / off button display visualization of indicator readings / Отображение кнопки вкл./выкл. визуализации показаний индикатора                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowInfoViewButton()
 
{
   
if(!g_init)
     
return;

   g_isShowInfo
=true;
   
ShowButton(BUTTON_XCOORD,BUTTON_YCOORD,"Кластеры выкл.");
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying the button graphic / Отображение графического объекта "Кнопка"                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowButton(int x,int y,string text)
 
{
   
string name=PREFIX+SIGN_BUTTON+IntegerToString(x)+IntegerToString(y);

   
if(ObjectFind(0,name)<0)
     
{
     
ObjectCreate(0,name,OBJ_BUTTON,0,0,0);

     
ObjectSetInteger(0,name,OBJPROP_CORNER,0);
     
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
     
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);

     
ObjectSetInteger(0,name,OBJPROP_XSIZE,BUTTON_WIDTH);
     
ObjectSetInteger(0,name,OBJPROP_YSIZE,BUTTON_HEIGHT);

     
ObjectSetString(0,name,OBJPROP_TEXT,text);
     
ObjectSetString(0,name,OBJPROP_FONT,BUTTON_FONT_NAME);
     
ObjectSetString(0,name,OBJPROP_TOOLTIP,BUTTON_TOOLTIP);
     
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,BUTTON_FONT_SIZE);

     
ObjectSetInteger(0,name,OBJPROP_COLOR,BUTTON_TEXT_COLOR);
     
ObjectSetInteger(0,name,OBJPROP_BORDER_COLOR,BUTTON_BORDER_COLOR);
     
ObjectSetInteger(0,name,OBJPROP_BGCOLOR,BUTTON_BACKGROUND_COLOR);

     
ObjectSetInteger(0,name,OBJPROP_BACK,false);
     
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
     
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
     
return;
     
}

   
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
   
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
   
ObjectSetString(0,name,OBJPROP_TEXT,text);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Deleting all objects created by the program / Удаление всех объектов, созданных программой                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void DeleteAllObjects()
 
{
   
for(int i=ObjectsTotal()-1; i>=0; i--)
     
if(StringSubstr(ObjectName(i),0,StringLen(PREFIX))==PREFIX)
         
ObjectDelete(ObjectName(i));

   g_init
=true;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Returning the current scale of the chart / Возвращение действующего масштаба графика                                                                                                              |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void RestoreChartView()
 
{
   
ChartSetInteger(0,CHART_FOREGROUND,g_chartForeground);

   
if(i_useNeededScale==NO)
     
return;

   
ChartSetInteger(0,CHART_SCALE,g_currentScale);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of the bar index from which it is necessary to recalculate / Определение индекса бара, с которого необходимо производить перерасчет                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex(int &total,const int ratesTotal,const int prevCalculated)
 
{
//--- Determination of the first bar in history, on which adequate indicator values will be available
   total
=ratesTotal-1;

//--- Or maybe the indicator values do not need to be displayed throughout the history?
   
if(i_indBarsCount>0 && i_indBarsCount<total)
      total
=MathMin(i_indBarsCount,total);

//--- The first display of the indicator or there was a pumping of data, i.e., on the previous tick, the bars were not one bar less, as in the normal development of history, but two or more bars less
   
if(prevCalculated<ratesTotal-1)
     
{
     
DeleteAllObjects();
     
return (total);
     
}

//--- Normal development of history. The number of bars of the current tick differs from the number of bars of the previous tick by no more than one bar
   
return (MathMin(ratesTotal - prevCalculated, total));
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Is the first number greater than the second? / Больше ли первое число, чем второе?                                                                                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFirstMoreThanSecond(double first,double second)
 
{
   
return (first - second > Point / 10);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Are the numbers equal?                                                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsValuesEquals(double first,double second)
 
{
   
return (MathAbs(first - second) < Point / 10);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Reading one tick from a file                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsReadTimeAndBidAskOfTick(int hTicksFile,TickStruct &tick)
 
{
   
if(FileIsEnding(hTicksFile))
     
{
     
FileClose(hTicksFile);
     
return false;
     
}

   
uint bytesCnt=FileReadStruct(hTicksFile,tick);
   
if(bytesCnt==sizeof(TickStruct))
     
return true;

   
FileClose(hTicksFile);
   
return false;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Reducing the market price to the price of the cluster, taking into account its height                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
double CastPriceToCluster(double price)
 
{
   
int priceInPoints=(int)MathRound(price/Point);
   
int clusterPrice =(int)MathRound(priceInPoints/1.0/i_pointsInBox);
   
return NormalizeDouble(clusterPrice * Point * i_pointsInBox, Digits);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Reading ticks belonging to one candlestick                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ReadTicksFromFile(int hTicksFile,datetime limitTime,TickStruct &tick,int &ticksCount,bool &fileClose)
 
{
   
while(!fileClose)
     
{
      fileClose
=!IsReadTimeAndBidAskOfTick(hTicksFile,tick);
     
if(tick.time>=limitTime || fileClose || tick.time==0)
         
break;

      g_ticksPrice
[ticksCount]=CastPriceToCluster(tick.bid);
      ticksCount
++;
     
if(ticksCount>MAX_TICKS_IN_CANDLE)
         
break;
     
}
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Distribution of ticks by clusters                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SortTicksByCluster(int ticksCount,int &arraySize)
 
{
   arraySize
=1;
   
ArrayInitialize(g_volumePriceArray,0);
   g_volumePriceArray
[0]=1;
   
for(int i=1; i<ticksCount; i++)
     
{
     
if(!IsValuesEquals(g_ticksPrice[i-1],g_ticksPrice[i]))
       
{
         arraySize
+=(int)MathRound((g_ticksPrice[i]-g_ticksPrice[i-1])/g_tickSize);
         
if(arraySize>MAX_POINTS_IN_CANDLE)
           
break;
       
}
      g_volumePriceArray
[arraySize-1]++;
     
}
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Reading tick data from the tick buffer                                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void AddDataFromBuffer(datetime limitTime,TickStruct &tick,int &ticksCount)
 
{
//--- Search in the buffer for a tick whose time is longer than the last read tick
   
int total=ArraySize(g_ticks),i=0;
   
while(i<total && tick.time>=g_ticks[i].time)
      i
++;

//--- Reached the end of the buffer - we are leaving
   
if(i>=total)
     
{
      tick
.time=0;                                                                               // Telling the while loop in the ProcessOldCandles function that the data in the buffer has run out
     
return;
     
}

//--- Overwriting data from one buffer to another
   
while(i<total && g_ticks[i].time<limitTime)
     
{
      g_ticksPrice
[ticksCount]=CastPriceToCluster(g_ticks[i].bid);
      ticksCount
++;
      i
++;
     
}

//--- Saving data on the tick of the next bar
   
if(i<total)
      tick
=g_ticks[i];
   
else
      tick
.time=0;                                                                               // Telling the while loop in the ProcessOldCandles function that the data in the buffer has run out
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Preparing data for one bar                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void FormDataForOneBar(int hTicksFile,datetime limitTime,TickStruct &tick,double &lowPrice,int &arraySize,bool &fileClose)
 
{
//--- Reading ticks belonging to one candlestick
   
int ticksCount=1;
   g_ticksPrice
[0]=CastPriceToCluster(tick.bid);
   
if(!fileClose)
     
ReadTicksFromFile(hTicksFile,limitTime,tick,ticksCount,fileClose);

   
if(fileClose) // This is not an error - else is not needed, because after ReadTicksFromFile execution, fileClose may change
     
AddDataFromBuffer(limitTime,tick,ticksCount);

//--- Sort the array in ascending order. After it, the zero element contains the low of the candlestick, and the [ticksCount - 1] element - the high
   
ArraySort(g_ticksPrice,ticksCount);
   lowPrice
=g_ticksPrice[0];

//--- Distribution of ticks by clusters
   
SortTicksByCluster(ticksCount,arraySize);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|  Horizontal line display                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowHLine(double price,color clr)
 
{
   
string name=PREFIX+"HLINE_"+IntegerToString((int)(price/g_point));

   
if(ObjectFind(0,name)<0)
     
{
     
ObjectCreate(0,name,OBJ_HLINE,0,0,price);
     
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
     
ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
     
ObjectSetInteger(0,name,OBJPROP_BACK,true);
     
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
     
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
     
return;
     
}

   
ObjectMove(0,name,0,1,price);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying the "Text" object                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowText(int index,datetime time,double price,string text,string toolTip,color clr)
 
{
   
string name=PREFIX+IntegerToString(time)+IntegerToString(index);
   
if(ObjectFind(0,name)<0)
     
{
     
ObjectCreate(0,name,OBJ_TEXT,0,time,price);
     
ObjectSetString(0,name,OBJPROP_FONT,FONT_NAME);
     
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,FONT_SIZE);
     
ObjectSetString(0,name,OBJPROP_TEXT,text);
     
ObjectSetString(0,name,OBJPROP_TOOLTIP,toolTip);
     
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
     
ObjectSetInteger(0,name,OBJPROP_BACK,false);
     
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
     
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
     
return;
     
}

   
ObjectMove(0,name,0,time,price);
   
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
   
ObjectSetString(0,name,OBJPROP_TEXT,text);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of which of the indicated volumes corresponds to the considered volume                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetVolumeLevel(int index)
 
{
   
for(int i=0; i<MAX_VOLUMES_SHOW; i++)
     
if(g_volumeLevelsColor[i].levelMinVolume>g_volumePriceArray[index])
         
return i - 1;

   
return MAX_VOLUMES_SHOW - 1;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying histograms of one bar                                                                                                                                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowBarHistogramms(int barIndex,double lowPrice,int arraySize)
 
{
   
if(!g_isShowInfo)
     
return;

   
for(int i=0; i<arraySize; i+=i_pointsInBox)
     
{
     
//--- Is the volume of the level large enough?
     
int volumeLevel=GetVolumeLevel(i);
     
if(volumeLevel<0)
         
continue;

     
//--- Display volumes
     
double price=lowPrice+i*g_tickSize;
     
ShowText(i,Time[barIndex],price,IntegerToString(g_volumePriceArray[i]),DoubleToString(price,Digits),g_volumeLevelsColor[volumeLevel].levelColor);
     
}
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying data for historical bars starting from the specified                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessOldCandles(int limit,double &lowPrice,int &arraySize)
 
{
//--- Opening a tick history file
   
bool fileClose = false;
   
int hTicksFile = FileOpen(Symbol() + ".tks", FILE_BIN | FILE_READ | FILE_SHARE_READ | FILE_SHARE_WRITE);
   
if(hTicksFile<1)
      fileClose
=true;

//--- Search for the first tick belonging to the limit bar or any later bar
   
TickStruct tick;
   tick
.time= Time[limit];
   tick
.bid = Open[limit];
   
while(!IsStopped() && !fileClose)
     
{
     
if(!IsReadTimeAndBidAskOfTick(hTicksFile,tick))
         
return;

     
if(tick.time>=Time[limit])
         
break;
     
}

//--- Displaying data
   datetime extremeTime
=Time[0]+PeriodSeconds();
   
while(tick.time<extremeTime && tick.time!=0)
     
{
     
int barIndex=iBarShift(NULL,0,tick.time);
     
FormDataForOneBar(hTicksFile,Time[barIndex]+PeriodSeconds(),tick,lowPrice,arraySize,fileClose);
     
ShowBarHistogramms(barIndex,lowPrice,arraySize);
     
}

   
if(!fileClose)
     
FileClose(hTicksFile);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Formation of a new bar                                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessNewBarForming(double bid,double &lowPrice,int &arraySize)
 
{
   
ArrayInitialize(g_volumePriceArray,0);
   arraySize
= 1;
   lowPrice
= bid;
   g_volumePriceArray
[0]=1;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Updating the low of the current candle                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessCandleMinimumUpdate(int priceIndex,double bid,double &lowPrice,int &arraySize)
 
{
   priceIndex
= MathAbs(priceIndex);
   arraySize
+= priceIndex;
   
if(arraySize>MAX_POINTS_IN_CANDLE)
     
return;

//--- Increasing the number of significant array elements by the priceIndex of the elements
   
for(int i=arraySize-1; i>priceIndex-1; i--)
      g_volumePriceArray
[i]=g_volumePriceArray[i-priceIndex];

//--- Zero-filling items corresponding to prices between the previous minimum and the current
   
for(int i=priceIndex-1; i>=0; i--)
      g_volumePriceArray
[i]=0;
   g_volumePriceArray
[0]=1;

//--- New minimum
   lowPrice
=bid;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Writing tick data to the g_ticks array                                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsUpdateTicksArray(TickStruct &tick)
 
{
   
int total=ArraySize(g_ticks);
   
if(ArrayResize(g_ticks,total+1,100)<0)
     
{
     
Alert(WindowExpertName(),": индикатору не хватает памяти для сохранения данных об очередном тике.");
     
return false;
     
}

   g_ticks
[total]=tick;
   
return true;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Adding one new tick to an existing candlestick                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessOneTick(int limit,double &lowPrice,int &arraySize)
 
{
   
TickStruct tick;
   tick
.time= TimeCurrent();
   tick
.ask = Ask;
   tick
.bid = Bid;

//--- Adding one tick to the tick storage array
   
if(!IsUpdateTicksArray(tick))
     
{
      g_activate
=false;
     
return;
     
}

   
double bid=CastPriceToCluster(Bid);

//--- Setting up a new bar or starting from scratch
   
if(limit==1 || lowPrice==0 || arraySize==0)
     
{
     
ProcessNewBarForming(bid,lowPrice,arraySize);
     
return;
     
}

//--- If the extremes of the candlestick are not updated, then the volume is simply added to one of the existing levels
   
int priceIndex=(int)MathRound((bid-lowPrice)/g_tickSize);                                 // Index of the element of the g_volumePriceArray array to which the Bid price corresponds
   
if(priceIndex>=0 && priceIndex < arraySize)
     
{
      g_volumePriceArray
[priceIndex]++;
     
return;
     
}

//---The minimum of the current candle has been updated. It is necessary to shift all elements of the g_volumePriceArray array by priceIndex up
   
if(IsFirstMoreThanSecond(lowPrice,bid))
     
{
     
ProcessCandleMinimumUpdate(priceIndex,bid,lowPrice,arraySize);
     
return;
     
}

//--- The high of the current candle has been updated.
   
if(priceIndex+1>MAX_POINTS_IN_CANDLE)
     
return;

   arraySize
=priceIndex+1;
   g_volumePriceArray
[priceIndex]=1;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Cluster grid display                                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowGrid()
 
{
   
if(!g_init)
     
return;

   g_init
=false;

   
if(i_showClusterGrid==NO)
     
return;

//--- Identifying Historical Extremes
   
double highPrice= CastPriceToCluster(High[iHighest(NULL,0,MODE_HIGH)]);
   
double lowPrice = CastPriceToCluster(Low[iLowest(NULL,0,MODE_LOW)]);

//--- Displaying cluster lines
   
for(double price=lowPrice; price<=highPrice; price=NormalizeDouble(price+i_pointsInBox*g_point,Digits))
     
ShowHLine(price,i_gridColor);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying indicator data                                                                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowIndicatorData(int limit,int total)
 
{
   
static double lowPrice = 0;                                                                     // The price corresponding to the low of the candlestick and the zero element of the g_volumePriceArray array. The first..
                                                                                                   
// ..the element will be matched with the price lowPrice + Point, etc .;
   
static int arraySize = 0;                                                                       // The number of elements written to the g_volumePriceArray array. Ideally, this value should be..
                                                                                                   
// ..is equal to the number of points that the candlestick consists of. But due to the separate recording of ticks and..
                                                                                                   
// ..real candlestick formation shifts are possible
   
if(limit>1)   // The call occurs only at the moment of displaying the entire history - initial download or update..
     
{           // ..bars with index more than 1
     
ProcessOldCandles(limit,lowPrice,arraySize);
     
return;
     
}

//--- Normal update - arrival of a new tick or formation of a new bar
   
ProcessOneTick(limit,lowPrice,arraySize);
   
ShowBarHistogramms(0,lowPrice,arraySize);
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator iteration function                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnCalculate(const int rates_total,
               
const int prev_calculated,
               
const datetime &time[],
               
const double &open[],
               
const double &high[],
               
const double &low[],
               
const double &close[],
               
const long &tick_volume[],
               
const long &volume[],
               
const int &spread[])
 
{
   
if(!g_activate) // If the indicator has not been initialized, then it should not work
     
return rates_total;

   
ProcessGlobalTick(rates_total,prev_calculated);

   
return rates_total;
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Performing one iteration of data display                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessGlobalTick(const int rates_total,const int prev_calculated)
 
{
   
int total;
   
int limit=GetRecalcIndex(total,rates_total,prev_calculated);                                // Which bar to start the update from?

   
ShowInfoViewButton();                                                                           // On / off button display visualization of indicator readings
   
ShowGrid();                                                                                     // Displaying cluster lines
   
ShowIndicatorData(limit, total);                                                                // Displaying indicator data
 
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Chart event handler                                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
 
{
   
if(id!=CHARTEVENT_OBJECT_CLICK)
     
return;

   
if(sparam!=PREFIX+SIGN_BUTTON+IntegerToString(BUTTON_XCOORD)+IntegerToString(BUTTON_YCOORD))
     
return;

//--- Shutting down clusters  
   
if(g_isShowInfo)
     
{
     
DeleteAllObjects();
     
ShowButton(BUTTON_XCOORD,BUTTON_YCOORD,"Кластеры вкл.");
      g_isShowInfo
=false;
      g_init
=false;
     
return;
     
}

//--- Enabling clusters
   g_init
=true;
   
ProcessGlobalTick(Bars,0);
 
}
//+------------------------------------------------------------------+
  • 0
  • Просмотров: 1233
  • 4 августа 2020, 15:31
  • TradeG
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Стол заказов MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
  Предыдущая запись в группе
Расширение фибо
Следующая запись в группе  
Скрипт
04 августа 2020
04 августа 2020

Брокер для ваших роботов, 15 лет на рынке

Комментарии (1)

0
Кто-нибудь хочет стать поручителем за это? *budenov* 
avatar

  2  TradeG Автор Сообщений: 32

  • 4 августа 2020, 15:33

Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий
Загрузка...