Вход в кабинет трейдера

Логин/E-mail *
Пароль *
  

Статьи MQLabs™

MQLabs: Достойный фрактал

Советник  WorthyFractal

Файлы стратегий для AutoGraf 4.0

Развернутые результаты тестирования эксперта

   

    Абсолютно все описываемые в рамках MQLabs стратегии можно разделить на два типа: трендовые и флэтовые. Как бы ни старался создатель системы привить ей универсальность, полностью уравновесить влияние тренда или флэта не получается. В определенный момент стратегия обязательно проявит свою предрасположенность к одному из состояний рынка. Такое положение дел можно сравнить с задачей получения золота 1000-ой пробы.

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

    Одно из таких решений сегодня и будет представлено на суд общественности. Речь идет о трендовой стратегии, состоящей из двух классических кирпичиков. Фундаментом выступает индикатор фракталов Билла Вильямса. Наиболее распространенное применение этого индикатора - открытие сделки в сторону пробития последнего фрактала. Большим недостатком в такой технике торговли является высокая частота ложных сигналов, так как после пробития фрактала цена часто совершает глубокие откаты с пробитием противоположного фрактала. То есть не каждое пробитие фрактала стоит считать сигналом открытия сделки. Необходимо выделить значимые или достойные фракталы.

    Здесь на помощь приходит второй, составляющий систему, классический кирпичик - средняя скользящая. С ее помощью легко отсекаются "недостойные" фракталы. Так, достойный фрактал "вверх", пробитие которого вверх будет приводить к открытию длинной сделки, обязательно находится выше средней скользящей линии. Все остальные фракталы "вверх", находящиеся ниже средней скользящей линии, считаются недействительными. Соответственно, достойным фракталом "вниз" для открытия короткой сделки считается тот, который находится ниже средней скользящей линии (см. рис. 1).

Рис. 1. - Примеры достойных фракталов.

    Как видно из рис. 1, у сделок не предполагается уровень профита. Закрытие сделок происходит лишь по стопу, который с течением времени передвигается вслед за ценой по найденным достойным фракталам. Такой подход дает возможность существования сделки до объективного окончания тренда. Минусом отсутствия профита является потеря значительной части прибыли в фазе возврата цены к средней скользящей линии. Незначительность этого минуса будет доказана в ходе тестирования стратегии, результаты которого приведены в конце материала.

    С целью уменьшения потерь при открытии сделок "с рынка", для ведения торговой деятельности будут использоваться отложенные ордера Buy Stop и Sell Stop. Цены открытия отложенных ордеров будут совпадать с уровнями стоп-приказов текущих позиций Buy или Sell. То есть в торговом окне терминала всегда будут присутствовать два ордера: Buy и Sell Stop или Sell и Buy Stop. Исключение составит случай запуска стратегии, когда можно будет наблюдать наличие двух отложенных ордеров Buy Stop и Sell Stop.

    Реализацией стратегии в виде советника является эксперт WorthyFractal. Алгоритмически он делится на две части: поиск двух последних достойных фракталов (один для открытия короткой сделки и один для открытия длинной сделки) и непосредственное ведение торговли.

    Первая часть реализована в виде функции GetSignal:

 
//+-------------------------------------------------------------------------------------+
  //| Расчет уровней BuyLevel и SellLevel                                                 |
  //+-------------------------------------------------------------------------------------+
  void GetSignal()
  {
  // - 1 - ==================== Поиск предыдущего посчитанного бара =======================
   int BegBar = iBarShift(NULL, 0, LastCalc);
  // - 1 - ==================================== Окончание блока ===========================
  
   for (int i = BegBar; i > 0; i--)
     {
  // - 2 - ================================ Поиск "верхних" фракталов =====================
      // - 2.1 - ================= Отслеживание пробития фрактала =========================
      if (High[i] >= BuyLevel + Tick && BuyChangeEnable)  // Если случилось пробитие уровня
        {                                                 // BUY
         BuyChangeEnable = False; // до пробития уровня Sell запрещается изменение величины
                                  // BuyLevel 
         SellChangeEnable = True; // величина SellLevel может изменяться
         SellLevel = LastDn;      // и принимает значение последнего фрактала ниже средней
        }
      // - 2.1 - ========================== Окончание блока  ==============================
      
      // - 2.2 - ======================== Поиск нового фрактала ===========================
      if (i > 2)
        {  
         double Fr = iFractals(NULL, 0, MODE_UPPER, i);    // Получение значения "верхнего"
                                                           // фрактала на свече №i
         if (Fr != 0)                                                // Если фрактал найден
           {
            double MA = iMA(NULL, 0, MAPeriod, 0, MAMethod, MAPrice, i);
            if (Fr > MA)                   // Чтобы фрактал был достоен внимания, он должен
              {                            // находиться выше средней
               LastUp = Fr;                      // В любом случае сохраняется его значение
               if (Fr < BuyLevel && BuyChangeEnable)   // Если фрактал ниже предыдущего или
                 BuyLevel = Fr;             // разрешено обновление, то уровень обновляется
              }   
           }
        }   
      // - 2.2 - ========================== Окончание блока  ==============================
  // - 2 - ==================================== Окончание блока ===========================
  
  // - 3 - ================================ Поиск "нижних" фракталов ======================
      // - 3.1 - ================= Отслеживание пробития фрактала =========================
      if (Low[i] <= SellLevel - Tick && SellChangeEnable) // Если случилось пробитие уровня 
        {                                                 // Sell
         SellChangeEnable = False; // до пробития уровня Buy запрещается изменение величины
                                   // SellLevel 
         BuyChangeEnable = True;   // величина BuyLevel может изменяться
         BuyLevel = LastUp;        // и принимает значение последнего фрактала выше средней
        }
      // - 3.1 - ========================== Окончание блока  ==============================
      
      // - 3.2 - ======================== Поиск нового фрактала ===========================
      if (i > 2)
        {
         Fr = iFractals(NULL, 0, MODE_LOWER, i);            // Получение значения "нижнего"
                                                            // фрактала на свече №i
         if (Fr != 0)                                                // Если фрактал найден
           {
            MA = iMA(NULL, 0, MAPeriod, 0, MAMethod, MAPrice, i);
            if (Fr < MA)                   // Чтобы фрактал был достоен внимания, он должен
              {                            // находиться ниже средней
               LastDn = Fr;                      // В любом случае сохраняется его значение
               if (Fr > SellLevel && SellChangeEnable) // Если фрактал ниже предыдущего или
                  SellLevel = Fr;           // разрешено обновление, то уровень обновляется
              }   
           }
        }   
      // - 3.2 - ========================== Окончание блока  ==============================
  // - 3 - ==================================== Окончание блока ===========================
     }
     
   LastCalc = Time[2];               // С этого бара начнется следующий цикл поиска уровней
   
   return;                                             
  }

    Искомые значения функции (уровень для открытия длинной и уровень для открытия короткой сделок) по ее окончании должны находиться в переменных BuyLevel и SellLevel соответственно.

     А начинается все с поиска начального бара для анализа. Это делается для ускорения работы функции и эксперта в целом, помогая избегать просмотра всей доступной истории при каждом вызове GetSignal. Время открытия бара, с которого необходимо начинать новый поиск, сохраняется в переменной LastCalc. Зная время, всегда можно вычислить номер бара, что и делается в первом блоке функции.

     Цикл поиска фракталов состоит из двух блоков: второго и третьего. Второй блок занимается вычислением уровня BuyLevel, а третий - уровня SellLevel. При первом вызове функции GetSignal значение BuyLevel равно 999999, а SellLevel - 0. Это позволяет первым же найденным фракталам стать "достойными".

     В этом месте стоит сделать небольшое отступление и разъяснить одно немаловажное условие стратегии, которое на первых порах не является очевидным. Дело заключается в порядке назначения достойных фракталов. Так, при пробитии достойного фрактала, например, вниз, все последующие фракталы "вниз" не должны фиксироваться в качестве достойных, чтобы не приводить к получению повторных сигналов открытия сделки. Следующий достойный фрактал вниз должен определяться только после пробития достойного фрактала вверх. Соответственно, в этом случае новые достойные фракталы вверх не фиксируются до момента пробития достойного фрактала вниз.

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

     Управление разрешением фиксации новых достойных фракталов занимаются переменные BuyChangeEnable и SellChangeEnable. При старте эксперта они имеют значение True, что впоследствии больше не случается, их значения всегда противоположны. Изменение их значений производится во вложенных блоках 2.1 и 3.1, где происходит проверка пробития существующих уровней BuyLevel и SellLevel. При пробитии уровня BuyLevel запрещается фиксация новых достойных фракталов вверх и разрешается фиксация достойных фракталов вниз (BuyChangeEnable принимает значение False, а SellChangeEnable - значение True). При этом уровень SellLevel, давно не обновлявшийся, принимает значение последнего фрактала "вниз", находящегося ниже средней скользящей линии. Это значение всегда находится в переменной LastDn.

    Аналогичным образом производятся действия в блоке 3.1 при определении пробития уровня SellLevel вниз. SellChangeEnable принимает значение False, а BuyChangeEnable - True. Обновление уровня BuyLevel производится при помощи переменной LastUp, хранящей значение последнего фрактала "вверх", находящегося выше средней скользящей линии.

    Также сходными между собой являются вложенные блоки 2.2 и 3.2, осуществляющие поиск новых фракталов. В блоке 2.2, при нахождении фрактала "вверх", вычисляется значение средней скользящей линии и сравнивается со значением фрактала. Если фрактал выше линии, то заполняется переменная LastUp. Если разрешена фиксация нового фрактала и фрактал находится ниже уровня BuyLevel, то BuyLevel принимает новое значение. Точно также работает блок 3.2. При нахождении фрактала "вниз", вычисляется значение средней скользящей линии. Если фрактал находится ниже линии, то переменная LastDn принимает значение найденного фрактала. Ели при этом разрешена фиксация нового фрактала и фрактал выше значения SellLevel, то SellLevel принимает значение LastDn.

    По окончании цикла "for" переменная LastCalc принимает значение времени открытия второго (на данный момент) бара. Это позволит начать следующий цикл поиска не с начала истории, а с третьей (если вызов функции GetSignal произойдет при открытии следующего бара) свечи.

    Найденные значения BuyLevel и SellLevel в дальнейшем используются во второй части советника, занимающейся отдачей торговых приказов. Эта часть реализована в виде функции Trade:

 
//+-------------------------------------------------------------------------------------+
  //| Открытие позиций и установка ордеров                                                |
  //+-------------------------------------------------------------------------------------+
  bool Trade()
  {
  // - 1 - ============================= Установка ордера BuyStop =========================
   if (BuyLevel < 999999)    // активен сигнал BUY (проверяется отложенный ордер Buy Stop и
     {                                          //  уровень стопа у имеющейся позиции Sell)
      double Price = NP(BuyLevel + Spread + Tick);         // Расчет цены открытия Buy Stop
      
      // - 1.1 - ====================== Проверка существования Buy Stop ===================
      if (BuyType == OP_BUYSTOP)                                    // Присутствует BuyStop
        if (OrderSelect(BuyTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
          {  
           if (MathAbs(OrderOpenPrice() - Price) >= Tick)         // Проверка цены открытия
                                    // Если не равна нужной цене, то производится изменение
             if (WaitForTradeContext())                      // свободен ли торговый поток?
               {
                RefreshRates();                            // Обновление значений Bid и Ask
                if (Price - Ask > StopLevel)// Если новое значение цены открытия достаточно
                  if (!OrderModify(BuyTicket, Price, 0, 0, 0))    // далеко от текущей цены
                    return(False);
               }
              else
               return(False);    
          }
      // - 1.1 - =========================== Окончание блока ==============================
          
      // - 1.2 - ==== Проверка существования Sell при уходе цены выше цены открытия Buy ===
      if (SellType == OP_SELL && Ask > Price)// Присутствует Sell при цене выше входа в Buy
        {
         CloseOrder(SellTicket);                 // В этом случае необходимо закрыть сделку
         return(False);
        } 
      // - 1.2 - =========================== Окончание блока ==============================
          
      // - 1.3 - ======== Проверка существования Sell в "нормальных условиях" =============
      if (SellType == OP_SELL)     // Если есть SELL, то проверяется расположение его стопа
        if (OrderSelect(SellTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
          {  
           if (MathAbs(OrderStopLoss() - Price) >= Tick)     // Проверка правильности стопа
             if (WaitForTradeContext())                      // свободен ли торговый поток?
               {
                RefreshRates();                            // Обновление значений Bid и Ask
                if (Price - Ask > StopLevel)//Если новое значение стопа открытия достаточно
                  if (!OrderModify(SellTicket, 0, Price, 0, 0))   // далеко от текущей цены
                    return(False);
               }
              else
               return(False);    
          }
      // - 1.3 - =========================== Окончание блока ==============================
  
      // - 1.4 - ====================== Установка Buy Stop при его отсутствии =============
      if (BuyType < 0 && Price > Ask)                        // Ордер BuyStop не установлен
        if (OpenOrderCorrect(OP_BUYSTOP, Lots, Price, 0, 0) != 0)
          return(False);                    
      // - 1.4 - =========================== Окончание блока ==============================
     }   
  // - 1 - =============================== Окончание блока ================================
             
  // - 2 - =========================== Установка ордера SellStop ==========================
   if (SellLevel > 0)      // активен сигнал SELL (проверяется отложенный ордер Sell Stop и
     {                                           //  уровень стопа у имеющейся позиции Buy)
      Price = NP(SellLevel - Tick);                       // Расчет цены открытия Sell Stop
  
      // - 2.1 - =================== Проверка существования Sell Stop =====================
      if (SellType == OP_SELLSTOP)                                 // Присутствует SellStop
        if (OrderSelect(SellTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
          {                                                       // Проверка цены открытия
           if (MathAbs(OrderOpenPrice() - Price) >= Tick)   // Если не равна, то изменяется
             if (WaitForTradeContext())                      // Свободен ли торговый поток?
               {
                RefreshRates();                            // Обновление значений Bid и Ask
                if (Bid - Price > StopLevel)// Если новая цена достаточно далеко от текущей
                  if (!OrderModify(SellTicket, Price, 0, 0, 0))// то меняется цена открытия
                    return(False);
               }
              else
               return(False);    
          }
      // - 2.1 - =========================== Окончание блока ==============================
          
      // - 2.2 - ==== Проверка существования Buy при уходе цены ниже цены открытия Sell ===
      if (BuyType == OP_BUY && Bid < Price)    // Присутствует BUY ниже уровня входа в Sell
        {
         CloseOrder(BuyTicket);
         return(False);
        }
      // - 2.2 - =========================== Окончание блока ==============================
        
      // - 2.3 - ======== Проверка существования Buy в "нормальных условиях" ==============
      if (BuyType == OP_BUY)        // Если есть Buy, то проверяется расположение его стопа
        if (OrderSelect(BuyTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
          {        // Если значение стопа не равно новому значению цены, то стоп изменяется
           if (MathAbs(OrderStopLoss() - Price) >= Tick)
             if (WaitForTradeContext())                      // свободен ли торговый поток?
               {
                RefreshRates();                            // Обновление значений Bid и Ask
                if (Bid - Price > StopLevel)   // Новое значение стопа достаточно далеко от
                  if (!OrderModify(BuyTicket, 0, Price, 0, 0))              // текущей цены
                    return(False);
               }
              else
               return(False);    
          }
      // - 2.3 - =========================== Окончание блока ==============================
  
      // - 2.4 - ====================== Установка Sell Stop при его отсутствии ============
      if (SellType < 0 && Bid > Price)                      // Ордер SellStop не установлен
        if (OpenOrderCorrect(OP_SELLSTOP, Lots, Price, 0, 0) != 0)
          return(False);                    
      // - 2.4 - =========================== Окончание блока ==============================
     }   
  // - 2 - =============================== Окончание блока ================================
   
   return(True);    
  }

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

        Первый блок обрабатывает значение BuyLevel. Любое реальное значение (все, что меньше 999999) приводит к исполнению команд внутри блока. Сначала вычисляется цена Price, соответствующая уровню пробития фрактала. Для движения вверх это Ask. Поэтому к BuyLevel прибавляется спрэд. Так как под пробитием подразумевается превышение уровня, то в выражении участвует одно минимальное изменение цены - Tick.

        Далее следует проверка всех возможных состояний ордеров. По аналогии с предыдущей рассмотренной стратегией (Молния), данные о наличии ордеров собирает функция FindOrders, которая формирует значения переменных BuyTicket, BuyType, SellTicket и SellType. Вложенный блок 1.1 при наличии ордера Buy Stop проверяет цену его открытия. При несоответствии цены открытия значению Price производится модификация ордера. Любая ошибка в ходе попытки модификации сразу же прекращает выполнение функции Trade с возвратом значения False.

        Вложенный блок 1.2 при нормальном функционировании эксперта никогда не будет выполнен, так как отслеживает ситуацию существования ордера Sell при пробитии уровня BuyLevel. Это возможно только при отключении эксперта на длительное время, за которое уровень существенно уменьшился. В этом случае сделка будет принудительно закрыта по текущей рыночной цене. При нормальной последовательной работе эксперта будет выполняться вложенный блок 1.3, отслеживающий правильность расположения уровня стоп-приказа ордера Sell. При несоответствии значению Price, будет произведена модификация значения Stop Loss ордера. Любая ошибка при попытке модификации также экстренно завершит функцию Trade.

        Последним из всех вложенных блоков блока 1 выполняется блок 1.4. При отсутствии отложенного ордера Buy Stop и нахождении текущей цены ниже уровня Price ордер будет установлен.

        Второй блок обрабатывает значение SellLevel. Аналогично первому блоку, сначала вычисляется значение цены Price, соответствующее уровню пробития фрактала. Для движения вниз это Bid. Поэтому спрэд вычитать не нужно. Достаточно вычесть значение Tick, чтобы обозначить момент пробития фрактала.

        Вложенный блок 2.1 проверяет существование отложенного ордера Sell Stop. При его наличии проверяется значение цены открытия. Неравенство цены открытия значению Price приводит к изменению уровня исполнения ордера.

        Аналогично вложенному блоку 1.2, блок 2.2 при последовательной работе эксперта никогда не исполнится. В нем проверяется существование ордера Buy при пробитии уровня SellLevel. При фиксации такой ситуации ордер принудительно закрывается. Нормальная работа эксперта будет приводить к исполнению вложенного блока 2.3, в котором отслеживается правильность расположения уровня стоп-приказа ордера Buy.

        Завершает функцию вложенный блок 2.4, устанавливающий ордер Sell Stop при его отсутствии и нахождении текущей цены выше последнего достойного фрактала.

 

        Основные функции эксперта рассмотрены, что делает возможным тестирование стратегии на исторических данных.

        Из имеющихся шести настроечных параметров эксперта лишь один будет изменяться в зависимости от валютной пары - MAPeriod. Параметры Lots, MAMethod, MAPrice, OpenOrderSound и MagicNumber во всех проведенных опытах содержат значения по умолчанию. Начало тестирования приходится на 01.01.2008, а окончание - на 24.07.2010. Рабочий таймфрейм - H1. Результаты представлены на рис. 2 - 5.

 

                Рис. 2. - Результаты тестирования эксперта WorthyFractal на валютной паре EURUSD.

EURUSD. Значение параметра MAPeriod равно 86. Вид кривой баланса не отличается стабильностью, хотя и имеет ярко выраженный восходящий характер. Как прибыль, так и убытки следуют рывками, после чего наблюдается некоторое затишье на небольшое время. То есть это стратегия для тех, кто умеет ждать. Чистая прибыль 4306 против максимальной просадки 1604 доллара. Фактор восстановления 2.68.

Для определения годовой доходности стратегии в процентах следует вычислить среднемесячную доходность в долларах, которая составляет 138.9 доллара или 1666.84 доллара в год. При минимально возможном депозите для данных условий 4800 долларов, получается около 35% годовых.

                Рис. 3. - Результаты тестирования эксперта WorthyFractal на валютной паре USDCHF.

USDCHF. Оптимальное значение параметра MARperiod = 10. Уже по виду кривой баланса можно сделать вывод об абсолютной бесперспективности стратегии касательно франка. Небольшое значение конечной чистой прибыли никоим образом не перекрывает всех тех убытков, которые сопровождали процесс тестирования. Чистая прибыль 114 долларов, максимальная просадка 2123 доллара.

                      Рис. 4. - Результаты тестирования эксперта WorthyFractal на валютной паре GBPUSD.

GBPUSD. Значение параметра MAPeriod = 37. Вид кривой баланса стабильный и подвержен уверенному росту. Если бы не первые 120 сделок, картина являла бы собой идеал. Чистая прибыль добралась до высокой отметки 8342 доллара, не дав разгуляться максимальной просадке в 1845 долларов. Итоговый фактор восстановления 4.52. Это крепкий средний показатель для фунта, с таким можно работать.

При минимальном депозите для одной валютной пары 5500 долларов (при лоте 0.1) можно рассчитывать на годовую доходность в 59%.

                        Рис. 5. - Результаты тестирования эксперта WorthyFractal на валютной паре USDJPY.

USDJPY.  Результаты показаны при значении MAPeriod = 18. Стабильной кривую баланса назвать нельзя, а вот растущей - можно. Резкие провалы и взлеты, конечно, не способствуют оказанию высокого доверия стратегии, но их амплитуда не такая и большая для "смертельного исхода". Чистая прибыль 3480 долларов, а максимальная просадка 2124 доллара. Фактор восстановления получается ниже двух - 1.64. Этого очень мало для реального применения стратегии. Поэтому рассуждения о годовой доходности сознательно пропускаются.

 Доработка стратегии для использования в AutoGraf 4.0

    Для управления стратегией "Достойный фрактал" в среде AutoGraf пользователю необходимо получить доступ к первым четырем настроечным параметрам: Lots, MAPeriod, MAMethod и MAPrice. Если объемом сделок можно управлять непосредственно во время выполнения приложения AutoGraf (значение Lot в панели управления), то остальные параметры требуют настройки в процессе запуска прикладной программы.

 

 

    В момент присоединения эксперта AG_exp к нужному графику, в появившемся окне необходимо активизировать закладку "Входные параметры" и среди названий переменных найти параметры AT_1, AT_2 и AT_3. Параметру AT_1 будет соответствовать значение MAPeriod, параметру AT_2 - MAMethod, а параметру AT_3 - MAPrice.

         Запуск стратегии в среде AutoGraf 4.0 состоит из следующих шагов:

  • Получить файл по ссылке Файлы стратегий для AutoGraf 4.0 и распаковать полученный архив в папку MT4\experts\libraries (с перезаписью файлов AG_AT.ex4 и AG_AT.mq4).

  •  Запустить AutoGraf (перетащить эксперта AG_exp с панели "Навигатор" на нужный график и разрешить советнику торговать, поставив соответствующую галочку в закладке "Общие").

  •  Для работы стратегии в ключе приведенных результатов, в окне настроек AutoGraf (закладка "Входные параметры") установить правильное значение параметров AT_1 - AT_3 (полное повторение результатов при этом не гарантируется).

  • Выбрать стратегию №5. Для этого необходимо передвинуть вверх значок So и среди названий стратегий найти значок S5, который также потянуть вверх.

  • Запустить функцию автоматической торговли, передвинув значок AT в верхнее положение.

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

 

Игорь Герасько

Июль 2010

Специально для компании Admiral Markets

0
 
 

Комментарии

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
CAPTCHA
Проверка на СПАМ:
  ____     ____      _      _   _  __   __   ___    _ 
/ ___| / ___| / \ | \ | | \ \ / / / _ \ (_)
\___ \ | | / _ \ | \| | \ V / | | | | | |
___) | | |___ / ___ \ | |\ | | | | |_| | | |
|____/ \____| /_/ \_\ |_| \_| |_| \__\_\ |_|
Enter the code depicted in ASCII art style.

Общие вопросы
info@admiralmarkets.com.ua
Техническая поддержка
support@admiralmarkets.com.ua
Необходимые файлы и документы
Филиальная сеть
Условия перепечатки материалов с сайта
Уведомление о рисках
Карта сайта