Miscellaneous
0
Views
0
Downloads
0
Favorites
clusterbox_ad
//+------------------------------------------------------------------+
//| 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 // Ïðèáðîñêà äëÿ ñâå÷åé ìåñÿ÷íîãî ãðàôèêà ïÿòèçíàêà
#define MAX_TICKS_IN_CANDLE 1000000 // Ïðèáðîñêà äëÿ ñâå÷åé ìåñÿ÷íîãî ãðàôèêà ïÿòèçíàêà
#define MAX_VOLUMES_SHOW 5 // Êîëè÷åñòâî óðîâíåé ìàêñèìàëüíîãî îáúåìà, êîòîðûå ñëåäóåò îòîáðàæàòü
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct LevelVolumeColor // Ñòðóêòóðà ñîîòâåòñòâèÿ óðîâíåé îáúåìà, äîñòèæåíèå êîòîðûõ íà öåíîâîì óðîâíå îòîáðàæàåòñÿ..
{ // ..ñîîòâåòñòâóþùèì öâåòîì
color levelColor;
int levelMinVolume;
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct TickStruct // Ñòðóêòóðà äëÿ çàïèñè äàííûõ îá îäíîì òèêå
{
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 / Íàèáîëüøèé
};
//--- Íàñòðîå÷íûå ïàðàìåòðû èíäèêàòîðà
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 / Êîë-âî áàðîâ îòîáðàæåíèÿ
//--- Ïðî÷èå ãëîáàëüíûå ïåðåìåííûå èíäèêàòîðà
bool g_activate, // Ïðèçíàê óñïåøíîé èíèöèàëèçàöèè èíäèêàòîðà
g_isShowInfo, // Ïðèçíàê íåîáõîäèìîñòè îòîáðàæåíèÿ äàííûõ èíäèêàòîðà
g_chartForeground, // Ïðèçíàê íàõîæäåíèÿ ñâå÷åé íà ïåðåäíåì ïëàíå
g_init; // Ïåðåìåííàÿ äëÿ èíèöèàëèçàöèè ñòàòè÷åñêèõ ïåðåìåííûõ âíóòðè ôóíêöèé â ìîìåíò ïðîâåäåíèÿ..
// ..ïîâòîðíîé èíèöèàëèçàöèè
int g_currentScale,// Ìàñøòàá ãðàôèêà äåéñòâóþùèé íà ìîìåíò ïðèñîåäèíåíèÿ èíäèêàòîðà
g_volumePriceArray[MAX_POINTS_IN_CANDLE]; // Ðàáî÷èé ìàññèâ óðîâíåé, â êîòîðûé çàïèñûâàåòñÿ êîëè÷åñòâî òèêîâ, êîòîðûå ïîïàëè íà..
// ..ñîîòâåòñòâóþùóþ öåíó ñâå÷è. Êîëè÷åñòâî çàïîëíåííûõ ýëåìåíòîâ ìàññèâà - âûñîòà ñâå÷è
double g_ticksPrice[MAX_TICKS_IN_CANDLE]; // Ìàññèâ äëÿ âðåìåííîãî õðàíåíèÿ íàáîðà òèêîâ, ïðèõîäÿùèõñÿ íà îäíó ñâå÷ó
double g_point,
g_tickSize;
TickStruct g_ticks[]; // Ìàññèâ äëÿ õðàíåíèÿ òèêîâ, ïîñòóïèâøèõ ïîñëå íà÷àëà ðàáîòû èíäèêàòîðà
LevelVolumeColor g_volumeLevelsColor[MAX_VOLUMES_SHOW]; // Ìàññèâ îáúåìîâ è, ñîîòâåòñòâóþùèì èì, öâåòîâ óðîâíåé
#define PREFIX "CLSTRBX_" // Ïðåôèêñ ãðàôè÷åñêèõ îáúåêòîâ, îòîáðàæàåìûõ èíäèêàòîðîì
#define SIGN_BUTTON "INFO_BUTTON_" // Êîðåíü èìåíè ãðàôè÷åñêîãî îáúåêòà "êíîïêà"
#define BUTTON_FONT_NAME "MS Sans Serif" // Èìÿ øðèôòà äëÿ îòîáðàæåíèÿ òåêñòà êíîïêè
#define BUTTON_TOOLTIP "Âêë/âûêë îòîáðàæåíèå êëàñòåðîâ è ñåòêè" // Ïîäñêàçêà ê íàçíà÷åíèþ êíîïêè
#define BUTTON_XCOORD 2 // Õ-êîîðäèíàòà ëåâîãî âåðõíåãî óãëà êíîïêè
#define BUTTON_YCOORD 14 // Y-êîîðäèíàòà ëåâîãî âåðõíåãî óãëà êíîïêè
#define BUTTON_WIDTH 110 // Øèðèíà êíîïêè
#define BUTTON_HEIGHT 20 // Âûñîòà êíîïêè
#define BUTTON_FONT_SIZE 7 // Ðàçìåð øðèôòà äëÿ òåêñòà êíîïêè
#define BUTTON_TEXT_COLOR clrBlack // Öâåò øðèôòà òåêñòà â êíîïêå
#define BUTTON_BORDER_COLOR clrNONE // Öâåò ãðàíèöû êíîïêè
#define BUTTON_BACKGROUND_COLOR clrLightGray // Öâåò çàëèâêè êíîïêè
#define FONT_NAME "MS Sans Serif"
#define FONT_SIZE 7
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
g_activate=false; // Èíäèêàòîð íå èíèöèàëèçèðîâàí
g_init=true;
if(!IsTuningParametersCorrect()) // Íåâåðíî óêàçàííûå çíà÷åíèÿ íàñòðîå÷íûõ ïàðàìåòðîâ - ïðè÷èíà íåóäà÷íîé èíèöèàëèçàöèè
return INIT_FAILED;
if(!IsLoadTempTicks()) // Çàãðóçêà äàííûõ î òèêàõ, ñîõðàíåííûõ çà ïðåäûäóùèé ïåðèîä ðàáîòû èíäèêàòîðà
return INIT_FAILED;
CreateVolumeColorsArray(); // Êîïèðîâàíèå äàííûõ î öâåòå è âåëè÷èíå óðîâíåé â ìàññèâ
SetChartView(); // Óñòàíîâêà ñïåöèôè÷åñêîãî âèäà ãðàôèêà
g_activate=true; // Èíäèêàòîð óñïåøíî èíèöèàëèçèðîâàí
return INIT_SUCCEEDED;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïðîâåðêà êîððåêòíîñòè íàñòðîå÷íûõ ïàðàìåòðîâ |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTuningParametersCorrect()
{
string name=WindowExpertName();
int period= Period();
if(period == 0)
{
Alert(name,": ôàòàëüíàÿ îøèáêà òåðìèíàëà - ïåðèîä 0 ìèíóò. Èíäèêàòîð îòêëþ÷åí.");
return (false);
}
g_point=Point;
if(g_point==0)
{
Alert(name,": ôàòàëüíàÿ îøèáêà òåðìèíàëà - âåëè÷èíà ïóíêòà ðàâíà íóëþ. Èíäèêàòîð îòêëþ÷åí.");
return (false);
}
g_tickSize=MarketInfo(Symbol(),MODE_TICKSIZE);
if(g_tickSize==0)
{
Alert(name,": ôàòàëüíàÿ îøèáêà òåðìèíàëà - âåëè÷èíà øàãà îäíîãî òèêà ðàâíà íóëþ. Èíäèêàòîð îòêëþ÷åí.");
return (false);
}
if(i_pointsInBox<1)
{
Alert(name,": êîëè÷åñòâî ïóíêòîâ â êëàñòåðå äîëæíî áûòü ïîëîæèòåëüíûì. Èíäèêàòîð îòêëþ÷åí.");
return (false);
}
return (true);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| ×òåíèå äàííûõ î òèêàõ, íàêîïëåííûõ â òå÷åíèå ïðåäûäóùåé ðàáî÷åé ñåññèè ïðîãðàììû |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsLoadTempTicks()
{
//--- Îòêðûòèå ôàéëà òèêîâîé èñòîðèè
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
if(hTicksFile<1)
return true;
//--- Ðàñïðåäåëåíèå ïàìÿòè äëÿ ìàññèâà g_ticks
int recSize=(int)(FileSize(hTicksFile)/sizeof(TickStruct));
if(ArrayResize(g_ticks,recSize,1000)<0)
{
Alert(WindowExpertName(),": íå óäàëîñü ðàñïðåäåëèòü ïàìÿòü äëÿ ïîäêà÷êè äàííûõ èç âðåìåííîãî ôàéëà òèêîâ. Èíäèêàòîð îòêëþ÷åí.");
FileClose(hTicksFile);
return false;
}
//--- ×òåíèå ôàéëà
int i=0;
while(i<recSize)
{
if(FileReadStruct(hTicksFile,g_ticks[i])==0)
{
Alert(WindowExpertName(),": îøèáêà ÷òåíèÿ äàííûõ èç âðåìåííîãî ôàéëà. Èíäèêàòîð îòêëþ÷åí.");
return false;
}
i++;
}
FileClose(hTicksFile);
return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ôîðìèðîâàíèå ìàññèâà çíà÷åíèé îáúåìîâ è ñîîòâåòñòâóþùèõ èì öâåòàì óðîâíåé |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Óñòàíîâêà íóæíîãî ìàñøòàáà ãðàôèêà äëÿ ðàáîòû èíäèêàòîðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SetChartView()
{
//--- Ïîëîæåíèå ñâå÷íîãî ãðàôèêà îòíîñèòåëüíî ïðî÷åé ãðàôèêè
g_chartForeground=(bool)ChartGetInteger(0,CHART_FOREGROUND);
ChartSetInteger(0,CHART_FOREGROUND,false);
if(i_useNeededScale==NO)
return;
//--- Ìàñøòàá ãðàôèêà
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()) // Åñëè íè îäèí èç ïîäêëþ÷åííûõ èíäèêàòîðîâ íå ñîõðàíèë äàííûå, òî èõ ñîõðàíèò òåêóùèé èíäèêàòîð
SaveTempTicks(); // Ñîõðàíåíèå äàííûõ î òèêàõ, íàêîïëåííûõ çà òåêóùèé ïåðèîä ðàáîòû èíäèêàòîðà
DeleteAllObjects();
RestoreChartView();
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïðîâåðêà íàëè÷èÿ çàïèñàííûõ äàííûõ äðóãèì èíäèêàòîðîì |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsSavedFile()
{
//--- Ïîëó÷åíèå âðåìåíè ïîñòóïëåíèÿ ïîñëåäíåãî çàïèñàííîãî òèêà
int lastTickIndex=ArraySize(g_ticks)-1;
if(lastTickIndex<0) // Íè îäèí òèê íå áûë ïîëó÷åí. Çàïèñü äàííûõ íå òðåáóåòñÿ
return true;
//--- Îòêðûòèå ôàéëà òèêîâîé èñòîðèè
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
if(hTicksFile<1)
return false;
//--- Ïåðåìåùåíèå ê ïîñëåäíåé çàïèñè â ôàéëå
if(!FileSeek(hTicksFile,-sizeof(TickStruct),SEEK_END))
{
FileClose(hTicksFile);
return false;
}
//--- ×òåíèå ïîñëåäíåé çàïèñè è çàêðûòèå ôàéëà
TickStruct tick;
uint readBytes=FileReadStruct(hTicksFile,tick);
FileClose(hTicksFile);
if(readBytes==0)
return false;
//--- Ñðàâíåíèå äàòû òèêà, çàïèñàííîãî â ôàéëå, è äàòû ïîñëåäíåãî ïîñòóïèâøåãî òèêà
return tick.time >= g_ticks[lastTickIndex].time; // Äàòà/âðåìÿ ïîñëåäíåãî çàïèñàííîãî â ôàéëå òèêà áîëüøå èëè ðàâíà äàòå/âðåìåíè..
// ..çàðåãèñòðèðîâàííîãî òèêà. Çíà÷èò, ôàéë óæå çàïèñàí, è ïîâòîðíàÿ çàïèñü íå òðåáóåòñÿ
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ñîõðàíåíèå äàííûõ î òèêàõ, íàêîïëåííûõ çà òåêóùóþ ðàáî÷óþ ñåññèþ ïðîãðàììû |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SaveTempTicks()
{
//--- Ñîçäàíèå ôàéëà òèêîâîé èñòîðèè
int hTicksFile=FileOpen(Symbol()+"temp.tks",FILE_BIN|FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE);
if(hTicksFile<1)
return;
//--- Çàïèñü ôàéëà
int total=ArraySize(g_ticks),i=0;
while(i<total)
{
if(FileWriteStruct(hTicksFile,g_ticks[i])==0)
{
Print("Îøèáêà ñîõðàíåíèÿ äàííûõ âî âðåìåííûé ôàéë...");
return;
}
i++;
}
FileClose(hTicksFile);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå êíîïêè âêë./âûêë. âèçóàëèçàöèè ïîêàçàíèé èíäèêàòîðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowInfoViewButton()
{
if(!g_init)
return;
g_isShowInfo=true;
ShowButton(BUTTON_XCOORD,BUTTON_YCOORD,"Êëàñòåðû âûêë.");
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå ãðàôè÷åñêîãî îáúåêòà "Êíîïêà" |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Óäàëåíèå âñåõ îáúåêòîâ, ñîçäàííûõ ïðîãðàììîé |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void DeleteAllObjects()
{
for(int i=ObjectsTotal()-1; i>=0; i--)
if(StringSubstr(ObjectName(i),0,StringLen(PREFIX))==PREFIX)
ObjectDelete(ObjectName(i));
g_init=true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Âîçâðàùåíèå äåéñòâóþùåãî ìàñøòàáà ãðàôèêà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void RestoreChartView()
{
ChartSetInteger(0,CHART_FOREGROUND,g_chartForeground);
if(i_useNeededScale==NO)
return;
ChartSetInteger(0,CHART_SCALE,g_currentScale);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îïðåäåëåíèå èíäåêñà áàðà, ñ êîòîðîãî íåîáõîäèìî ïðîèçâîäèòü ïåðåðàñ÷åò |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex(int &total,const int ratesTotal,const int prevCalculated)
{
//--- Îïðåäåëåíèå ïåðâîãî áàðà èñòîðèè, íà êîòîðîì áóäóò äîñòóïíû àäåêâàòíûå çíà÷åíèÿ èíäèêàòîðà
total=ratesTotal-1;
//--- À ìîæåò çíà÷åíèÿ èíäèêàòîðà íå íóæíî îòîáðàæàòü íà âñåé èñòîðèè?
if(i_indBarsCount>0 && i_indBarsCount<total)
total=MathMin(i_indBarsCount,total);
//--- Ïåðâîå îòîáðàæåíèå èíäèêàòîðà èëè ïðîèçîøëà ïîäêà÷êà äàííûõ, ò. å. íà ïðåäûäóùåì òèêå áàðîâ áûëî íå íà îäèí áàð ìåíüøå, êàê ïðè íîðìàëüíîì ðàçâèòèè èñòîðèè, à íà äâà èëè áîëåå áàðîâ ìåíüøå
if(prevCalculated<ratesTotal-1)
{
DeleteAllObjects();
return (total);
}
//--- Íîðìàëüíîå ðàçâèòèå èñòîðèè. Êîëè÷åñòâî áàðîâ òåêóùåãî òèêà îòëè÷àåòñÿ îò êîëè÷åñòâà áàðîâ ïðåäûäóùåãî òèêà íå áîëüøå, ÷åì íà îäèí áàð
return (MathMin(ratesTotal - prevCalculated, total));
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Áîëüøå ëè ïåðâîå ÷èñëî, ÷åì âòîðîå? |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFirstMoreThanSecond(double first,double second)
{
return (first - second > Point / 10);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ðàâíû ëè ÷èñëà? |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsValuesEquals(double first,double second)
{
return (MathAbs(first - second) < Point / 10);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| ×òåíèå îäíîãî òèêà èç ôàéëà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïðèâåäåíèå ðûíî÷íîé öåíû ê öåíå êëàñòåðà ñ ó÷åòîì åãî âûñîòû |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ñ÷èòûâàíèå òèêîâ, ïðèíàäëåæàùèõ îäíîé ñâå÷å |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
}
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ðàñïðåäåëåíèå òèêîâ ïî êëàñòåðàì |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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]++;
}
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| ×òåíèå òèêîâûõ äàííûõ èç áóôåðà òèêîâ |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void AddDataFromBuffer(datetime limitTime,TickStruct &tick,int &ticksCount)
{
//--- Ïîèñê â áóôåðå òèêà, âðåìÿ êîòîðîãî áîëüøå ïîñëåäíåãî ñ÷èòàííîãî òèêà
int total=ArraySize(g_ticks),i=0;
while(i<total && tick.time>=g_ticks[i].time)
i++;
//--- Äîñòèãëè êîíöà áóôåðà - óõîäèì
if(i>=total)
{
tick.time=0; // Óêàçàíèå öèêëó while â ôóíêöèè ProcessOldCandles íà òî, ÷òî äàííûå â áóôåðå çàêîí÷èëèñü
return;
}
//--- Ïåðåçàïèñü äàííûõ èç îäíîãî áóôåðà â äðóãîé
while(i<total && g_ticks[i].time<limitTime)
{
g_ticksPrice[ticksCount]=CastPriceToCluster(g_ticks[i].bid);
ticksCount++;
i++;
}
//--- Ñîõðàíåíèå äàííûõ î òèêå ñëåäóþùåãî áàðà
if(i<total)
tick=g_ticks[i];
else
tick.time=0; // Óêàçàíèå öèêëó while â ôóíêöèè ProcessOldCandles íà òî, ÷òî äàííûå â áóôåðå çàêîí÷èëèñü
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïîäãîòîâêà äàííûõ äëÿ îäíîãî áàðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void FormDataForOneBar(int hTicksFile,datetime limitTime,TickStruct &tick,double &lowPrice,int &arraySize,bool &fileClose)
{
//--- Ñ÷èòûâàíèå òèêîâ, ïðèíàäëåæàùèõ îäíîé ñâå÷å
int ticksCount=1;
g_ticksPrice[0]=CastPriceToCluster(tick.bid);
if(!fileClose)
ReadTicksFromFile(hTicksFile,limitTime,tick,ticksCount,fileClose);
if(fileClose) // Ýòî íå îøèáêà - else íå íóæåí, ò. ê. ïîñëå âûïîëíåíèÿ ReadTicksFromFile ìîæåò èçìåíèòüñÿ fileClose
AddDataFromBuffer(limitTime,tick,ticksCount);
//--- Ñîðòèðîâêà ìàññèâà â ïîðÿäêå âîçðàñòàíèÿ. Ïîñëå íåå íóëåâîé ýëåìåíò ñîäåðæèò ìèíèìóì ñâå÷è, à ýëåìåíò [ticksCount - 1] - ìàêñèìóì
ArraySort(g_ticksPrice,ticksCount);
lowPrice=g_ticksPrice[0];
//--- Ðàñïðåäåëåíèå òèêîâ ïî êëàñòåðàì
SortTicksByCluster(ticksCount,arraySize);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå ãîðèçîíòàëüíîé ëèíèè |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå îáúåêòà "Òåêñò" |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îïðåäåëåíèå, êàêîìó èç óêàçàííûõ îáúåìîâ ñîîòâåòñòâóåò ðàññìàòðèâàåìàÿ âåëè÷èíà îáúåìà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå ãèñòîãðàìì îäíîãî áàðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowBarHistogramms(int barIndex,double lowPrice,int arraySize)
{
if(!g_isShowInfo)
return;
for(int i=0; i<arraySize; i+=i_pointsInBox)
{
//--- ßâëÿåòñÿ ëè îáúåì óðîâíÿ äîñòàòî÷íî áîëüøèì?
int volumeLevel=GetVolumeLevel(i);
if(volumeLevel<0)
continue;
//--- Îòîáðàæåíèå îáúåìîâ
double price=lowPrice+i*g_tickSize;
ShowText(i,Time[barIndex],price,IntegerToString(g_volumePriceArray[i]),DoubleToString(price,Digits),g_volumeLevelsColor[volumeLevel].levelColor);
}
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå äàííûõ ïî èñòîðè÷åñêèì áàðàì, íà÷èíàÿ ñ óêàçàííîãî |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessOldCandles(int limit,double &lowPrice,int &arraySize)
{
//--- Îòêðûòèå ôàéëà òèêîâîé èñòîðèè
bool fileClose = false;
int hTicksFile = FileOpen(Symbol() + ".tks", FILE_BIN | FILE_READ | FILE_SHARE_READ | FILE_SHARE_WRITE);
if(hTicksFile<1)
fileClose=true;
//--- Ïîèñê ïåðâîãî òèêà, ïðèíàäëåæàùåãî áàðó limit èëè ëþáîìó áîëåå ïîçäíåìó áàðó
TickStruct tick;
tick.time= Time[limit];
tick.bid = Open[limit];
while(!IsStopped() && !fileClose)
{
if(!IsReadTimeAndBidAskOfTick(hTicksFile,tick))
return;
if(tick.time>=Time[limit])
break;
}
//--- Îòîáðàæåíèå äàííûõ
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);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îáðàçîâàíèå íîâîãî áàðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessNewBarForming(double bid,double &lowPrice,int &arraySize)
{
ArrayInitialize(g_volumePriceArray,0);
arraySize= 1;
lowPrice = bid;
g_volumePriceArray[0]=1;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îáíîâëåíèå ìèíèìóìà òåêóùåé ñâå÷è |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessCandleMinimumUpdate(int priceIndex,double bid,double &lowPrice,int &arraySize)
{
priceIndex = MathAbs(priceIndex);
arraySize += priceIndex;
if(arraySize>MAX_POINTS_IN_CANDLE)
return;
//--- Óâåëè÷åíèå êîëè÷åñòâà çíà÷èìûõ ýëåìåíòîâ ìàññèâà íà priceIndex ýëåìåíòîâ
for(int i=arraySize-1; i>priceIndex-1; i--)
g_volumePriceArray[i]=g_volumePriceArray[i-priceIndex];
//--- Çàïîëíåíèå íóëÿìè ýëåìåíòîâ, ñîîòâåòñòâóþùèõ öåíàì ìåæäó ïðåäûäóùèì ìèíèìóìîì è òåêóùèì
for(int i=priceIndex-1; i>=0; i--)
g_volumePriceArray[i]=0;
g_volumePriceArray[0]=1;
//--- Íîâûé ìèíèìóì
lowPrice=bid;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Çàïèñü äàííûõ î òèêå â ìàññèâ g_ticks |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Äîáàâëåíèå îäíîãî íîâîãî òèêà ê èìåþùåéñÿ ñâå÷å |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessOneTick(int limit,double &lowPrice,int &arraySize)
{
TickStruct tick;
tick.time= TimeCurrent();
tick.ask = Ask;
tick.bid = Bid;
//--- Äîáàâëåíèå îäíîãî òèêà â ìàññèâ õðàíåíèÿ òèêîâ
if(!IsUpdateTicksArray(tick))
{
g_activate=false;
return;
}
double bid=CastPriceToCluster(Bid);
//--- Îáðàçîâàíèå íîâîãî áàðà èëè íà÷àëî ðàáîòû "ñ íóëÿ"
if(limit==1 || lowPrice==0 || arraySize==0)
{
ProcessNewBarForming(bid,lowPrice,arraySize);
return;
}
//--- Åñëè ýêñòðåìóìû ñâå÷è íå îáíîâëåíû, òî ïðîñòî äîáàâëÿåòñÿ îáúåì îäíîìó èç ñóùåñòâóþùèõ óðîâíåé
int priceIndex=(int)MathRound((bid-lowPrice)/g_tickSize); // Èíäåêñ ýëåìåíòà ìàññèâà g_volumePriceArray, êîòîðîìó ñîîòâåòñòâóåò öåíà Bid
if(priceIndex>=0 && priceIndex < arraySize)
{
g_volumePriceArray[priceIndex]++;
return;
}
//--- Îáíîâëåí ìèíèìóì òåêóùåé ñâå÷è. Íóæíî ñäâèíóòü âñå ýëåìåíòû ìàññèâà g_volumePriceArray íà priceIndex ââåðõ
if(IsFirstMoreThanSecond(lowPrice,bid))
{
ProcessCandleMinimumUpdate(priceIndex,bid,lowPrice,arraySize);
return;
}
//--- Îáíîâëåí ìàêñèìóì òåêóùåé ñâå÷è.
if(priceIndex+1>MAX_POINTS_IN_CANDLE)
return;
arraySize=priceIndex+1;
g_volumePriceArray[priceIndex]=1;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå ñåòêè êëàñòåðîâ |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowGrid()
{
if(!g_init)
return;
g_init=false;
if(i_showClusterGrid==NO)
return;
//--- Îïðåäåëåíèå èñòîðè÷åñêèõ ýêñòðåìóìîâ
double highPrice= CastPriceToCluster(High[iHighest(NULL,0,MODE_HIGH)]);
double lowPrice = CastPriceToCluster(Low[iLowest(NULL,0,MODE_LOW)]);
//--- Îòîáðàæåíèå ëèíèé êëàñòåðîâ
for(double price=lowPrice; price<=highPrice; price=NormalizeDouble(price+i_pointsInBox*g_point,Digits))
ShowHLine(price,i_gridColor);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòîáðàæåíèå äàííûõ èíäèêàòîðà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowIndicatorData(int limit,int total)
{
static double lowPrice = 0; // Öåíà, ñîîòâåòñòâóþùàÿ ìèíèìóìó ñâå÷è è íóëåâîìó ýëåìåíòó ìàññèâà g_volumePriceArray. Ïåðâîìó..
// ..ýëåìåíòó áóäåò ñîîòâåòñòâîâàòü öåíà lowPrice + Point è ò.ä.;
static int arraySize = 0; // Êîëè÷åñòâî ýëåìåíòîâ, çàïèñàííûõ â ìàññèâ g_volumePriceArray.  èäåàëå ýòî çíà÷åíèå äîëæíî áûòü..
// ..ðàâíî êîëè÷åñòâó ïóíêòîâ, èç êîòîðûõ ñîñòîèò ñâå÷à. Íî èç-çà ðàçäåëüíîé çàïèñè òèêîâ è..
// ..ðåàëüíîãî ôîðìèðîâàíèÿ ñâå÷åé âîçìîæíû ñäâèãè
if(limit>1) // Âûçîâ ïðîèñõîäèò òîëüêî â ìîìåíò îòîáðàæåíèÿ âñåé èñòîðèè - íà÷àëüíàÿ çàãðóçêà èëè îáíîâëåíèå..
{ // ..áàðîâ ñ èíäåêñîì áîëåå 1
ProcessOldCandles(limit,lowPrice,arraySize);
return;
}
//--- Íîðìàëüíîå îáíîâëåíèå - ïðèõîä íîâîãî òèêà èëè îáðàçîâàíèå íîâîãî áàðà
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) // Åñëè èíäèêàòîð íå ïðîøåë èíèöèàëèçàöèþ, òî ðàáîòàòü îí íå äîëæåí
return rates_total;
ProcessGlobalTick(rates_total,prev_calculated);
return rates_total;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Âûïîëíåíèå îäíîé èòåðàöèè îòîáðàæåíèÿ äàííûõ |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessGlobalTick(const int rates_total,const int prev_calculated)
{
int total;
int limit=GetRecalcIndex(total,rates_total,prev_calculated); // Ñ êàêîãî áàðà íà÷èíàòü îáíîâëåíèå?
ShowInfoViewButton(); // Îòîáðàæåíèå êíîïêè âêë./âûêë. âèçóàëèçàöèè ïîêàçàíèé èíäèêàòîðà
ShowGrid(); // Îòîáðàæåíèå ëèíèé êëàñòåðîâ
ShowIndicatorData(limit, total); // Îòîáðàæåíèå äàííûõ èíäèêàòîðà
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îáðàáîò÷èê ñîáûòèé ÷àðòà |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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;
//--- Âûêëþ÷åíèå êëàñòåðîâ
if(g_isShowInfo)
{
DeleteAllObjects();
ShowButton(BUTTON_XCOORD,BUTTON_YCOORD,"Êëàñòåðû âêë.");
g_isShowInfo=false;
g_init=false;
return;
}
//--- Âêëþ÷åíèå êëàñòåðîâ
g_init=true;
ProcessGlobalTick(Bars,0);
}
//+------------------------------------------------------------------+
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---