194 行
7.2 KiB
MQL5
194 行
7.2 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| CandleCode.mq5 |
|
||
|
|
//| Copyright 2026, MetaQuotes Ltd. |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2026, MetaQuotes Ltd."
|
||
|
|
#property link "https://www.mql5.com"
|
||
|
|
#property version "1.00"
|
||
|
|
#property indicator_separate_window
|
||
|
|
#property indicator_buffers 5
|
||
|
|
#property indicator_plots 2
|
||
|
|
//--- plot Code
|
||
|
|
#property indicator_label1 "Code"
|
||
|
|
#property indicator_type1 DRAW_LINE
|
||
|
|
#property indicator_color1 clrDodgerBlue
|
||
|
|
#property indicator_style1 STYLE_SOLID
|
||
|
|
#property indicator_width1 1
|
||
|
|
//--- plot CodeAvg
|
||
|
|
#property indicator_label2 "CodeAvg"
|
||
|
|
#property indicator_type2 DRAW_LINE
|
||
|
|
#property indicator_color2 clrOrangeRed
|
||
|
|
#property indicator_style2 STYLE_SOLID
|
||
|
|
#property indicator_width2 1
|
||
|
|
|
||
|
|
//--- input parameters
|
||
|
|
input int InpBBLength = 55; // BB Length (Thresholds)
|
||
|
|
input double InpBBNumDevs = 0.5; // BB Deviations
|
||
|
|
input int InpAvgLength = 9; // Average Length (SMA)
|
||
|
|
|
||
|
|
//--- indicator buffers
|
||
|
|
double BufferCCode[]; // Код свечи
|
||
|
|
double BufferCCodeAvg[]; // Среднее кодов свечей
|
||
|
|
double BufferBD[]; // Тело свечи
|
||
|
|
double BufferUS[]; // Верхняя тень
|
||
|
|
double BufferLS[]; // Нижняя тень
|
||
|
|
|
||
|
|
//--- global variables
|
||
|
|
int period_bb;
|
||
|
|
int period_sm;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator initialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
//--- indicator buffers mapping
|
||
|
|
SetIndexBuffer(0,BufferCCode,INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(1,BufferCCodeAvg,INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(2,BufferBD,INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(3,BufferUS,INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(4,BufferLS,INDICATOR_CALCULATIONS);
|
||
|
|
|
||
|
|
//--- Индексация как в таймсериях
|
||
|
|
ArraySetAsSeries(BufferCCode,true);
|
||
|
|
ArraySetAsSeries(BufferCCodeAvg,true);
|
||
|
|
ArraySetAsSeries(BufferBD,true);
|
||
|
|
ArraySetAsSeries(BufferUS,true);
|
||
|
|
ArraySetAsSeries(BufferLS,true);
|
||
|
|
|
||
|
|
//--- Корректировка введённых значений
|
||
|
|
period_bb=(InpBBLength<1 ? 55 : InpBBLength);
|
||
|
|
period_sm=(InpAvgLength<1 ? 9 : InpAvgLength);
|
||
|
|
|
||
|
|
//--- Настройки индикатора
|
||
|
|
IndicatorSetString(INDICATOR_SHORTNAME,StringFormat("CandleCode(%d,%.1f,%d)",period_bb,InpBBNumDevs,period_sm));
|
||
|
|
IndicatorSetInteger(INDICATOR_DIGITS,0);
|
||
|
|
|
||
|
|
//--- Успешно
|
||
|
|
return(INIT_SUCCEEDED);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator iteration function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnCalculate(const int32_t rates_total,
|
||
|
|
const int32_t 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 int32_t &spread[])
|
||
|
|
{
|
||
|
|
//--- Проверка количества доступных баров
|
||
|
|
if(rates_total<period_bb+period_sm)
|
||
|
|
return(0);
|
||
|
|
|
||
|
|
//--- Массивы для расчёта - как таймсерии
|
||
|
|
ArraySetAsSeries(open, true);
|
||
|
|
ArraySetAsSeries(high, true);
|
||
|
|
ArraySetAsSeries(low, true);
|
||
|
|
ArraySetAsSeries(close,true);
|
||
|
|
|
||
|
|
//--- Проверка и расчёт количества просчитываемых баров
|
||
|
|
int limit=rates_total-prev_calculated;
|
||
|
|
|
||
|
|
//--- Если первый запуск или изменения исторических данных
|
||
|
|
if(limit>1)
|
||
|
|
{
|
||
|
|
limit=rates_total-period_bb-1;
|
||
|
|
ArrayInitialize(BufferCCode,0);
|
||
|
|
ArrayInitialize(BufferCCodeAvg,0);
|
||
|
|
ArrayInitialize(BufferBD,0);
|
||
|
|
ArrayInitialize(BufferUS,0);
|
||
|
|
ArrayInitialize(BufferLS,0);
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- Основной цикл
|
||
|
|
for(int i=limit;i>=0;i--)
|
||
|
|
{
|
||
|
|
//--- Верх и низ текущей свечи
|
||
|
|
double hi=fmax(open[i],close[i]);
|
||
|
|
double lo=fmin(open[i],close[i]);
|
||
|
|
|
||
|
|
//--- Записываем в буферы размеры тела, верхней и нижней теней
|
||
|
|
BufferBD[i]=hi-lo;
|
||
|
|
BufferUS[i]=high[i]-hi;
|
||
|
|
BufferLS[i]=lo-low[i];
|
||
|
|
|
||
|
|
//--- Переменные для порогов (Bollinger Bands)
|
||
|
|
double bot_bd=0, top_bd=0, bot_us=0, top_us=0, bot_ls=0, top_ls=0;
|
||
|
|
|
||
|
|
//--- Расчет статистических порогов для каждого элемента свечи
|
||
|
|
CalcBBThresholds(BufferBD,i,period_bb,InpBBNumDevs,bot_bd,top_bd);
|
||
|
|
CalcBBThresholds(BufferUS,i,period_bb,InpBBNumDevs,bot_us,top_us);
|
||
|
|
CalcBBThresholds(BufferLS,i,period_bb,InpBBNumDevs,bot_ls,top_ls);
|
||
|
|
|
||
|
|
int color_code=0, body_code=0, us_code=0, ls_code=0;
|
||
|
|
|
||
|
|
//--- Определение кодов цвета и тела свечи
|
||
|
|
//--- Бычье тело
|
||
|
|
if(close[i]>open[i])
|
||
|
|
{
|
||
|
|
color_code=64;
|
||
|
|
body_code=(BufferBD[i]<bot_bd ? 16 : BufferBD[i]<top_bd ? 32 : 48);
|
||
|
|
}
|
||
|
|
//--- Медвежье тело
|
||
|
|
else if(close[i]<open[i])
|
||
|
|
{
|
||
|
|
color_code=0;
|
||
|
|
body_code=(BufferBD[i]<bot_bd ? 32 : BufferBD[i]<top_bd ? 16 : 0);
|
||
|
|
}
|
||
|
|
//--- Doji (Open == Close)
|
||
|
|
else
|
||
|
|
{
|
||
|
|
color_code=(BufferUS[i]>=BufferLS[i] ? 64 : -64);
|
||
|
|
body_code=0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- Код верхней тени
|
||
|
|
us_code=(BufferUS[i]==0 ? 0 : BufferUS[i]<bot_us ? 4 : BufferUS[i]<top_us ? 8 : 12);
|
||
|
|
|
||
|
|
//--- Код нижней тени
|
||
|
|
ls_code=(BufferLS[i]==0 ? 3 : BufferLS[i]<bot_ls ? 2 : BufferLS[i]<top_ls ? 1 : 0);
|
||
|
|
|
||
|
|
//--- Итоговый код свечи Лиховидова
|
||
|
|
BufferCCode[i]=double(color_code+body_code+us_code+ls_code);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//--- Сглаживание
|
||
|
|
for(int i=limit;i>=0;i--)
|
||
|
|
{
|
||
|
|
double sum=0;
|
||
|
|
for(int j=0;j<period_sm;j++)
|
||
|
|
sum+=BufferCCode[i+j];
|
||
|
|
BufferCCodeAvg[i]=sum/period_sm;
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- return value of prev_calculated for next call
|
||
|
|
return(rates_total);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Расчет пороговых значений на основе Bollinger Bands |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CalcBBThresholds(const double &data[], int pos, int period, double dev, double &bot, double &top)
|
||
|
|
{
|
||
|
|
double sum=0, avg=0, sq_sum=0, std_dev=0;
|
||
|
|
//--- Среднее (SMA)
|
||
|
|
for(int i=0;i<period;i++)
|
||
|
|
sum+=data[pos+i];
|
||
|
|
avg=sum/period;
|
||
|
|
|
||
|
|
//--- Сумма квадратов отклонений для StdDev
|
||
|
|
for(int i=0;i<period;i++)
|
||
|
|
sq_sum+=pow(data[pos+i]-avg,2);
|
||
|
|
std_dev=sqrt(sq_sum/period);
|
||
|
|
|
||
|
|
//--- Расчёт значений BB
|
||
|
|
bot=avg-dev*std_dev;
|
||
|
|
top=avg+dev*std_dev;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|