Читать книгу 10 роботов для автоматической торговли на Форекс (Алексей Дмитриевич Боровков) онлайн бесплатно на Bookz (2-ая страница книги)
10 роботов для автоматической торговли на Форекс
10 роботов для автоматической торговли на Форекс
Оценить:

3

Полная версия:

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 &&

bannerbanner