private void CalculateSlOrTpTarget(bool slChosen = true)
        {
            var orders = gridOrders.GetRowValues<MarketOrder>(false).Where(o => o.ID != 0).ToList();
            if (orders.Count == 0) return;
            if (orders.Select(o => o.Symbol).Distinct().Count() != 1)
            {
                MessageBox.Show(Localizer.GetString("MessageCannotSetupCommonSlTp"));
                return;
            }

            var symbol = orders[0].Symbol;
            var active = DalSpot.Instance.GetActiveFromPair(symbol, false);

            // посчитать цену паритета
            var priceParity = 0f;
            var priceParityDenom = orders.Sum(o => o.Side*o.Volume);
            if (priceParityDenom != 0)
                priceParity = orders.Sum(o => o.Side*o.Volume*o.PriceEnter)/priceParityDenom;

            // выбрать цель - пункты или контрвалюта, указать смещение от паритета
            var dlg = new CloseTargetDlg(active, priceParity);
            if (dlg.ShowDialog() != DialogResult.OK) return;

            // для ордеров вычислить TP - SL, соответствующий указанной цене / пунктам
            var target = dlg.TargetNumber;
            float price = 0;
            if (dlg.Units == CloseTargetDlg.UnitType.Points) // пунктам...
            {
                var sumSign = orders.Sum(o => o.Side);
                if (sumSign == 0)
                {
                    MessageBox.Show(Localizer.GetString("MessageSumPointsBuysAndSellsAreNil"));
                    return;
                }
                var sideTotal = Math.Sign(sumSign);
                target = DalSpot.Instance.GetAbsValue(symbol, target);
                price = sideTotal * target + orders.Sum(o => o.Side * o.PriceEnter) / sumSign;
            }
            else if (dlg.Units == CloseTargetDlg.UnitType.Counter)
            {
                // прибыль в контрвалюте?
                var sumVolume = orders.Sum(o => o.Side * o.Volume);
                if (sumVolume == 0)
                {
                    MessageBox.Show(Localizer.GetString("MessageSumVolmBuysAndSellsAreNil"));
                    return;
                }
                //var sideTotal = Math.Sign(sumVolume);
                price = (target + orders.Sum(o => o.Side * o.PriceEnter * o.Volume)) / sumVolume;
            }
            else
            {
                // цена
                price = dlg.TargetNumber;
            }

            // получить текущую цену, для сравнения
            var quote = QuoteStorage.Instance.ReceiveValue(symbol);
            if (quote == null)
            {
                MessageBox.Show(Localizer.GetString("MessageNoQuote") + " " + symbol);
                return;
            }

            // предупредить пользователя
            int countTp = 0, countSl = 0;
            foreach (var order in orders)
            {
                var isSl = (order.Side > 0 && price < quote.bid) ||
                           (order.Side < 0 && price > quote.bid);
                if (isSl) countSl++;
                else countTp++;
            }

            var priceStr = price.ToStringUniformPriceFormat();
            var msgParts = new List<string>();
            if (countSl > 0)
                msgParts.Add(
                    string.Format(Localizer.GetString("MessagePtrWillBeSetForNPosFmt"), countSl) +
                    " SL = " + priceStr);
            if (countTp > 0)
                msgParts.Add(string.Format(Localizer.GetString("MessagePtrWillBeSetForNPosFmt"), countTp) +
                    " TP = " + priceStr);

            if (MessageBox.Show(string.Join(Environment.NewLine, msgParts) +
                ". " + Localizer.GetString("TitleProceed") + "?",
                Localizer.GetString("TitleConfirmation"),
                MessageBoxButtons.YesNo) == DialogResult.No) return;

            // таки выставить SL - TP
            foreach (var order in orders)
            {
                var isSl = (order.Side > 0 && price < quote.bid) ||
                           (order.Side < 0 && price > quote.bid);
                if (isSl) order.StopLoss = price;
                else order.TakeProfit = price;
                // отправить запрос на изменение ордера
                MainForm.Instance.SendEditMarketRequestSafe(order);
            }
        }
        private void CalculateSlOrTpTarget(bool slChosen = true)
        {
            var orders = gridOrders.GetRowValues <MarketOrder>(false).Where(o => o.ID != 0).ToList();

            if (orders.Count == 0)
            {
                return;
            }
            if (orders.Select(o => o.Symbol).Distinct().Count() != 1)
            {
                MessageBox.Show(Localizer.GetString("MessageCannotSetupCommonSlTp"));
                return;
            }

            var symbol = orders[0].Symbol;
            var active = DalSpot.Instance.GetActiveFromPair(symbol, false);

            // посчитать цену паритета
            var priceParity      = 0f;
            var priceParityDenom = orders.Sum(o => o.Side * o.Volume);

            if (priceParityDenom != 0)
            {
                priceParity = orders.Sum(o => o.Side * o.Volume * o.PriceEnter) / priceParityDenom;
            }

            // выбрать цель - пункты или контрвалюта, указать смещение от паритета
            var dlg = new CloseTargetDlg(active, priceParity);

            if (dlg.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            // для ордеров вычислить TP - SL, соответствующий указанной цене / пунктам
            var   target = dlg.TargetNumber;
            float price  = 0;

            if (dlg.Units == CloseTargetDlg.UnitType.Points) // пунктам...
            {
                var sumSign = orders.Sum(o => o.Side);
                if (sumSign == 0)
                {
                    MessageBox.Show(Localizer.GetString("MessageSumPointsBuysAndSellsAreNil"));
                    return;
                }
                var sideTotal = Math.Sign(sumSign);
                target = DalSpot.Instance.GetAbsValue(symbol, target);
                price  = sideTotal * target + orders.Sum(o => o.Side * o.PriceEnter) / sumSign;
            }
            else if (dlg.Units == CloseTargetDlg.UnitType.Counter)
            {
                // прибыль в контрвалюте?
                var sumVolume = orders.Sum(o => o.Side * o.Volume);
                if (sumVolume == 0)
                {
                    MessageBox.Show(Localizer.GetString("MessageSumVolmBuysAndSellsAreNil"));
                    return;
                }
                //var sideTotal = Math.Sign(sumVolume);
                price = (target + orders.Sum(o => o.Side * o.PriceEnter * o.Volume)) / sumVolume;
            }
            else
            {
                // цена
                price = dlg.TargetNumber;
            }

            // получить текущую цену, для сравнения
            var quote = QuoteStorage.Instance.ReceiveValue(symbol);

            if (quote == null)
            {
                MessageBox.Show(Localizer.GetString("MessageNoQuote") + " " + symbol);
                return;
            }

            // предупредить пользователя
            int countTp = 0, countSl = 0;

            foreach (var order in orders)
            {
                var isSl = (order.Side > 0 && price < quote.bid) ||
                           (order.Side <0 && price> quote.bid);
                if (isSl)
                {
                    countSl++;
                }
                else
                {
                    countTp++;
                }
            }

            var priceStr = price.ToStringUniformPriceFormat();
            var msgParts = new List <string>();

            if (countSl > 0)
            {
                msgParts.Add(
                    string.Format(Localizer.GetString("MessagePtrWillBeSetForNPosFmt"), countSl) +
                    " SL = " + priceStr);
            }
            if (countTp > 0)
            {
                msgParts.Add(string.Format(Localizer.GetString("MessagePtrWillBeSetForNPosFmt"), countTp) +
                             " TP = " + priceStr);
            }

            if (MessageBox.Show(string.Join(Environment.NewLine, msgParts) +
                                ". " + Localizer.GetString("TitleProceed") + "?",
                                Localizer.GetString("TitleConfirmation"),
                                MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }

            // таки выставить SL - TP
            foreach (var order in orders)
            {
                var isSl = (order.Side > 0 && price < quote.bid) ||
                           (order.Side <0 && price> quote.bid);
                if (isSl)
                {
                    order.StopLoss = price;
                }
                else
                {
                    order.TakeProfit = price;
                }
                // отправить запрос на изменение ордера
                MainForm.Instance.SendEditMarketRequestSafe(order);
            }
        }