/// <summary>
        /// собственно защита
        /// </summary>        
        private void CheckProtect(List<MarketOrder> orders, QuoteData curQuote,
            List<RobotHint> hints)
        {
            if (protectList == null) return;
            if (protectList.orderIds.Count == 0)
            {
                protectList = null;
                return;
            }
            var ordersToProtect = (from order in orders let orderId = order.ID where
                                       protectList.orderIds.Contains(orderId) select order).ToList();
            if (ordersToProtect.Count == 0) return;

            var pointCost = DalSpot.Instance.GetAbsValue(ordersToProtect[0].Symbol, 1f);

            // индивидуальная "защита"
            if (ProtectPosType == ProtectType.Индивидуально)
            {
                foreach (var order in ordersToProtect)
                {
                    var targetStop = order.PriceEnter + order.Side*ProtectTarget*pointCost;
                    // проверка - не пытаться переставить стоп на 0.4 пп например
                    var delta = Math.Abs(targetStop - (order.StopLoss ?? 0));
                    delta = delta/pointCost;
                    if (delta < ProtectSensitivity) continue;
                    // проверка контрольной отметки
                    var orderProtectLevel = order.PriceEnter + order.Side*ProtectLevel*pointCost;
                    var shouldProtect = order.Side == 1
                                            ? curQuote.bid > orderProtectLevel
                                            : curQuote.bid < orderProtectLevel;
                    if (!shouldProtect) continue;
                    order.StopLoss = targetStop;
                    robotContext.SendEditMarketRequest(protectedContext.MakeProtectedContext(), order);
                    if (ShowProtectMarker)
                    {
                        var title = "Защита сделки " + order.ID;
                        hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), title, title, "p", curQuote.bid)
                                      {
                                          RobotHintType = RobotHint.HintType.Коментарий,
                                          Time = curQuote.time,
                                          ColorFill = Color.White,
                                          ColorLine = Color.DarkBlue,
                                          ColorText = Color.Black
                                      });
                    }
                    protectList.orderIds.Remove(order.ID);
                }
                if (protectList.orderIds.Count == 0) protectList = null;
                return;
            }

            // защита по "медианнной цене" или по "худшей цене"
            // найти ту самую медианную цену
            float medPrice = 0;
            if (ProtectPosType == ProtectType.ПоСреднейЦене)
            { // средняя цена...
                var sumPrice = ordersToProtect.Sum(o => o.PriceEnter * o.Volume);
                var sumVolume = ordersToProtect.Sum(o => o.Volume);
                medPrice = sumPrice/sumVolume;
            }
            if (ProtectPosType == ProtectType.ПоХудшейЦене)
            {
                var date = ordersToProtect[0].TimeEnter;
                medPrice = ordersToProtect[0].PriceEnter;
                for (var i = 1; i < ordersToProtect.Count; i++)
                {
                    if (ordersToProtect[i].TimeEnter >= date) continue;
                    date = ordersToProtect[i].TimeEnter;
                    medPrice = ordersToProtect[i].PriceEnter;
                }
            }

            var stopPrice = medPrice + ordersToProtect[0].Side * ProtectTarget * pointCost;
            // проверить все ордера
            var dealProtected = false;
            foreach (var order in ordersToProtect)
            {
                var delta = Math.Abs(stopPrice - (order.StopLoss ?? 0));
                delta = delta / pointCost;
                if (delta < ProtectSensitivity) continue;
                // цена прошла рубеж?
                var shouldProtect = order.Side == 1
                                            ? curQuote.bid > medPrice
                                            : curQuote.bid < medPrice;
                if (!shouldProtect) continue;
                dealProtected = true;
                order.StopLoss = stopPrice;
                protectList.orderIds.Remove(order.ID);
            }
            if (ShowProtectMarker && dealProtected)
            {
                var text = new StringBuilder();
                text.AppendLine("Защита сделок " + string.Join(", ", ordersToProtect.Select(o => o.ID)));
                text.AppendFormat("Средневзвеш. цена: {0:f4}", medPrice);
                hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита сделок", text.ToString(), "p", curQuote.bid)
                {
                    RobotHintType = RobotHint.HintType.Коментарий,
                    Time = curQuote.time,
                    ColorFill = Color.White,
                    ColorLine = Color.DarkBlue,
                    ColorText = Color.Black
                });
            }

            if (protectList.orderIds.Count == 0) protectList = null;
            return;
        }
        /// <summary>
        /// проверить условия защиты либо по диверам, либо - по Фибоначчи
        /// прошерстить все таймфреймы, на каждом ТФ - все диверы
        /// проверить, выполняется ли условие на защиту покупок или продаж
        /// </summary>
        private void CheckProtectTrigger(
            List<MarketOrder> orders,
            QuoteData curQuote,
            List<RobotHint> hints,
            bool isHistoryStartOff,
            CandleData newCandle)
        {
            if (diversToProtect.Count == 0 && fibonacciProtect.Count == 0) return;

            var protectConditions = new StringBuilder();
            int diverSign = CheckProtectByDivers(curQuote, isHistoryStartOff, protectConditions);
            if (diverSign == 0)
                diverSign = CheckProtectByFibos(protectConditions, orders, newCandle);
            if (diverSign == 0) return;
            // защищаем сделки с указанным знаком
            var protectSide = (DealType) diverSign;
            // создать новый список защиты
            // старый либо актуализируется, либо игнорируется
            orders = orders.Where(o => o.Side == (int)protectSide).ToList();
            if (orders.Count == 0) return;

            var newProtectList = new ProtectList
            {
                orderIds = orders.Select(o => o.ID).ToList(),
                side = protectSide
            };
            if (protectList != null)
                if (newProtectList.AreEqual(protectList)) return;
            protectList = newProtectList;

            // добавить маркер на график
            if (ShowProtectEventMarker)
            {
                var eventTitle = protectSide == DealType.Buy
                    ? string.Format("Защита {0} покупок", orders.Count)
                    : string.Format("Защита {0} продаж", orders.Count);
                var eventText = "Условия: " + protectConditions;
                hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), eventText, eventTitle, "p", curQuote.bid)
                {
                    Time = curQuote.time,
                    ColorFill = Color.Yellow,
                    ColorLine = Color.Black,
                    RobotHintType = RobotHint.HintType.Коментарий
                        //diverSign > 0
                        //    ? RobotHint.HintType.Покупка
                        //    : RobotHint.HintType.Продажа
                });
            }
            //Logger.InfoFormat("CheckProtectTrigger: защита сделок [{0}] типа {1}",
            //                  string.Join(", ", protectList.orderIds), protectList.side);
        }
 public bool AreEqual(ProtectList list)
 {
     if (side != list.side) return false;
     if (orderIds.Count != list.orderIds.Count) return false;
     for (var i = 0; i < orderIds.Count; i++)
         if (orderIds[i] != list.orderIds[i]) return false;
     return true;
 }