Article-21319-MQL5-CandleCo.../CandleCode.mq5

194 行
7.2 KiB
MQL5
Raw パーマリンク 通常表示 履歴

2026-03-24 22:08:50 +07:00
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+