English 中文 Español Deutsch 日本語 Português
Фильтр на основании истории торговли

Фильтр на основании истории торговли

MetaTrader 4Торговые системы | 29 ноября 2006, 15:12
2 339 9
Andrey Khatimlianskii
Andrey Khatimlianskii

Введение


Фильтры бывают разные: значения индикаторов, волатильность рынка, время, день недели. Все это можно использовать для отсеивания убыточных сделок. И добавить такой фильтр в эксперта достаточно просто - еще одно условие перед блоком открытия.

Но что делать, если вы хотите в качестве фильтра использовать историю торговли эксперта? Если после неудачной серии сделок торговую систему отключить, то дальнейшей истории торговли у нас не будет, и, соответственно, нечего будет анализировать. Для решения этой проблемы нам необходимо научить эксперта торговать виртуально, то есть симулировать открытие, модификацию и закрытие сделок без реальной торговой деятельности.

Именно этому и посвящена данная статья.

Подопытная стратегия


Для реализации нашей системы возьмем советник CrossMACD_DeLuxe.mq4 и внесем в него несколько изменений:
  • при открытии/модификации/закрытии каждой позиции будем записывать изменения в массив виртуальных позиций;
  • добавим отслеживание срабатывания СтопЛосс и ТейкПрофит виртуальных позиций;
  • добавим критерий фильтрации - условие, при выполнении которого реальные сделки открываться не будут.
Я постараюсь описать каждый шаг доработки эксперта максимально подробно. Но если вам не интересно, вы можете просто скачать готового эксперта и переходить к главе "Игра не стоит свеч?".

Учет виртуальных позиций


Итак, появился сигнал на открытие позиции. Просчитаны параметры СтопЛосс и ТейкПрофит, всё готово к вызову функции OrderSend(). Именно в этот момент мы и откроем виртуальную сделку - просто сохраним необходимые параметры позиции в соответствующие переменные:
void OpenBuy()
  {
    int _GetLastError = 0;
    double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel;
    _OpenPriceLevel = NormalizeDouble(Ask, Digits);
 
    if(StopLoss > 0)
        _StopLossLevel = NormalizeDouble(_OpenPriceLevel - 
                                     StopLoss*Point, Digits); 
    else
        _StopLossLevel = 0.0; 
    if(TakeProfit > 0)
        _TakeProfitLevel = NormalizeDouble(_OpenPriceLevel + 
                                   TakeProfit*Point, Digits); 
    else
        _TakeProfitLevel = 0.0; 
 
    //---- открываем виртуальную позицию
    virtOrderSend(OP_BUY, _OpenPriceLevel, _StopLossLevel, 
                  _TakeProfitLevel);
 
    if(OrderSend(Symbol(), OP_BUY, 0.1, _OpenPriceLevel, 3, 
       _StopLossLevel, _TakeProfitLevel, "CrossMACD", 
       _MagicNumber, 0, Green) < 0)
      {
        _GetLastError = GetLastError();
        Alert("Ошибка OrderSend № ", _GetLastError);
        return(-1);
      }
  }
 
//---- Сохраняем параметры открываемой позиции в гл. переменные
void virtualOrderSend(int type, double openprice, double stoploss,
                      double takeprofit)
  {
    virtTicket = 1;
    virtType = type;
    virtOpenPrice = openprice;
    virtStopLoss = stoploss;
    virtTakeProfit = takeprofit;
  }

Как видите, мы используем всего пять переменных:
int       virtTicket     = 0;   
// определяет, есть ли открытая виртуальная позиция
int       virtType       = 0;   // тип позиции
double    virtOpenPrice  = 0.0; // цена открытия позиции
double    virtStopLoss   = 0.0; // СтопЛосс позиции
double    virtTakeProfit = 0.0; // ТейкПрофит позиции

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

Для отслеживания закрытия и модификации позиций придется поработать чуть больше. Скопируем блок контроля открытых позиций, который есть в эксперте и заменим там характеристики реальных ордеров на виртуальные:
int start()
  {
    // skipped...
 
    //+------------------------------------------------------------------+
    //| Блок контроля "виртуальных" позиций                              |
    //+------------------------------------------------------------------+
    if(virtTicket > 0)
      {
        //---- если открыта БАЙ-позиция,
        if(virtType == OP_BUY)
          {
            //---- если МАКД пересек 0-ю линию вниз,
            if(NormalizeDouble(MACD_1 + CloseLuft*Point*0.1, 
               Digits + 1) <= 0.0)
              {
                //---- закрываем позицию
                virtOrderClose(Bid);
              }
            //---- если сигнал не изменился, сопровождаем позицию 
            //     ТрейлингСтопом
            else
              {
                if(TrailingStop > 0)
                  {
                    if(NormalizeDouble(Bid - virtOpenPrice, 
                       Digits ) > 0.0)
                      {
                        if(NormalizeDouble( Bid - TrailingStop*Point - 
                           virtStopLoss, Digits) > 0.0 || virtStopLoss < Point)
                        {
                          virtStopLoss = Bid - TrailingStop*Point;
                        }
                      }
                  }
              }
          }
        //---- если открыта СЕЛЛ-позиция,
        if(virtType == OP_SELL)
          {
            //---- если МАКД пересек 0-ю линию вверх,
            if(NormalizeDouble(MACD_1 - CloseLuft*Point*0.1, 
               Digits + 1 ) >= 0.0)
              {
                //---- закрываем позицию
                virtOrderClose(Ask);
              }
            //---- если сигнал не изменился, сопровождаем позицию 
            //     ТрейлингСтопом
            else
              {
                if ( TrailingStop > 0 )
                  {
                    if(NormalizeDouble( virtOpenPrice - Ask, 
                       Digits ) > 0.0 )
                      {
                        if(NormalizeDouble( virtStopLoss - ( Ask + 
                           TrailingStop*Point ), Digits ) > 0.0 ||
                           virtStopLoss <= Point )
                          {
                            virtStopLoss = Ask + TrailingStop*Point;
                          }
                      }
                  }
              }
          }
      }
    // skipped...
    return(0);
  } 
 
 
//---- Функция закрытия виртуальной позиции
void virtOrderClose(double closeprice)
  {
    //---- Сохраняем параметры закрываемой позиции в массив
    ArrayResize(virtClosedOrders, virtClosedOrdersCount + 1);
 
    virtClosedOrders[virtClosedOrdersCount][0] = virtType;
    virtClosedOrders[virtClosedOrdersCount][1] = virtOpenPrice;
    virtClosedOrders[virtClosedOrdersCount][2] = virtStopLoss;
    virtClosedOrders[virtClosedOrdersCount][3] = virtTakeProfit;
    virtClosedOrders[virtClosedOrdersCount][4] = closeprice;
 
    virtClosedOrdersCount ++;
 
    //---- очищаем переменные
    virtTicket = 0;
    virtType = 0;
    virtOpenPrice = 0.0;
    virtStopLoss = 0.0;
    virtTakeProfit = 0.0;
  }
Как видите, модификация стала простым присваиванием нового значения переменной virtStopLoss. А вот закрытие стало достаточно сложным - все характеристики закрываемого ордера сохраняются в массив. В последствии в нем будет храниться вся виртуальная история сделок. Из нее мы будем брать информацию о закрытых сделках для принятия решения, открывать ли новую позицию.

Теперь нам необходимо обработать закрытие позиций по СтопЛоссу и ТейкПрофиту. Для этого в только что созданный блок управления виртуальными позициями добавим несколько строк:
if(virtType == OP_BUY)
  {
    //---- проверяем, не сработал ли СЛ
    if(virtStopLoss > 0.0 && NormalizeDouble(virtStopLoss - Bid, 
       Digits ) >= 0.0)
      {
        virtOrderClose(virtStopLoss);
      }
    //---- проверяем, не сработал ли ТП
    if(virtTakeProfit > 0.0 && NormalizeDouble( Bid - virtTakeProfit, 
       Digits ) >= 0.0)
      {
        virtOrderClose(virtTakeProfit);
      }
  }

Теперь наша виртуальная история счета готова и мы можем приступать к введению критерия фильтрации.

Что такое "хорошо", а что такое "плохо"?


Нам необходимо запретить открытие позиций после выполнения некоторого условия. Но какое условие выбрать? Несколько убыточных сделок подряд, срабатывание СтопЛосс позиции или уменьшение средней прибыли последних нескольких сделок? Сложно ответить однозначно - у каждого варианта могут быть свои плюсы и минусы.

Для проверки работоспособности каждого из них попробуем закодировать все три условия и протестировать на истории:
extern int TradeFiltrVariant = 0;
 
//---- Функция проверки необходимости реальной торговли
bool virtCheckCondition()
  {
    int pos, check_pos = 2;
    double last_profit = 0.0, pre_last_profit = 0.0;
    
    //---- в зависимости от значения TradeFiltrVariant:
    switch(TradeFiltrVariant)
      {
        //---- 1: запрещаем реальную торговлю, если 2 последние сделки убыточные
        case 1:
          {
            //---- если в виртуальной истории есть достаточное количество ордеров,
            if(virtClosedOrdersCount >= check_pos)
              {
                for(pos = 1; pos check_pos; pos ++)
                  {
                    //---- если сделка прибыльная, возвращаем true
                    if((virtClosedOrders[virtClosedOrdersCount-pos][0] == 0 && 
                        virtClosedOrders[virtClosedOrdersCount-pos][4] - 
                        virtClosedOrders[virtClosedOrdersCount-pos][1] >= 0.0) ||
                        (virtClosedOrders[virtClosedOrdersCount-pos][0] == 1 && 
                        virtClosedOrders[virtClosedOrdersCount-pos][1] - 
                        virtClosedOrders[virtClosedOrdersCount-pos][4] >= 0.0))
                      {
                        return(true);
                      }
                    }
              }
            return(false);
          }
        //---- 2: запрещаем реальную торговлю, если последняя позиция закрылась 
        //        по СтопЛоссу
        case 2:
          {
            //---- если в виртуальной истории есть достаточное количество ордеров,
            if(virtClosedOrdersCount > 0)
              {
                //---- если цена закрытия последнего ордера равна стоплоссу,
                if(virtClosedOrders[virtClosedOrdersCount-1][2] - 
                   virtClosedOrders[virtClosedOrdersCount-1][4] < Point &&
                   virtClosedOrders[virtClosedOrdersCount-1][4] - 
                   virtClosedOrders[virtClosedOrdersCount-1][2] < Point)
                  {
                    return(false);
                  }
              }
            return(true);
          }
        //---- 3: запрещаем реальную торговлю, если прибыль последней позиции  
        //----    меньше, чем у предпоследней (или убыток больше)
        case 3:
          {
            if(virtClosedOrdersCount >= 2)
              {
                if(virtClosedOrders[virtClosedOrdersCount-1][0] == 0)
                  {
                    last_profit =  virtClosedOrders[virtClosedOrdersCount-1][4] - 
                                   virtClosedOrders[virtClosedOrdersCount-1][1];
                  }
                else
                  {
                    last_profit =  virtClosedOrders[virtClosedOrdersCount-1][1] - 
                                   virtClosedOrders[virtClosedOrdersCount-1][4];
                  }
                if(virtClosedOrders[virtClosedOrdersCount-2][0] == 0)
                  {
                    pre_last_profit = virtClosedOrders[virtClosedOrdersCount-2][4] - 
                                      virtClosedOrders[virtClosedOrdersCount-2][1];
                  }
                else
                  {
                    pre_last_profit = virtClosedOrders[virtClosedOrdersCount-2][1] - 
                                      virtClosedOrders[virtClosedOrdersCount-2][4];
                  }
 
                if(pre_last_profit - last_profit > 0.0)
                  {
                    return(false);
                  }
              }
            return(true);
          }
        //---- по умолчанию фильтр выключен, т.е. позиция всегда будет открываться в реале
        default: return(true);
      }
    return(true);
  }
 
void OpenBuy()
  {
    int _GetLastError = 0;
    double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel;
    _OpenPriceLevel = NormalizeDouble(Ask, Digits);
 
    if(StopLoss > 0)
      { 
        _StopLossLevel = NormalizeDouble(_OpenPriceLevel - StopLoss*Point, Digits); 
      }
    else
      { 
        _StopLossLevel = 0.0; 
      }
 
    if(TakeProfit > 0)
      { 
        _TakeProfitLevel = NormalizeDouble(_OpenPriceLevel + TakeProfit*Point, Digits); 
      }
    else
      { 
        _TakeProfitLevel = 0.0; 
      }
 
    //---- открываем виртуальную позицию
    virtOrderSend(OP_BUY, _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel);
 
    //---- если фильтр виртуальных позиций торговлю запрещает, выходим
    if(virtCheckCondition() == false) 
      { 
        return(0); 
      }
 
    if(OrderSend( Symbol(), OP_BUY, 0.1, _OpenPriceLevel, 3, _StopLossLevel, 
          _TakeProfitLevel, "CrossMACD", _MagicNumber, 0, Green) < 0 )
      {
        _GetLastError = GetLastError();
        Alert("Ошибка OrderSend № ", _GetLastError);
        return(-1);
      }
  }
Как видите, у нас появилась внешняя переменная TradeFiltrVariant. Она отвечает за то, какой критерий фильтрации будет выбран:
extern int TradeFiltrVariant = 0;
//---- 0: фильтр выключен, т.е. позиция всегда будет открываться в реале
//---- 1: запрещаем реальную торговлю, если 2 последние сделки убыточные
//---- 2: запрещаем реальную торговлю, если последняя позиция закрылась по СтопЛоссу
//---- 3: запрещаем реальную торговлю, если прибыль последней позиции меньше, 
//----    чем у предпоследней (или убыток больше)
Теперь протестируем эксперта с разными фильтрами и сравним результаты.

Игра не стоит свеч?


Для тестов я выбрал следующие параметры:
Символ: GBPUSD
Период: Н4, 01.01.2005 - 01.01.2006
Режим моделирования: все тики (качество моделирования 90%, котировки HistoryCenter)

Параметры эксперта:
StopLoss: 50
TakeProfit: 0 (отключен)
TrailingStop: 0 (отключен)
FastEMAPeriod: 12
SlowEMAPeriod: 26
OpenLuft: 10
CloseLuft: 0

Зависимость результатов от выбранного фильтра приведена в таблице:

TradeFiltrVariantОбщая прибыль/убыток
Всего сделок Прибильных сделок Убыточных сделок
0 1678.75
419 (22%)
32 (78%)
1105.6520
2 (10%)
18 (90%)
2 -550.20110 (0%)
11 (100%)
3 1225.13287 (25%)
21 (75%)









Как видите, предположение о полезности фильтра сделок пока не подтвердилось. Напротив, все результаты с его использованием хуже исходного. Единственным исключением стал третий вариант - у него больше процент прибыльных сделок (25 против 22), но общая прибыль меньше у всех вариантов.

Что же мы сделали неправильно? Наверное ошибочно выбрали критерий фильтрации. Давайте попробуем поменять все три наши фильтра на прямо противоположные, то есть отключать реальную торговлю если:
  • две последние сделки прибыльные;
  • последняя позиция прибыльная (аналогии срабатыванию СтопЛосс у нас нет, так как ТейкПрофит отключен);
  • или прибыль последней позиции больше, чем у предпоследней.
Чтоб не урезать советника, просто добавим ещё три значения TradeFiltrVariant - 4, 5 и 6:
//---- 4: запрещаем реальную торговлю, если 2 последние сделки прибыльные
//---- 5: запрещаем реальную торговлю, если последняя сделка прибыльная
//---- 6: запрещаем реальную торговлю, если прибыль последней позиции больше, 
//----    чем у предпоследней (или убыток меньше)
 
    //---- 4: запрещаем реальную торговлю, если 2 последние сделки прибыльные
    case 4:
      {
        if(virtClosedOrdersCount >= check_pos)
          {
            for(pos = 1; pos check_pos; pos ++)
              {
                //---- если сделка убыточная, возвращаем true
                if((virtClosedOrders[virtClosedOrdersCount-pos][0] == 0 && 
                   virtClosedOrders[virtClosedOrdersCount-pos][1] - 
                   virtClosedOrders[virtClosedOrdersCount-pos][4] > 0.0) ||
                   (virtClosedOrders[virtClosedOrdersCount-pos][0] == 1 && 
                   virtClosedOrders[virtClosedOrdersCount-pos][4] - 
                   virtClosedOrders[virtClosedOrdersCount-pos][1] > 0.0))
                  {
                    return(true);
                  }
              }
          }
        return(false);
      }
    //---- 5: запрещаем реальную торговлю, если последняя сделка прибыльная
    case 5:
      {
        if(virtClosedOrdersCount >= 1)
          {
            if(virtClosedOrders[virtClosedOrdersCount-1][0] == 0)
              {
                last_profit =  virtClosedOrders[virtClosedOrdersCount-1][4] - 
                               virtClosedOrders[virtClosedOrdersCount-1][1];
              }
            else
              {
                last_profit =  virtClosedOrders[virtClosedOrdersCount-1][1] - 
                               virtClosedOrders[virtClosedOrdersCount-1][4];
              }
 
            if(last_profit > 0.0)
              {
                return(false);
              }
          }
        return(true);
      }
    //---- 6: запрещаем реальную торговлю, если прибыль последней позиции больше, 
    //----    чем у предпоследней (или убыток меньше)
    case 6:
      {
        if(virtClosedOrdersCount >= 2)
          {
            if(virtClosedOrders[virtClosedOrdersCount-1][0] == 0) 
              {
                last_profit =  virtClosedOrders[virtClosedOrdersCount-1][4] - 
                               virtClosedOrders[virtClosedOrdersCount-1][1];
              }
            else
              {
                last_profit =  virtClosedOrders[virtClosedOrdersCount-1][1] - 
                               virtClosedOrders[virtClosedOrdersCount-1][4];
              }
            if(virtClosedOrders[virtClosedOrdersCount-2][0] == 0)
              {
                pre_last_profit = virtClosedOrders[virtClosedOrdersCount-2][4] - 
                                  virtClosedOrders[virtClosedOrdersCount-2][1];
              }
            else
              {
                pre_last_profit = virtClosedOrders[virtClosedOrdersCount-2][1] - 
                                  virtClosedOrders[virtClosedOrdersCount-2][4];
              }
 
            if(last_profit - pre_last_profit > 0.0)
              {
                return(false);
              }
          }
        return(true);
      }
Теперь протестируем три новых варианта и добавим их в нашу таблицу:

AdaptVariantОбщая прибыль/убыток
Всего сделок Прибильных сделок Убыточных сделок
0 1678.75
419 (22%)
32 (78%)
1105.65 202 (10%)
18 (90%)
2 -550.20110 (0%)
11 (100%)
3 1225.13 287 (25%)
21 (75%)
4
1779.24
399 (23%) 30 (77%)
5
2178.95
31
9 (29%)
22 (71%)
6
602.32
24
5 (21%)
19 (79%)














Шестой вариант отфильтровал половину сделок - как прибыльных, так и убыточных. Четвертый - отсеял две убыточные сделки, увеличив итоговую прибыль на 100.49$.

А лучше всего показал себя вариант с запретом торговли после каждой прибыльной сделки - фильтр отсеял десять убыточных сделок, не затронув ни одной прибыльной.

Так что надежда есть - даже такую простую и популярную стратегию можно улучшить!

Выводы


Думаю, что для реального улучшения системы таких простых фильтров недостаточно - необходимо провести намного более глубокие исследования и сделать новые выводы.

Найденные фильтры могут быть кроме того, что на порядок сложнее, абсолютно разными для каждой стратегии. Их эффективность напрямую зависит от чередования прибыльных и убыточных позиций.

В этой статье я лишь коснулся темы фильтров и надеюсь, что дал стимул развивать эту тему дальше.


Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (9)
Andrey Khatimlianskii
Andrey Khatimlianskii | 17 дек. 2006 в 13:43
AgentRX:
Хотелось бы задать такой вопрос автору статьи: Исходя из каких соображений построен фильтр?
Наверное, практически у каждого эксперта в истории торговли можно заметить закономерности в чередовании сделок - прибыльная-убыточная. Если такая закономерность явно выражена (например, 2-х убыточных сделок подряд не бывает вообще), этим можно воспользоваться.
Как?
Например, открывать сделку только после убыточной "виртуальной" (из предыдущего примера). Или, если средняя серия прибыльных сделок 3, не открывать "настоящую" позицию после каждых 3-х прибыльных сделок.


На самом деле, изначально задумывался адаптирующийся эксперт, критерием принятия решения у которого был бы именно фильтр по истории сделок. Но, написав статью, я понял что пока это только статический фильтр.
Опубликовал её в таком виде только потому, что "виртуальная" торговля может быть использована в экспертах и по-другому. Может, кому-то пигодится ;)

А адаптивную стратегию, использующую подобный фильтр, я постараюсь рассмотреть в ближайшее время в новой статье.

AgentRX:
Также хотелось бы добавить, что 31 сделка за год на H4 - это очень мало.
Вы не поверите, насколько сложно каждый раз "придумывать" нового эксперта для статьи =)))
Поэтому я использую CrossMACD уже раз 10-й =)
Это - иллюстрация. Помощь в интеграции кода, если хотите.

Без примера использования статья бы малого стоила, а так - практическое пособие ;)
Andrey Khatimlianskii
Andrey Khatimlianskii | 17 дек. 2006 в 13:47
AgentRX:
Фильтр отрабатывался на конкретном советнике. То, что он работает на любом другом советнике - не доказывалось.
Я как раз наоборот считаю, что данная стратегия - не самый удачный вариант использования фильтра.
Признаюсь, параметры и критерии фильтрации выбирал так, чтоб тест показывал хоть какую-нибудь прибыль =)

Думаю, если использовать длинную историю торговли, можно подобрать намного более "качественные" критерии фильтрации.
[Удален] | 19 дек. 2006 в 10:07
komposter:
AgentRX:
Хотелось бы задать такой вопрос автору статьи: Исходя из каких соображений построен фильтр?
Наверное, практически у каждого эксперта в истории торговли можно заметить закономерности в чередовании сделок - прибыльная-убыточная. Если такая закономерность явно выражена (например, 2-х убыточных сделок подряд не бывает вообще), этим можно воспользоваться.
Как?
Например, открывать сделку только после убыточной "виртуальной" (из предыдущего примера). Или, если средняя серия прибыльных сделок 3, не открывать "настоящую" позицию после каждых 3-х прибыльных сделок.

Во-первых, спасибо за ответ.

По поводу закономерности в торговле - на мой взгляд, это относится только к "определенной группе" экспертов. На примере чемпионата можно найти как подтверждения, так и опровержения вашей теории. Хотелось бы сразу заметить, что мы говорим об определенном временном интервале и заранее известной стратегии.

Для работы вашего фильтра необходимо выделить множество эспертов, условиями которых, например, будет частое совершение двух убыточных сделок подряд. Т.е. необходимо провести классификацию. Ее можно выявить либо эмпирически, либо математически. Первое легче - но менее достоверно, т.к. рынок меняется во времени. По поводу второго не могу ничего сказать, т.к. пока не видел работ, связанных с данным направлением.

Если вы будете строить параметры фильтра в процессе работы эксперта, то получится эмпирическая (адаптивная) классификация. Таким образом, у вас два возможных пути - классифицировать экспертов и строить фильтры для данных классификаций, либо строить универсальный фильтр с адаптивной классификацией.

В любом случае, это мое сугубо личное мнение, желаю вам успехов в дальнейших исследованиях.
Andrey Khatimlianskii
Andrey Khatimlianskii | 19 дек. 2006 в 10:55
AgentRX:
По поводу закономерности в торговле - на мой взгляд, это относится только к "определенной группе" экспертов.
Не спорю.
Но я все равно считаю, что такой фильтр имеет право на жизнь.
Vladimir Karputov
Vladimir Karputov | 20 июл. 2015 в 09:18

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Вопросы от начинающих

Lena Selesneva, 2015.07.20 06:53

Раньше советник из статьи "фИЛЬТР НА ОСНОВАНИИ ИСТОРИИ ТОРГОВЛИ" ( www.mql5.com/ru/articles/1441 ) работал отлично, сейчас же при компилировании выдает ошибку '[' - invalid index value при задании входных параметров: double virtClosedOrders[0][5]; Помогите разобраться.


Трейдинг под Linux Трейдинг под Linux
Использование программ-индикаторов для оперативного отслеживания ситуации на мировых финансовых биржах.
Отображение уровней поддержки и сопротивления Отображение уровней поддержки и сопротивления
Эта статья посвящена поиску и отображению Уровней Поддержки и Сопротивления в программе MetaTrader 4. На основе простого алгоритма строится удобный и универсальный индикатор. Эта статья затрагивает так же такую полезную тему, как создание простого индикатора, способного отображать в одну рабочую область результаты с разных периодов времени.
Трёхмерные графики - профессиональный инструмент анализа рынка Трёхмерные графики - профессиональный инструмент анализа рынка
В это статье мы напишем простую библиотеку для создания трехмерных графиков и последующего их проcмотра в Microsoft Excel. Мы воспользуемся стандартными возможностями языка MQL 4 для подготовки и экспорта данных в файл формата *.csv.
Один способ построения уровней поддержки и сопротивления Один способ построения уровней поддержки и сопротивления
В данной статье описывается процесс создания простейшего скрипта для вычисления уровней поддержки и сопротивления. Статья ориентирована на новичков, поэтому каждый момент процесса разобран очень подробно. Однако, несмотря на всю простоту скрипта, изучение данной статьи, вероятно, будет полезным и для людей более продвинутых в трейдинге и владении платформой MetaTrader 4, так как содержит в себе пример экспорта данных в текстовую таблицу, импорта ее в Microsoft Excel и построения графиков для дальнейшего подробного анализа.