regressionchannelbreakoutscanner.mq5
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «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? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.