← К каталогу
Исходный код · ID 4474

regressionchannelbreakoutscanner.mq5

Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Данный индикатор для MetaTrader 5 выполняет сканирование пробоев регрессионных каналов по множеству торговых символов. Для каждого символа рассчитывается линейная регрессия по ценам закрытия за заданное количество баров, а ширина канала определяется на основе среднего истинного диапазона (ATR) и множителя. Текущая цена сравнивается с границами канала с учётом порогового смещения, и определяется наличие пробоя вверх или вниз.

Результаты отображаются в таблице на графике: для каждого символа показывается название и тип сигнала — от сильного восходящего пробоя до сильного нисходящего. Для текущего символа на графике дополнительно рисуются стрелки и текстовые метки. Канал регрессии для текущего инструмента отображается в виде трендовых линий.

Сканирование запускается при инициализации и далее выполняется периодически по таймеру с настраиваемым интервалом обновления. Пользователь может выбрать таймфрейм анализа, количество анализируемых баров, число отображаемых символов и цвета сигналов. Доступен режим отладочного логирования и выбор между отображением всех символов из Market Watch или только текущего графика.

Настройки программы

НастройкаОписание
BarsToAnalyze Количество баров, используемых для расчёта регрессии
BreakoutThreshold Дополнительное расстояние в пунктах символа для определения пробоя
MaxSymbolsToShow Максимальное количество строк в таблице символов
BullishColor Цвет сигнала бычьего направления
BearishColor Цвет сигнала медвежьего направления
NeutralColor Цвет сигнала при отсутствии пробоя
ShowAllSymbols Отображение всех символов из Market Watch или только символ текущего графика
EnableDebugLog Включение диагностического логирования в окно экспертов
ScanTimeframe Таймфрейм, используемый для сканирования
AtrPeriod Период расчёта среднего истинного диапазона
AtrMultiplier Множитель для расчёта ширины канала на основе ATR
UpdateIntervalSecs Интервал обновления сканирования в секундах
Получить полный код

Поиск по коду файла

#property version   "2.00"
#property strict
#property indicator_chart_window
#property indicator_plots 0

input int             BarsToAnalyze       = 100;       // Bars used by regression
input double          BreakoutThreshold   = 0.0010;    // Extra distance, in symbol points
input int             MaxSymbolsToShow    = 20;        // Maximum table rows
input color           BullishColor        = clrGreen;  // Bullish signal color
input color           BearishColor        = clrRed;    // Bearish signal color
input color           NeutralColor        = clrGray;   // Neutral signal color
input bool            ShowAllSymbols      = true;      // Market Watch symbols, otherwise chart symbol
input bool            EnableDebugLog      = true;      // Enable diagnostic log
input ENUM_TIMEFRAMES ScanTimeframe       = PERIOD_H1; // Timeframe used by scanner
input int             AtrPeriod           = 14;        // ATR period
input double          AtrMultiplier       = 1.5;       // ATR channel-width multiplier
input int             UpdateIntervalSecs  = 10;        // Refresh interval in seconds

const string SCANNER_PREFIX = "REGRESSION_SCANNER_";
const string CHANNEL_PREFIX = "REGRESSION_CHANNEL_";
const string SIGNAL_PREFIX  = "REGRESSION_BREAKOUT_";

string   g_symbols[];
int      g_total_symbols = 0;
datetime g_last_update   = 0;
bool     g_updating      = false;

struct RegressionChannelData
{
   double slope;
   double intercept;
   double width;
   double upper;
   double middle;
   double lower;
   double current_close;
   datetime current_time;
};

int OnInit()
{
      // код доступен только после оплаты
   }

void OnDeinit(const int reason)
{
   EventKillTimer();
   ObjectsDeleteAll(0, SCANNER_PREFIX);
   ObjectsDeleteAll(0, CHANNEL_PREFIX);
   ObjectsDeleteAll(0, SIGNAL_PREFIX);
   ChartRedraw(0);
}

void OnTimer()
{
   UpdateSignals();
}

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[])
{
      // код доступен только после оплаты
   }

void BuildSymbolList()
{
   if(!ShowAllSymbols)
   {
      g_total_symbols = 1;
      ArrayResize(g_symbols, 1);
      g_symbols[0] = _Symbol;
      return;
   }

   g_total_symbols = SymbolsTotal(true);
   if(g_total_symbols <= 0)
   {
      g_total_symbols = 1;
      ArrayResize(g_symbols, 1);
      g_symbols[0] = _Symbol;
      return;
   }

   ArrayResize(g_symbols, g_total_symbols);
   for(int i = 0; i < g_total_symbols; i++)
      g_symbols[i] = SymbolName(i, true);

   for(int i = 0; i < g_total_symbols; i++)
   {
      if(g_symbols[i] == _Symbol)
      {
         string first = g_symbols[0];
         g_symbols[0] = g_symbols[i];
         g_symbols[i] = first;
         break;
      }
   }
}

bool CalculateRegressionChannel(const string symbol,
                                const ENUM_TIMEFRAMES timeframe,
                                const int bars,
                                RegressionChannelData &data)
{
   int base_count = (bars > AtrPeriod ? bars : AtrPeriod);
   int required   = base_count + 1; // extra bar supplies previous close for true range

   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   ResetLastError();
   int copied = CopyRates(symbol, timeframe, 0, required, rates);
   if(copied < required)
   {
      if(EnableDebugLog)
         PrintFormat("%s: insufficient %s data (%d/%d), error=%d",
                     symbol, EnumToString(timeframe), copied, required, GetLastError());
      return false;
   }

   double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_xx = 0.0;
   for(int x = 0; x < bars; x++)
   {
      int series_index = bars - 1 - x;
      double price = rates[series_index].close;
      sum_x  += x;
      sum_y  += price;
      sum_xy += x * price;
      sum_xx += x * x;
   }

   double n = (double)bars;
   double denominator = n * sum_xx - sum_x * sum_x;
   if(MathAbs(denominator) <= DBL_EPSILON)
      return false;

   data.slope     = (n * sum_xy - sum_x * sum_y) / denominator;
   data.intercept = (sum_y - data.slope * sum_x) / n;
   data.middle    = data.intercept + data.slope * (bars - 1);

   double tr_sum = 0.0;
   for(int i = 0; i < AtrPeriod; i++)
   {
      double previous_close = rates[i + 1].close;
      double range_1 = rates[i].high - rates[i].low;
      double range_2 = MathAbs(rates[i].high - previous_close);
      double range_3 = MathAbs(rates[i].low  - previous_close);
      tr_sum += MathMax(range_1, MathMax(range_2, range_3));
   }

   data.width         = (tr_sum / AtrPeriod) * AtrMultiplier;
   data.upper         = data.middle + data.width;
   data.lower         = data.middle - data.width;
   data.current_close = rates[0].close;
   data.current_time  = rates[0].time;
   return true;
}

int CheckRegressionChannelBreakout(const string symbol,
                                   const ENUM_TIMEFRAMES timeframe,
                                   const int bars,
                                   RegressionChannelData &data)
{
   if(!CalculateRegressionChannel(symbol, timeframe, bars, data))
      return 0;

   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   if(point <= 0.0)
      return 0;

   double threshold = BreakoutThreshold * point;
   int direction = (data.slope > 0.0 ? 1 : (data.slope < 0.0 ? -1 : 0));

   if(EnableDebugLog)
   {
      int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
      Print(symbol, " regression: slope=", DoubleToString(data.slope, 10),
            " dir=", direction,
            " upper=", DoubleToString(data.upper, digits),
            " middle=", DoubleToString(data.middle, digits),
            " lower=", DoubleToString(data.lower, digits),
            " close=", DoubleToString(data.current_close, digits));
   }

   if(direction > 0)
   {
      if(data.current_close > data.upper + threshold)  return 2;
      if(data.current_close > data.middle + threshold) return 1;
      if(data.current_close < data.lower - threshold)  return -1;
   }
   else if(direction < 0)
   {

      if(data.current_close > data.upper + threshold)  return 1;
      if(data.current_close < data.lower - threshold)  return -2;
      if(data.current_close < data.middle - threshold) return -1;
   }
   else
   {
      if(data.current_close > data.upper + threshold) return 1;
      if(data.current_close < data.lower - threshold) return -1;
   }

   return 0;
}

void UpdateSignals()
{
   if(g_updating)
      return;
   g_updating = true;

   if(ObjectFind(0, SCANNER_PREFIX + "BG") < 0)
      CreateTableHeader();

   DeleteObjectsByPrefix(SCANNER_PREFIX + "ROW_");
   DrawRegressionChannel(BarsToAnalyze, clrRed, clrGray, 2);

   int rows = 0;
   for(int i = 0; i < g_total_symbols && rows < MaxSymbolsToShow; i++)
   {
      string symbol = g_symbols[i];
      if(symbol == "")
         continue;

      MqlTick tick;
      ResetLastError();
      if(!SymbolInfoTick(symbol, tick) || tick.bid <= 0.0 || tick.ask <= 0.0)
      {
         if(EnableDebugLog)
            PrintFormat("%s: no valid tick, error=%d", symb

Показано первые 50% кода (символов: 11275)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
1 127,50₽ ≈ $13.78