Обсуждение статьи "Методы Уильяма Ганна (Часть I): Создаем индикатор углов Ганна" - страница 2

 
Vitaly Muzichenko #:

Если вы прошли курсы и не получилось - а оно и не получится что и логично, вам скажут что не правильно сопоставляете звёзды между планетами.   

Вы упустили один момент!  Кто разобрался как торговал Ганн, не будет никого учить. Поэтому все курсы от инфоцыган сплошная липа.

 
Bogard_11 #:

Вы упустили один момент!  Кто разобрался как торговал Ганн, не будет никого учить. Поэтому все курсы от инфоцыган сплошная липа.

Истину глаголите, Уважаемый :-)
 
Ганн был гениальный трейдер, и астролог, и нумеролог, математик, который верил в магические числа. Великий предсказатель, который предсказал начало и окончание первой и второй мировых войн. Имел огромное количество учеников, но как утверждают его последователи, полностью свою стратегию никому не передал. Имел огромные обороты денежных средств, а к концу жизни пришел со скромной суммой в 100000$. С нетерпением буду ждать следующие статьи про гениальную личность Ганна, очень интересно.


  
 
Eva-oren #:
Ганн был гениальный трейдер, и астролог, и нумеролог, математик, который верил в магические числа. Великий предсказатель, который предсказал начало и окончание первой и второй мировых войн. Имел огромное количество учеников, но как утверждают его последователи, полностью свою стратегию никому не передал. Имел огромные обороты денежных средств, а к концу жизни пришел со скромной суммой в 100000$. С нетерпением буду ждать следующие статьи про гениальную личность Ганна, очень интересно.

Забыли упомянуть, он имел частный самолет, что в те времена была большая редкость. Плюс 100.000$ тогда, это как минимум мульт зелени сейчас, если не 10 мультов.

P.S. - стратегию он передал. В своих трудах. Кто захотел, собрал из разных глав полную ТС. Ганн спецом всё разбросал, чтобы на шару никому не досталось.

 
Нашёл в гугле способ торговли

 
Ivan Butko #:
Нашёл в гугле способ торговли

во второй картинке - не уловил принцип :-(

 

Кину картинку. Кто понял Ганна, сразу поймет принцип работы с углами, где ищем вход в лонг и где переворачиваемся.


 
Оговорка: я не знаю синтаксиса программирования индикаторов на MQL5.

Но мне кажется, что алгоритм угловой линии не правильный (см. прикрепленный индикатор угловой линии, который я написал в другой программе), вот мой диалог с DeepSeek:

下面代码是通达信的代码,里面计算斜率的方法才是正确的,请阅读理解后,把上面priceShift 的计算方法改为下列代码正确的范式:

涨周期数:= IF(低点k位置 > 高点k位置, 低点k位置 - 高点k位置 + 1, 低点k位置), NODRAW;
跌周期数:= IF(高点k位置 > 低点k位置, 高点k位置 - 低点k位置 + 1, 高点k位置), NODRAW;

天线:= CONST(IF(高点k位置 = 1, H, REF(H, 高点k位置 - 1))), NODRAW;
地线:= CONST(IF(低点k位置 = 1, L, REF(L, 低点k位置 - 1))), NODRAW;

上涨天数:= IF(ISVALID(地线), BARSLAST(L = 地线), DRAWNULL), NODRAW;
下跌天数:= IF(ISVALID(天线), BARSLAST(H = 天线), DRAWNULL), NODRAW;

上涨高度:= IF(低点k位置 > 高点k位置, 天线 - 地线, HHV(H, 上涨天数) - 地线), NODRAW;
下跌高度:= IF(高点k位置 > 低点k位置, 天线 - 地线, 天线 - LLV(L, 下跌天数)), NODRAW;

上涨斜率:= IF(上涨天数 > 0, ROUND2(上涨高度 / 涨周期数, 4), 0), NODRAW;
下跌斜率:= IF(下跌天数 > 0, ROUND2(下跌高度 / 跌周期数, 4), 0), NODRAW;

Однако DeepSeek дал мне код модификации, который, похоже, мне не подошел:
.
//+------------------------------------------------------------------+
//| Построение линии сектора Венна & nbsp; |
//+------------------------------------------------------------------+
void DrawGannFan(double extremum, datetime extremumTime)
{
    // Определите угол Ганна и соответствующее имя.
    double angles[] = {82.5, 75, 71.25, 63.75, 45, 26.25, 18.75, 15, 7.5};
    string angleNames[] = {"1x8", "1x4", "1x3", "1x2", "1x1", "2x1", "3x1", "4x1", "8x1"};

    // Получите количество периодов от крайней точки до текущей K-линии
    int extremumBar = iBarShift(_Symbol, PERIOD_CURRENT, extremumTime);
    int currentBar = 0; // Текущая K-линия равна 0
    int barDiff = currentBar - extremumBar; // Разница в номерах циклов
    
    // Вычислите разницу в высоте цены
    double priceDiff;
    if(isTrendUp)
    {
        // Восходящий тренд: рассчитывает высоту от экстремального минимума до текущей максимальной цены
        double currentHigh = iHigh(_Symbol, PERIOD_CURRENT, 0);
        priceDiff = currentHigh - extremum;
    }
    else
    {
        // Нисходящий тренд: рассчитывает высоту от крайнего максимума до текущей низкой цены
        double currentLow = iLow(_Symbol, PERIOD_CURRENT, 0);
        priceDiff = extremum - currentLow;
    }
    
    // Вычислите базовый наклон (наклон линии 1x1)
    double baseSlope = (barDiff > 0) ? priceDiff / barDiff : 0;
    
    // Нарисуйте линии секторов для каждого угла
    for(int i = 0; i < ArraySize(angles); i++)
    {
        string label = "GannFan_" + angleNames[i];  // Метки объектов
        double angle = angles[i];                  // Текущий угол
        
        // Вычислите множитель наклона на основе угла
        double slopeMultiplier = MathTan(angle * M_PI / 180.0) / MathTan(45 * M_PI / 180.0);
        
        // Рассчитайте смещение цены (на основе базового уклона и углового множителя)
        double priceShift = baseSlope * barDiff * slopeMultiplier * _Point;
        double endPrice;
        
        // Расчет цены закрытия на основе направления тренда
        if(isTrendUp)
        {
            endPrice = extremum + priceShift;
        }
        else
        {
            endPrice = extremum - priceShift;
            angle = -angle; // Угол разворота в нисходящем тренде
        }

        // Создайте объект линии тренда
        if(ObjectCreate(0, label, OBJ_TREND, 0, extremumTime, extremum, TimeCurrent(), endPrice))
        {
            // Установите свойства линии тренда
            ObjectSetInteger(0, label, OBJPROP_COLOR, GannFanColor);
            ObjectSetInteger(0, label, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, label, OBJPROP_WIDTH, 1);
            ObjectSetInteger(0, label, OBJPROP_RAY_RIGHT, true);
            ObjectSetString(0, label, OBJPROP_TOOLTIP, "Gann Fan " + angleNames[i]);
        }
        else
        {
            Print("Failed to create Gann Fan line: ", GetLastError());
        }
    }
}

//+------------------------------------------------------------------+
//|| Построение обратной веерной линии Ганна & nbsp; &nbsp ; ||
//+------------------------------------------------------------------+
void DrawOppositeGannFan(double extremum, datetime extremumTime)
{
    // Определите угол Ганна и соответствующее имя.
    double angles[] = {82.5, 75, 71.25, 63.75, 45, 26.25, 18.75, 15, 7.5};
    string angleNames[] = {"1x8", "1x4", "1x3", "1x2", "1x1", "2x1", "3x1", "4x1", "8x1"};

    // Получите количество периодов от крайней точки до текущей K-линии
    int extremumBar = iBarShift(_Symbol, PERIOD_CURRENT, extremumTime);
    int currentBar = 0; // Текущая K-линия равна 0
    int barDiff = currentBar - extremumBar; // Разница в номерах циклов
    
    // Вычислите разницу в высоте цены
    double priceDiff;
    if(!isTrendUp)
    {
        // Обратный тренд (вверх): рассчитывается высота от крайнего минимума до текущей максимальной цены
        double currentHigh = iHigh(_Symbol, PERIOD_CURRENT, 0);
        priceDiff = currentHigh - extremum;
    }
    else
    {
        // Обратный тренд (нисходящий): рассчитывается высота от крайнего максимума до текущей низкой цены
        double currentLow = iLow(_Symbol, PERIOD_CURRENT, 0);
        priceDiff = extremum - currentLow;
    }
    
    // Вычислите базовый наклон (наклон линии 1x1)
    double baseSlope = (barDiff > 0) ? priceDiff / barDiff : 0;
    
    // Нарисуйте линии секторов для каждого угла
    for(int i = 0; i < ArraySize(angles); i++)
    {
        string label = "OppositeGannFan_" + angleNames[i];  // Метки объектов
        double angle = angles[i];                          // Текущий угол
        
        // Вычислите множитель наклона на основе угла
        double slopeMultiplier = MathTan(angle * M_PI / 180.0) / MathTan(45 * M_PI / 180.0);
        
        // Рассчитайте смещение цены (на основе базового уклона и углового множителя)
        double priceShift = baseSlope * barDiff * slopeMultiplier * _Point;
        double endPrice;
        
        // Расчет цены закрытия на основе направления обратного тренда
        if(!isTrendUp)
        {
            endPrice = extremum + priceShift;
        }
        else
        {
            endPrice = extremum - priceShift;
            angle = -angle; // Угол разворота в нисходящем тренде
        }

        // Создайте объект линии тренда
        if(ObjectCreate(0, label, OBJ_TREND, 0, extremumTime, extremum, TimeCurrent(), endPrice))
        {
            // Установите свойства линии тренда
            ObjectSetInteger(0, label, OBJPROP_COLOR, GannFanColor);
            ObjectSetInteger(0, label, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, label, OBJPROP_WIDTH, 1);
            ObjectSetInteger(0, label, OBJPROP_RAY_RIGHT, true);
            ObjectSetString(0, label, OBJPROP_TOOLTIP, "Opposite Gann Fan " + angleNames[i]);
        }
        else
        {
            Print("Failed to create Opposite Gann Fan line: ", GetLastError());
        }
    }
}





В итоге мне пришлось попросить DeepSeek подправить ваш исходный код (он работает нормально и рисует линии автоматически):
#property copyright "Copyright 2024, Evgeniy Shtenco"  // Информация об авторских правах
#property link      "https://www.mql5.com/en/users/koshtenko"  // Ссылки на автора
#property version   "1.00"  // Номер версии индикатора
#property indicator_chart_window  // Индикаторы отображаются в окне графика

// Входные параметры
input int LookBackBars = 300;      // Количество K-линий, проанализированных обратно
input color GannFanColor = clrBlue; // Цвета веерной линии Вогана

// Глобальные переменные
double extremumPrice;        // Цена крайнего пункта
datetime extremumTime;       // Время экстремальной точки
double oppositeExtremumPrice; // Обратная экстремальная цена
datetime oppositeExtremumTime; // Время точки обратной полярности
bool isTrendUp;              // Флаг направления тренда (истинный для восходящего тренда)

//+------------------------------------------------------------------+
//| Функции инициализации пользовательских индикаторов & nbsp; &nbsp ; ||
//+------------------------------------------------------------------+
int OnInit()
{
    return (INIT_SUCCEEDED);  // Успешная инициализация
}

//+------------------------------------------------------------------+
//| Пользовательские функции реинициализации индикаторов & nbsp; &nbsp ; ||
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
    {
        // Удалить все объекты сектора Ганна
        ObjectsDeleteAll(0, "GannFan_");
ObjectsDeleteAll(0, "OppositeGannFan_");
}

//+------------------------------------------------------------------+
//| Функции расчета пользовательских индикаторов & nbsp; &nbsp ; | | | | | | | |
//+------------------------------------------------------------------+
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[])            // Массив разброса точек
{
    if (rates_total < LookBackBars) return (0);  // Возврат, если данных недостаточно

    // Очистите ранее нарисованные объекты
    if (prev_calculated == 0) {
        ObjectsDeleteAll(0, "GannFan_");
        ObjectsDeleteAll(0, "OppositeGannFan_");
    }

    // Нахождение крайних точек в последних 300 K-линиях
    FindExtremums(rates_total, high, low, time);

    // Рисование веерной линии Венна
    DrawGannFan(extremumPrice, extremumTime);
    DrawOppositeGannFan(oppositeExtremumPrice, oppositeExtremumTime);

    return (rates_total);  // Возвращает общее количество обработанных столбцов
}

//+------------------------------------------------------------------+
//| Найдите экстремальные точки в пределах заданного количества K-линий. |
//+------------------------------------------------------------------+
void FindExtremums(const int rates_total, const double & high[], const double & low[], const datetime & time[])
{
    int startIndex = rates_total - LookBackBars;  // Начните индексирование (300 K строк назад)
    int endIndex = rates_total - 1;               // Конечный индекс (последняя K-строка)

    // Поиск максимумов и минимумов
    int highestIndex = ArrayMaximum(high, startIndex, LookBackBars);
    int lowestIndex = ArrayMinimum(low, startIndex, LookBackBars);

    // Определите направление тренда (сравните время максимумов и минимумов)
    if (time[highestIndex] > time[lowestIndex]) {
        // Нисходящий тренд, если высшая точка находится после низшей точки
        extremumPrice = high[highestIndex];
        extremumTime = time[highestIndex];
        oppositeExtremumPrice = low[lowestIndex];
        oppositeExtremumTime = time[lowestIndex];
        isTrendUp = false;
    }
    else {
        // в противном случае восходящий тренд
        extremumPrice = low[lowestIndex];
        extremumTime = time[lowestIndex];
        oppositeExtremumPrice = high[highestIndex];
        oppositeExtremumTime = time[highestIndex];
        isTrendUp = true;
    }
}

//+------------------------------------------------------------------+
//| Построение линии сектора Венна & nbsp; |
//+------------------------------------------------------------------+
void DrawGannFan(double extremum, datetime extremumTime)
{
    // Определите угол Ганна и соответствующее имя.
    double angles[] = { 82.5, 75, 71.25, 63.75, 45, 26.25, 18.75, 15, 7.5};
    string angleNames[] = { "1x8", "1x4", "1x3", "1x2", "1x1", "2x1", "3x1", "4x1", "8x1"};

    // Вычислите время окончания строки сектора (текущее время + 300 циклов)
    datetime endTime = TimeCurrent();  // Используйте текущее время в качестве времени окончания

    // Нарисуйте линии секторов для каждого угла
    for (int i = 0; i < ArraySize(angles); i++)
    {
        string label = "GannFan_" + angleNames[i];  // Метки объектов
        double angle = angles[i];                  // Текущий угол

        // Рассчитайте смещение цены (на основе разницы во времени)
        double secondsDiff = endTime - extremumTime;
        double priceShift = MathTan(angle * M_PI / 180.0) * secondsDiff / PeriodSeconds();
        double endPrice;

        // Расчет цены закрытия на основе направления тренда
        if (isTrendUp) {
            endPrice = extremum + priceShift;
        }
        else {
            endPrice = extremum - priceShift;
            angle = -angle; // Угол разворота в нисходящем тренде
        }

        // Создайте объект линии тренда
        if (ObjectCreate(0, label, OBJ_TREND, 0, extremumTime, extremum, endTime, endPrice)) {
            // Установите свойства линии тренда
            ObjectSetInteger(0, label, OBJPROP_COLOR, GannFanColor);
            ObjectSetInteger(0, label, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, label, OBJPROP_WIDTH, 1);
            ObjectSetInteger(0, label, OBJPROP_RAY_RIGHT, true);
            ObjectSetString(0, label, OBJPROP_TOOLTIP, "Gann Fan " + angleNames[i]);
        }
        else {
            Print("Failed to create Gann Fan line: ", GetLastError());
        }
    }
}

//+------------------------------------------------------------------+
//|| Построение обратной веерной линии Ганна & nbsp; &nbsp ; ||
//+------------------------------------------------------------------+
void DrawOppositeGannFan(double extremum, datetime extremumTime)
{
    // Определите угол Ганна и соответствующее имя.
    double angles[] = { 82.5, 75, 71.25, 63.75, 45, 26.25, 18.75, 15, 7.5};
    string angleNames[] = { "1x8", "1x4", "1x3", "1x2", "1x1", "2x1", "3x1", "4x1", "8x1"};

    // Вычислите время окончания строки сектора (текущее время)
    datetime endTime = TimeCurrent();

    // Нарисуйте линии секторов для каждого угла
    for (int i = 0; i < ArraySize(angles); i++)
    {
        string label = "OppositeGannFan_" + angleNames[i];  // Метки объектов
        double angle = angles[i];                          // Текущий угол

        // Рассчитайте смещение цены (на основе разницы во времени)
        double secondsDiff = endTime - extremumTime;
        double priceShift = MathTan(angle * M_PI / 180.0) * secondsDiff / PeriodSeconds();
        double endPrice;

        // Расчет конечной цены в зависимости от направления противоположного тренда
        if (!isTrendUp) // Обратная тенденция
        {
            endPrice = extremum + priceShift;
        }
        else {
            endPrice = extremum - priceShift;
            angle = -angle; // Угол разворота в нисходящем тренде
        }

        // Создайте объект линии тренда
        if (ObjectCreate(0, label, OBJ_TREND, 0, extremumTime, extremum, endTime, endPrice)) {
            // Установите свойства линии тренда
            ObjectSetInteger(0, label, OBJPROP_COLOR, GannFanColor);
            ObjectSetInteger(0, label, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, label, OBJPROP_WIDTH, 1);
            ObjectSetInteger(0, label, OBJPROP_RAY_RIGHT, true);
            ObjectSetString(0, label, OBJPROP_TOOLTIP, "Opposite Gann Fan " + angleNames[i]);
        }
        else {
            Print("Failed to create Opposite Gann Fan line: ", GetLastError());
        }
    }
}

//+------------------------------------------------------------------+
//| Функции обработчика событий диаграммы &nbsp nbsp; & & & nbsp; |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,                  // Идентификатор события
const long & lparam,            // Длинные целочисленные параметры
                  const double & dparam,          // Параметры двойной точности
                  const string & sparam)         // Строковые параметры
{
    // Перерисовывайте объекты при изменении графика
    if (id == CHARTEVENT_CHART_CHANGE || id == CHARTEVENT_CLICK) {
        // Заново найдите крайние точки и постройте веерную линию Венна.
        int rates_total = Bars(_Symbol, PERIOD_CURRENT);
        double high[], low[];
        datetime time[];
        ArraySetAsSeries(high, true);
        ArraySetAsSeries(low, true);
        ArraySetAsSeries(time, true);
        CopyHigh(_Symbol, PERIOD_CURRENT, 0, rates_total, high);
        CopyLow(_Symbol, PERIOD_CURRENT, 0, rates_total, low);
        CopyTime(_Symbol, PERIOD_CURRENT, 0, rates_total, time);

        FindExtremums(rates_total, high, low, time);
        DrawGannFan(extremumPrice, extremumTime);
        DrawOppositeGannFan(oppositeExtremumPrice, oppositeExtremumTime);
    }
}
Файлы: