//+------------------------------------------------------------------+
//|                           Скрипт частичного закрытия ордеров.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property description "Частичное закрытие Buy , Sell, Auto ордеров"
#property strict

extern  int    Magic     = 123;//Уникальный номер;
extern  int    Delta     = -10;//мимнимальный процент профита от депозита;
//+------------------------------------------------------------------+
#property script_show_inputs
//--- с какими ордерами работаем
enum general_direction 
  { 
  ordersBUY  = OP_BUY,  //Ордера на покупку
  ordersSELL = OP_SELL, //Ордера на продажу
  AUTO       = -1,      //В автоматичуском режиме
  };
//--- input parameters
input general_direction Dir = AUTO;
int   Direct = Dir;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()   
{
   double p = ChartPriceOnDropped();
   
// <------------- Я решил без switch обойтись, а то масло-масляное получится
// В общем надо в цикле по всем ордерам (рыночным) найти ордер, цена открытия которого будет ближе всего к "p"

   if (Direct < 0)      //Режим АВТО-определения направления предстоящей сделки
   {
       double разница = 90000;
       int otype;
       for (int i = 0; i < OrdersTotal(); i++)//пересчитываем ордера в цикле
        {
          if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
          {       
             if(OrderSymbol() == Symbol() && OrderMagicNumber()==Magic && OrderType()<2)
             {
                //Итак отфильтровали ненужные ордера. Те ордера которые прошли - все наши - будем анализировать
                if (OrderOpenPrice() - p < разница)
                  {//Вот сюда попадают кандидаты в искомый ордер - здесь надо запомнить разницу и тип кандидата
                     разница  = OrderOpenPrice();//когда цикл закончится последний оставшийся кандидат будет искомым ордером, а его тип - выбранным пользователем
                     otype    = OrderType();
                  }
             }
          } 
        }//<--- Здесь цикл закончился в переменной otype - тип ордера, который выбрал пользователь
        
       Direct = otype;              //Раз пользователь выбрал авто-режим, то не стесняемся и выбираем тип
   }//<--- Здесь закончился авто-режим
   //<--- Здесь закончился блок авто-выбора и далее только Direct определяет направление работы
   
   double arWork[90][3];   //Поля массива: [90]-это строки (с запасом), [3]-столбцы с инф.: 0=ООР, 1=Ticket, 2=Profit;
   double arOrder[][3];    //это массив с ордерами - итоговый
   double countP=0, countM=0, profitP=0, SumProfit=0, profitM=0, priceBU=0, sumLot=0, deltaBU=0, priceClose=0;
   int i=0;
   //Теперь я сделаю цикл по ордерам, а Вы опишите разницу и почему
   double OOP, Profit, ProfitPlus, LossBuy, LossSell;
   double MaxOrderBuy, MinOrderSell;
   int TicketBuy, TicketSell;
    for (i = 0; i < OrdersTotal(); i++)//пересчитываем ордера в цикле
     {
         if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
         if(!(OrderSymbol() == Symbol() && OrderMagicNumber()==Magic && OrderType() == Direct)) continue;        
         //Итак отфильтровали ненужные ордера. Те ордера которые прошли - все наши - будем анализировать
             // для подсчета количества ордеров,
             //сколько (-) и (+) сколько профита в (-) и (+) ордерах
             //Чтобы посчитать это всё нужно много переменных - определите их перед телом цикла.
             //Все ордера перепишем в двумерный массив с полями: OrderOpenPrice, OrderTicket, OrderProfit - массив то же нужно определить
      //========================
            OOP = NormalizeDouble(OrderOpenPrice(),Digits);       //Это я так понял для сортировки ордеров
            Profit=OrderProfit()+OrderCommission()+OrderSwap();   //правильно
            if (Profit>0) 
            ProfitPlus+=Profit;                      //Суммируем профит (+) ордеров - правильно
            {  //<--- это к какому оператору скобка??? -или просто выделили блок сортировки?
               if (MaxOrderBuy < OOP || MaxOrderBuy==0)
               {
                  MaxOrderBuy = OOP; TicketBuy=OrderTicket(); LossBuy=Profit;
               }                                                                         
               if (MinOrderSell > OOP || MinOrderSell==0) 
               {
                  MinOrderSell = OOP; TicketSell=OrderTicket(); LossSell=Profit;
               }
               //1. У нас здесь нет Селл и Бай, у нас здесь или Селл или Бай, направление уже выбрано...
               //2. В результате такой сортировки мы получим 1 и последний ордер корзины, а как-же 2 и предпоследний?
               //3. Я предлагал сделать массив вида Orders[50][4] загнать в него ордера и отсортировать в этом случае будут все по-порядку
            } 
      //=========================== отделил Ваш код
      //   т.к. с массивами сложно - наверное я начну...
            Profit=OrderProfit()+OrderCommission()+OrderSwap();
            if (Profit >= 0) { countP++; profitP+=Profit; }
            if (Profit  < 0) { countM++; profitM+=Profit; }
            SumProfit += Profit;
            arWork[i][0] = OrderOpenPrice();
            arWork[i][1] = OrderTicket();
            arWork[i][2] = Profit;
            sumLot += OrderLots();
            priceBU+= OrderOpenPrice()*OrderLots();
            //на этом закончили - дальше самое интересное...
     }//<--- Здесь цикл закончился все параметры сделки уже должны быть определены
      priceBU = NormalizeDouble(priceBU / sumLot, Digits);     //Это уровень безубытка для выбранной сетки (без учета свопов и комиссий)
      priceClose = Bid;    if (Direct>0)  priceClose = Ask;    //Цена закрытия "наших" ордеров
      if (SumProfit < 0)
         {
            deltaBU = MathAbs(priceClose - priceBU)/Point;     //Расстояние в пипс до закрытия в безубыток
         }
      //ArrayResize(arOrder,i);                                //это не нужно - компилятор увеличивает размер при копировании автоматически!
      ArrayCopy(arOrder, arWork, 0,0, i *3);                   //Копируем найденные ордера из рабочего массива в основной, пустые не копируем!
      ArraySort(arOrder,i,0,MODE_DESCEND - Direct);            //Сортируем по столбцу OrderOpenPrice, с направлением сортировки - сам разберись
      //<--- здесь мы уже имеем все данные для вывода подтверждающего окна, или ещё чего-нибудь
      //извини - сам накатал - наверное из меня преподаватель хреновый...
// <-------------

//Здесь вместо Алерта инфу загнал в MessageBox, потом будем форматировать
   string ss = " Магик =" + IntegerToString(Magic) + "\nСимвол =" + Symbol() + "\nПериод =" + IntegerToString(Period()) + 
               "\nкоординаты: цена = " + DoubleToString(p,5);
   int rat=MessageBox("закрытие ордеров " + ss,"Скрипт частичного закрытия ордеров", MB_OKCANCEL);
   
   if(rat == IDOK)Alert ("закрываем ");
   if(rat == IDCANCEL)Alert("пока");

   return;  
}
//+------------------------------------------------------------------+
