Графический эксперт.

 
Тут недавно вопрос возникал по торговле каналов по нарисованным трендовым линиям.

Вот текст.
//+------------------------------------------------------------------+
//|                                                 TradeChannel.mq4 |
//|                                   Copyright © 2005, Yuri Makarov |
//|                                       http://mak.tradersmind.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, Yuri Makarov"
#property link      "http://mak.tradersmind.com"

extern double Lots  = 1.0;
extern int Slippage = 5;
extern int TimeOut  = 10000;

double SetLevel(double Level, double NewLevel, string ObjName, int Style)
{
   switch (Style)
   {
   case 1:  // Buy Order line
      ObjectSet(ObjName,OBJPROP_COLOR,Blue);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_SOLID);
      ObjectSet(ObjName,OBJPROP_WIDTH,2);
      break;
   case 2:  // Sell Order line
      ObjectSet(ObjName,OBJPROP_COLOR,Red);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_SOLID);
      ObjectSet(ObjName,OBJPROP_WIDTH,2);
      break;
   case 3:  // Buy Stop line
      ObjectSet(ObjName,OBJPROP_COLOR,Blue);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(ObjName,OBJPROP_WIDTH,1);
      break;
   case 4:  // Sell Stop line
      ObjectSet(ObjName,OBJPROP_COLOR,Red);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(ObjName,OBJPROP_WIDTH,1);
      break;
   case 5:  // Buy Take line
      ObjectSet(ObjName,OBJPROP_COLOR,Blue);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_DOT);
      ObjectSet(ObjName,OBJPROP_WIDTH,1);
      break;
   case 6:  // Sell Take line
      ObjectSet(ObjName,OBJPROP_COLOR,Red);
      ObjectSet(ObjName,OBJPROP_STYLE,STYLE_DOT);
      ObjectSet(ObjName,OBJPROP_WIDTH,1);
      break;
   }
   
   if (MathAbs(NewLevel - Close[0]) < MathAbs(Level - Close[0])) return (NewLevel);
   else return (Level);
}

int start()
{
   int NumObj = ObjectsTotal();
   double Spread = Ask - Bid;
   
   double pBuy  = 0;
   double pSell = 0;
   double pBuyStop = 0;
   double pBuyTake = 0;
   double pSellStop = 0;
   double pSellTake = 0;

   for (int i = 0; i < NumObj; i++)
   {
      string ObjName = ObjectName(i);
      string ObjDesc = ObjectDescription(ObjName);
      double Price = 0;

      switch (ObjectType(ObjName))
      {
      case OBJ_HLINE:
         Price = ObjectGet(ObjName,OBJPROP_PRICE1); 
         break;
      case OBJ_TREND:
         Price = ObjectGetValueByShift(ObjName,0); 
         break;
      }

      if (Price > 0)
      {
         if (ObjDesc == "Buy")  pBuy  = SetLevel(pBuy,  Price, ObjName, 1); else
         if (ObjDesc == "Sell") pSell = SetLevel(pSell, Price, ObjName, 2); else
         if (ObjDesc == "Stop") 
         {
            if (Price < Close[0]) pBuyStop = SetLevel(pBuyStop, Price, ObjName, 3);
            else pSellStop = SetLevel(pSellStop, Price, ObjName, 4); 
         } else
         if (ObjDesc == "Take") 
         {
            if (Price > Close[0]) pBuyTake = SetLevel(pBuyTake, Price, ObjName, 5);
            else pSellTake = SetLevel(pSellTake, Price, ObjName, 6);
         }
      }
   }
   
   int NumOrders = OrdersTotal();
   int NumPos = 0;

   for (i = 0; i < NumOrders; i++)
   {
      OrderSelect(i, SELECT_BY_POS);
      if (OrderSymbol() != Symbol()) continue;
      
      NumPos++;

      double tp = OrderTakeProfit();
      double sl = OrderStopLoss();

      if (OrderType() == OP_BUY)
      {
         if (Bid > pSell && pSell > 0)
         {
            OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Red);
            Sleep(TimeOut);
            return(0);
         }
         if (MathAbs(tp - pBuyTake) > Spread || MathAbs(sl - pBuyStop) > Spread) 
         {
            OrderModify(OrderTicket(), Ask, pBuyStop, pBuyTake, 0);
            Sleep(TimeOut);
            return(0);
         }
      }

      if (OrderType() == OP_SELL)
      {
         if (Ask < pBuy)
         {
            OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Red);
            Sleep(TimeOut);
            return(0);
         }
         if (MathAbs(tp - pSellTake) > Spread || MathAbs(sl - pSellStop) > Spread) 
         {
            OrderModify(OrderTicket(), Bid, pSellStop, pSellTake, 0);
            Sleep(TimeOut);
            return(0);
         }
      }
   }
   
   if (NumPos > 0) return(0);
   if ((pSell - pBuy) < Spread*2) return(0);
      
   if (Bid > pSell && pSell > pBuyStop)
   {
      OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, pSellStop, pSellTake);
      Sleep(TimeOut);
      return(0);
   }

   if (Ask < pBuy && (pBuy < pSellStop || pSellStop == 0))
   {
      OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, pBuyStop, pBuyTake);
      Sleep(TimeOut);
      return(0);
   }
}

int init()
{
   return(0);
}

int deinit()
{
   return(0);
}


Работать должен, но проверить пока не смог - Воскресенье.

Как эксперт работает.

1. Он понимает только горизонтальные и трендовые линии.
2. Рисуем на чарте произвольное число горизонтальных и трендовых линий.
3. В свойствах линии в Описании пишем слово обозначающее смысл линии - Buy, Sell, Stop, Take.
4. Смотрим как оно работает :))
5. При перемещении линий вручную, все ордера должны автоматом скорректироваться.

Если имеем несколько линий одинакового типа, эксперт выбирает ближайшую к цене.
Кроме того эксперт различает тейки и стопы для ордеров Buy и Sell.
Т.е. линии типа Stop могут быть и выше цены и ниже цены (первые для ордеров Sell, вторые для Buy).
При открытии позиции делается реверс (т.е. противоположная закрывается).

 
Немного поправил.
Добавил боевую раскраску линий.
 
Забавно, но работает :))
 
Исправил ошибку в условии на покупку.
 
Да... Скоро можно будет по ночам спать спокойно. Накинул линий, дал описание - и спать. Утром встаешь, подтягиваешь безубыток, пьешь чай...
Спасибо Mak.
 
Хочу радикально переделать,
чтобы не только каналы торговать,
но и вообще произвольную структуру уровней.
В текущей версии есть с этим проблемы.

И к этому эксперту идеально подошел бы индикатор профайла рынка,
если бы он размещался на самом чарте.
 
Добрый день, Мак, классный эксперт, спасибо.
Хотелось бы увидеть в Вашем эксперте следующее:
- Что бы поза открывалась за n пипсов до касания ценой тренд.линии т.е. иметь некий зазор для учета спрэда, да и нервишки целее:)
- При открытии позы Стоп "замораживался" на месте, но при этом иметь возможность выставлять в настройках эксперта размер Трейлинг стопа.
- Возможность выставлять Стоп не только по линии, а и фиксированный, указывая его в настройках эксперта.
- Отключать те функции эксперта которые выделены на графике (например если линия Sell выделена то эсперт не продает)т.е. обезопасить трэидера при работе.

С уважением.
 
Mak, выложи , пожалуйста, поправленного эксперта. Хочу выложить на форуме Альпари.
Ветку начал - http://www.alpari-idc.ru/ru/forum/viewtopic.php?t=43089
 
Я его пока не переделывал (и возможно не буду).
Хотел переделать логику расчета ближайших к цене линий,
но уже забыл что конкретно собирался делать.

Тут меня на пару недель от форума отключали,
и я решил что писать сюда все равне не придется,
а самому это все равно не нужно ...
 
"Нас было много на челне
Иные парус напрягали..."
А.С. Пушкин (кажется)
 
Ребята!!! Програмисты!!! Доведите, плз, до ума эксперта. Такая класная идея пропадает...