
Полная версия
10 роботов для автоматической торговли на Форекс
input int Momentum_Period = 3; // Период момента
input double MinTickSpeed = 0.5; // Мин. скорость тиков (тиков/сек)
//+–+
//| Глобальные переменные |
//+–+
int handleFastMA, handleSlowMA, handleMomentum;
double fastMA[], slowMA[], momentum[];
datetime lastTradeTime = 0;
int todayTrades = 0;
datetime lastTradeDate = 0;
double initialEquity = 0;
MqlDateTime currentTime;
int tickCounter = 0;
datetime lastTickTime = 0;
double tickSpeed = 0;
// Структура для хранения информации о новостях
struct NewsEvent
{
datetime time;
string currency;
string event;
int impact; // 0=low, 1=medium, 2=high, 3=very high
};
//+–+
//| Expert initialization function |
//+–+
int OnInit()
{
// Проверка входных параметров
if(LotSize <= 0 || LotSize > 100)
{
Print("Некорректный размер лота!");
return INIT_PARAMETERS_INCORRECT;
}
if(TakeProfit_Pips <= 0 || StopLoss_Pips <= 0)
{
Print("Некорректные уровни TP/SL!");
return INIT_PARAMETERS_INCORRECT;
}
// Инициализация индикаторов
handleFastMA = iMA(_Symbol, PERIOD_M1, FastMA_Period, 0, MA_Method, PRICE_CLOSE);
handleSlowMA = iMA(_Symbol, PERIOD_M1, SlowMA_Period, 0, MA_Method, PRICE_CLOSE);
handleMomentum = iMomentum(_Symbol, PERIOD_M1, Momentum_Period, PRICE_CLOSE);
if(handleFastMA == INVALID_HANDLE || handleSlowMA == INVALID_HANDLE ||
handleMomentum == INVALID_HANDLE)
{
Print("Ошибка создания индикаторов!");
return INIT_FAILED;
}
// Установка массивов как таймсерии
ArraySetAsSeries(fastMA, true);
ArraySetAsSeries(slowMA, true);
ArraySetAsSeries(momentum, true);
// Инициализация начального эквити
initialEquity = AccountInfoDouble(ACCOUNT_EQUITY);
// Сброс счетчика сделок при перезагрузке
ResetDailyTradesCounter();
// Создание таймера для мониторинга скорости тиков
EventSetTimer(1);
return INIT_SUCCEEDED;
}
//+–+
//| Expert deinitialization function |
//+–+
void OnDeinit(const int reason)
{
if(handleFastMA != INVALID_HANDLE) IndicatorRelease(handleFastMA);
if(handleSlowMA != INVALID_HANDLE) IndicatorRelease(handleSlowMA);
if(handleMomentum != INVALID_HANDLE) IndicatorRelease(handleMomentum);
EventKillTimer();
}
//+–+
//| Expert tick function |
//+–+
void OnTick()
{
// Подсчет скорости тиков
tickCounter++;
datetime currentTickTime = TimeCurrent();
if(lastTickTime == 0) lastTickTime = currentTickTime;
// Проверяем ежедневный лимит сделок
CheckDailyTradesLimit();
// Проверяем защиту по эквити
if(UseEquityProtection && !CheckEquityProtection()) return;
// Проверяем фильтр новостей
if(UseNewsFilter && IsNewsTime()) return;
// Проверяем спред
if(!CheckSpread()) return;
// Проверяем скорость тиков
if(!CheckTickSpeed()) return;
// Проверяем наличие открытых позиций
if(PositionSelect(_Symbol)) return;
// Получаем данные индикаторов
if(!UpdateIndicators()) return;
// Получаем тиковые данные
MqlTick lastTick;
if(!SymbolInfoTick(_Symbol, lastTick)) return;
// Получаем данные объемов
long volumeArray[];
ArraySetAsSeries(volumeArray, true);
if(CopyTickVolume(_Symbol, PERIOD_M1, 0, 3, volumeArray) <= 0) return;
// Генерируем сигналы
bool buySignal = GenerateBuySignal(lastTick, volumeArray);
bool sellSignal = GenerateSellSignal(lastTick, volumeArray);
// Открываем позиции
if(buySignal)
{
OpenPosition(ORDER_TYPE_BUY);
}
else if(sellSignal)
{
OpenPosition(ORDER_TYPE_SELL);
}
}
//+–+
//| Timer function для подсчета скорости тиков |
//+–+
void OnTimer()
{
datetime currentTime = TimeCurrent();
double timeDiff = currentTime – lastTickTime;
if(timeDiff > 0)
{
tickSpeed = tickCounter / timeDiff;
tickCounter = 0;
lastTickTime = currentTime;
}
}
//+–+
//| Функция генерации сигнала на покупку |
//+–+
bool GenerateBuySignal(MqlTick &tick, long &volumeArray[])
{
// Сигнал по скользящим средним
bool maSignal = fastMA[0] > slowMA[0] && fastMA[1] <= slowMA[1];
// Сигнал по моменту
bool momentumSignal = momentum[0] > 100 && momentum[1] <= 100;
// Проверка объема
bool volumeSignal = volumeArray[0] > Volume_Threshold;
// Проверка цены (микро-паттерны)
bool pricePattern = CheckBullishMicroPattern();
// Комбинированный сигнал
return (maSignal && momentumSignal && volumeSignal && pricePattern);
}
//+–+
//| Функция генерации сигнала на продажу |
//+–+
bool GenerateSellSignal(MqlTick &tick, long &volumeArray[])
{
// Сигнал по скользящим средним
bool maSignal = fastMA[0] < slowMA[0] && fastMA[1] >= slowMA[1];
// Сигнал по моменту
bool momentumSignal = momentum[0] < 100 && momentum[1] >= 100;
// Проверка объема
bool volumeSignal = volumeArray[0] > Volume_Threshold;
// Проверка цены (микро-паттерны)
bool pricePattern = CheckBearishMicroPattern();
// Комбинированный сигнал
return (maSignal && momentumSignal && volumeSignal && pricePattern);
}
//+–+
//| Проверка бычьего микро-паттерна |
//+–+
bool CheckBullishMicroPattern()
{
// Пример: проверка последовательности из 3 последних тиков
MqlRates rates[];
ArraySetAsSeries(rates, true);
if(CopyRates(_Symbol, PERIOD_M1, 0, 5, rates) < 5) return false;
// Паттерн: снижение-снижение-рост (поглощение)
bool pattern1 = rates[3].close < rates[3].open && // Медвежья свеча
rates[2].close < rates[2].open && // Медвежья свеча
rates[1].close > rates[1].open && // Бычья свеча
rates[1].close > rates[2].close; // Закрытие выше предыдущего закрытия
// Паттерн: молот или доджи после снижения
bool pattern2 = rates[2].close < rates[2].open && // Медвежья свеча
(rates[1].high – rates[1].low) > 3 * (rates[1].close – rates[1].open) && // Длинная тень
rates[1].close > rates[1].open; // Закрытие выше открытия
return pattern1 || pattern2;
}
//+–+
//| Проверка медвежьего микро-паттерна |
//+–+
bool CheckBearishMicroPattern()
{
MqlRates rates[];
ArraySetAsSeries(rates, true);
if(CopyRates(_Symbol, PERIOD_M1, 0, 5, rates) < 5) return false;
// Паттерн: рост-рост-снижение (поглощение)
bool pattern1 = rates[3].close > rates[3].open && // Бычья свеча
rates[2].close > rates[2].open && // Бычья свеча
rates[1].close < rates[1].open && // Медвежья свеча
rates[1].close < rates[2].close; // Закрытие ниже предыдущего закрытия
// Паттерн: повешенный или доджи после роста
bool pattern2 = rates[2].close > rates[2].open && // Бычья свеча
(rates[1].high – rates[1].low) > 3 * (rates[1].open – rates[1].close) && // Длинная тень
rates[1].close < rates[1].open; // Закрытие ниже открытия
return pattern1 || pattern2;
}
//+–+
//| Обновление данных индикаторов |
//+–+
bool UpdateIndicators()
{
if(CopyBuffer(handleFastMA, 0, 0, 3, fastMA) <= 0) return false;
if(CopyBuffer(handleSlowMA, 0, 0, 3, slowMA) <= 0) return false;
if(CopyBuffer(handleMomentum, 0, 0, 3, momentum) <= 0) return false;
return true;
}
//+–+
//| Проверка спреда |
//+–+
bool CheckSpread()
{
MqlTick lastTick;
if(!SymbolInfoTick(_Symbol, lastTick)) return false;
double currentSpread = (lastTick.ask – lastTick.bid) / _Point;
return currentSpread <= MaxSpread_Pips;
}
//+–+
//| Проверка скорости тиков |
//+–+
bool CheckTickSpeed()
{
return tickSpeed >= MinTickSpeed;
}
//+–+
//| Проверка времени новостей |
//+–+
bool IsNewsTime()
{
// В реальной реализации здесь должен быть доступ к календарю новостей
// Это примерная заглушка
TimeToStruct(TimeCurrent(), currentTime);
// Пример: не торговать в 8:30-9:00 и 13:30-14:00 (важные релизы)
bool newsTime1 = (currentTime.hour == 8 && currentTime.min >= 30) ||
(currentTime.hour == 9 && currentTime.min == 0);
bool newsTime2 = (currentTime.hour == 13 && currentTime.min >= 30) ||
(currentTime.hour == 14 && currentTime.min == 0);
return newsTime1 || newsTime2;
}
//+–+
//| Проверка защиты по эквити |
//+–+
bool CheckEquityProtection()
{
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double drawdownPercent = ((initialEquity – currentEquity) / initialEquity) * 100;
return drawdownPercent < EquityProtectionPercent;
}
//+–+
//| Проверка дневного лимита сделок |
//+–+
void CheckDailyTradesLimit()
{
datetime currentDate = TimeCurrent();
MqlDateTime dateStruct;
TimeToStruct(currentDate, dateStruct);
// Если день сменился, сбрасываем счетчик
if(lastTradeDate != dateStruct.day)
{
todayTrades = 0;
lastTradeDate = dateStruct.day;
}
}
//+–+
//| Сброс счетчика дневных сделок |
//+–+
void ResetDailyTradesCounter()
{
datetime currentDate = TimeCurrent();
MqlDateTime dateStruct;
TimeToStruct(currentDate, dateStruct);
todayTrades = 0;
lastTradeDate = dateStruct.day;
}
//+–+
//| Открытие позиции |
//+–+
void OpenPosition(ENUM_ORDER_TYPE orderType)
{
// Проверяем лимит сделок
if(todayTrades >= MaxDailyTrades) return;
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = LotSize;
request.type = orderType;
request.type_filling = ORDER_FILLING_IOC; // Немедленное исполнение или отмена
request.deviation = 1; // Минимальное отклонение
request.magic = MagicNumber;
// Установка цен
MqlTick lastTick;
SymbolInfoTick(_Symbol, lastTick);
if(orderType == ORDER_TYPE_BUY)
{
request.price = lastTick.ask;
request.sl = request.price – StopLoss_Pips * _Point;
request.tp = request.price + TakeProfit_Pips * _Point;
}
else // ORDER_TYPE_SELL
{
request.price = lastTick.bid;
request.sl = request.price + StopLoss_Pips * _Point;
request.tp = request.price – TakeProfit_Pips * _Point;
}
// Отправка ордера
if(!OrderSend(request, result))
{
Print("Ошибка открытия позиции: ", GetLastError());
}
else
{
todayTrades++;
Print("Позиция открыта. Сегодня сделок: ", todayTrades);
}
}
//+–+
//| Функция закрытия всех позиций |
//+–+
void CloseAllPositions()
{
for(int i = PositionsTotal()-1; i >= 0; i–)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = _Symbol;
request.volume = PositionGetDouble(POSITION_VOLUME);
request.deviation = 1;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
request.type = ORDER_TYPE_SELL;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
}
else
{
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
}
OrderSend(request, result);
}
}
}
}
```
Дополнительные функции для реального скальпинга:
```mq5
//+–+
//| Функция мониторинга стакана цен (упрощенная) |
//+–+
void MonitorMarketDepth()
{
// В MT5 нет прямого доступа к Level II, но можно использовать
// символьные свойства для получения информации о спросе/предложении
MqlTick lastTick;
SymbolInfoTick(_Symbol, lastTick);
// Можно добавить логику анализа объема на текущих ценах
// Например, отслеживать крупные лимитные ордера
}
//+–+
//| Функция анализа кластеров объемов |
//+–+
void AnalyzeVolumeClusters()
{
// Использование индикатора Volume Profile или Cluster Charts
// для определения уровней с максимальным объемом
}
//+–+
//| Функция для работы со стаканом заявок (требует специальных API) |
//+–+
void ProcessMarketDepth()
{
// Для реального доступа к Level II потребуется:
// 1. API от брокера с доступом к стакану
// 2. Специальные библиотеки или плагины
// 3. Прямое подключение к биржевым данным
}
```
Ключевые особенности скальпера:
1. Сверхбыстрая торговля:
· Использование тиковых данных
· Мгновенное исполнение (IOC)
· Минимальные уровни TP/SL (5-15 пунктов)
2. Система защиты:
· Ограничение по количеству сделок в день
· Защита по эквити
· Фильтр по спреду
· Фильтр новостей
3. Мониторинг качества соединения:
· Контроль скорости тиков
· Проверка стабильности подключения
4. Анализ микро-паттернов:
· Свечные паттерны на M1
· Анализ объемов
· Мониторинг момента
Требования для работы скальпера:
1. Технические:
· VPS с низкой задержкой (менее 1 мс к серверу)
· Выделенный канал связи
· Стабильное электропитание
2. Торговые условия:
· ECN счет с сырыми спредами
· Минимальная комиссия
· Разрешение на скальпинг
3. Рыночные условия:
· Высокая ликвидность (мажорные пары)
· Низкая волатильность в азиатскую сессию
· Отсутствие важных новостей
Важно: Скальпинг – это высокочастотная торговля с высокими рисками. Тестируйте стратегию на демо-счете не менее 3 месяцев перед использованием на реальные деньги. Начните с минимального лота и постепенно увеличивайте объемы при стабильной прибыльности.
Робот 4: «Гармоничный паттерн» (Harmonic Pattern Scanner)
Гармоничный паттерн (Harmonic Pattern Scanner) для MetaTrader 5
```mq5
//+–+
//| HarmonicPatternScanner.mq5 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+–+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//+–+
//| Входные параметры эксперта |
//+–+
input double LotSize = 0.1; // Размер лота
input int StopLoss_Points = 200; // Стоп-лосс в пунктах
input int TakeProfit_Points = 400; // Тейк-профит в пунктах
input int MagicNumber = 112233; // Магический номер
input double FiboTolerance = 0.05; // Допуск для уровней Фибо (5%)
input int MinPatternBars = 20; // Минимум баров в паттерне
input int MaxPatternBars = 300; // Максимум баров в паттерне
input bool ShowPatternLines = true; // Показывать линии паттернов
input color PatternColor = clrBlue; // Цвет линий паттернов
//+–+
//| Перечисление типов паттернов |
//+–+
enum PATTERN_TYPE
{
PATTERN_NONE = 0,
PATTERN_GARTLEY = 1,
PATTERN_BUTTERFLY = 2,
PATTERN_CRAB = 3,
PATTERN_BAT = 4,
PATTERN_SHARK = 5,
PATTERN_CYPHER = 6
};
//+–+
//| Структура для хранения точек паттерна |
//+–+
struct PatternPoints
{
double X, A, B, C, D;
datetime timeX, timeA, timeB, timeC, timeD;
PATTERN_TYPE type;
int direction; // 1 – бычий, -1 – медвежий
};
//+–+
//| Глобальные переменные |
//+–+
PatternPoints lastPattern;
bool patternFound = false;
int lastPatternBar = 0;
int zigzagHandle;
double zigzagBuffer[];
datetime timeBuffer[];
double highBuffer[], lowBuffer[];
int lastCalculated = 0;
//+–+
//| Expert initialization function |
//+–+
int OnInit()
{
// Проверка входных параметров
if(LotSize <= 0 || LotSize > 100)
{
Print("Некорректный размер лота!");
return INIT_PARAMETERS_INCORRECT;
}
// Создание индикатора ZigZag для поиска экстремумов
zigzagHandle = iCustom(_Symbol, _Period, "Examples\\ZigZag.ex5", 12, 5, 3);
if(zigzagHandle == INVALID_HANDLE)
{
Print("Ошибка создания индикатора ZigZag!");
return INIT_FAILED;
}
// Настройка массивов
ArraySetAsSeries(zigzagBuffer, true);
ArraySetAsSeries(timeBuffer, true);
ArraySetAsSeries(highBuffer, true);
ArraySetAsSeries(lowBuffer, true);
return INIT_SUCCEEDED;
}
//+–+
//| Expert deinitialization function |
//+–+
void OnDeinit(const int reason)
{
if(zigzagHandle != INVALID_HANDLE) IndicatorRelease(zigzagHandle);
DeletePatternLines();
}
//+–+
//| Expert tick function |
//+–+
void OnTick()
{
// Проверяем наличие открытых позиций по этому символу и магику
if(PositionSelect(_Symbol)) return;
// Получаем текущее время бара
datetime currentTime = iTime(_Symbol, _Period, 0);
// Ищем паттерны каждые N баров или при смене дня
static datetime lastScanTime = 0;
if(currentTime – lastScanTime < 3600) return; // Сканируем раз в час
// Обновляем данные ZigZag
if(!UpdateZigZagData()) return;
// Ищем гармонические паттерны
PatternPoints foundPattern = ScanForPatterns();
if(foundPattern.type != PATTERN_NONE)
{
patternFound = true;
lastPattern = foundPattern;
lastPatternBar = iBarShift(_Symbol, _Period, currentTime);
// Отображаем паттерн на графике
if(ShowPatternLines) DrawPattern(foundPattern);
// Открываем сделку в точке D
OpenPatternTrade(foundPattern);
lastScanTime = currentTime;
}
}
//+–+
//| Обновление данных ZigZag |
//+–+
bool UpdateZigZagData()
{
// Копируем данные ZigZag
if(CopyBuffer(zigzagHandle, 0, 0, 500, zigzagBuffer) <= 0)
{
Print("Ошибка копирования данных ZigZag!");
return false;
}
// Копируем временные метки
if(CopyTime(_Symbol, _Period, 0, 500, timeBuffer) <= 0) return false;
// Копируем High и Low
if(CopyHigh(_Symbol, _Period, 0, 500, highBuffer) <= 0) return false;
if(CopyLow(_Symbol, _Period, 0, 500, lowBuffer) <= 0) return false;
return true;
}
//+–+
//| Поиск гармонических паттернов |
//+–+
PatternPoints ScanForPatterns()
{
PatternPoints result;
result.type = PATTERN_NONE;
// Собираем экстремумы из ZigZag
double extremes[];
datetime extremeTimes[];
int extremeBars[];
CollectExtremes(extremes, extremeTimes, extremeBars);
int extremeCount = ArraySize(extremes);
if(extremeCount < 5) return result;
// Ищем паттерны среди экстремумов
for(int i = 4; i < extremeCount; i++)
{
// Проверяем XABCD паттерны
for(int x = i-4; x <= i-4; x++)
for(int a = x+1; a <= i-3; a++)
for(int b = a+1; b <= i-2; b++)
for(int c = b+1; c <= i-1; c++)
for(int d = c+1; d <= i; d++)
{
// Проверяем временные рамки паттерна
int patternBars = extremeBars[d] – extremeBars[x];
if(patternBars < MinPatternBars || patternBars > MaxPatternBars) continue;
// Проверяем бычий паттерн (X – low, A – high, B – low, C – high, D – low)
if(extremes[x] < extremes[a] && extremes[a] > extremes[b] &&
extremes[b] < extremes[c] && extremes[c] > extremes[d])
{
PatternPoints bullPattern;
bullPattern.X = extremes[x];
bullPattern.A = extremes[a];
bullPattern.B = extremes[b];
bullPattern.C = extremes[c];
bullPattern.D = extremes[d];
bullPattern.timeX = extremeTimes[x];
bullPattern.timeA = extremeTimes[a];
bullPattern.timeB = extremeTimes[b];
bullPattern.timeC = extremeTimes[c];
bullPattern.timeD = extremeTimes[d];
bullPattern.direction = 1;
// Проверяем тип паттерна
bullPattern.type = CheckPatternType(bullPattern);
if(bullPattern.type != PATTERN_NONE)
{
// Проверяем, что точка D – последняя (или почти последняя)
int barsSinceD = iBarShift(_Symbol, _Period, extremeTimes[d]);
if(barsSinceD <= 3) // Паттерн свежий
{
return bullPattern;
}
}
}
// Проверяем медвежий паттерн (X – high, A – low, B – high, C – low, D – high)
if(extremes[x] > extremes[a] && extremes[a] < extremes[b] &&
extremes[b] > extremes[c] && extremes[c] < extremes[d])
{
PatternPoints bearPattern;
bearPattern.X = extremes[x];
bearPattern.A = extremes[a];
bearPattern.B = extremes[b];
bearPattern.C = extremes[c];
bearPattern.D = extremes[d];
bearPattern.timeX = extremeTimes[x];
bearPattern.timeA = extremeTimes[a];
bearPattern.timeB = extremeTimes[b];
bearPattern.timeC = extremeTimes[c];
bearPattern.timeD = extremeTimes[d];
bearPattern.direction = -1;
// Проверяем тип паттерна
bearPattern.type = CheckPatternType(bearPattern);
if(bearPattern.type != PATTERN_NONE)
{
// Проверяем, что точка D – последняя (или почти последшая)
int barsSinceD = iBarShift(_Symbol, _Period, extremeTimes[d]);
if(barsSinceD <= 3) // Паттерн свежий
{
return bearPattern;
}
}
}
}
}
return result;
}
//+–+
//| Сбор экстремумов из ZigZag |
//+–+
void CollectExtremes(double &extremes[], datetime ×[], int &bars[])
{
ArrayResize(extremes, 0);
ArrayResize(times, 0);
ArrayResize(bars, 0);
for(int i = 100; i >= 0; i–)
{
if(zigzagBuffer[i] != 0 && zigzagBuffer[i] != EMPTY_VALUE)
{
int size = ArraySize(extremes);
ArrayResize(extremes, size + 1);
ArrayResize(times, size + 1);
ArrayResize(bars, size + 1);
extremes[size] = zigzagBuffer[i];
times[size] = timeBuffer[i];
bars[size] = i;
}
}
// Ограничиваем количество экстремумов
int count = ArraySize(extremes);
if(count > 20)
{
ArrayResize(extremes, 20);
ArrayResize(times, 20);
ArrayResize(bars, 20);
}
}
//+–+
//| Проверка типа паттерна |
//+–+
PATTERN_TYPE CheckPatternType(const PatternPoints &pattern)
{
// Вычисляем соотношения Фибоначчи
double XA = MathAbs(pattern.A – pattern.X);
double AB = MathAbs(pattern.B – pattern.A);
double BC = MathAbs(pattern.C – pattern.B);
double CD = MathAbs(pattern.D – pattern.C);
// Отношения
double AB_XA = (XA != 0) ? AB / XA : 0;
double BC_AB = (AB != 0) ? BC / AB : 0;
double CD_BC = (BC != 0) ? CD / BC : 0;
double XC_XA = (XA != 0) ? MathAbs(pattern.C – pattern.X) / XA : 0;
double XD_XA = (XA != 0) ? MathAbs(pattern.D – pattern.X) / XA : 0;
// Уровни Фибоначчи
double fib_0382 = 0.382;
double fib_0500 = 0.5;
double fib_0618 = 0.618;
double fib_0707 = 0.707;
double fib_0786 = 0.786;
double fib_0886 = 0.886;
double fib_1130 = 1.13;
double fib_1272 = 1.272;
double fib_1414 = 1.414;
double fib_1618 = 1.618;
double fib_2000 = 2.0;
double fib_2240 = 2.24;
double fib_2618 = 2.618;
// Проверяем паттерн Гартли (Gartley)
// AB = 0.618 XA, BC = 0.382-0.886 AB, CD = 1.272-1.618 BC, XD = 0.786 XA
if(MathAbs(AB_XA – fib_0618) < FiboTolerance &&









