コード例 #1
0
        public void BuildSeries(ChartControl chart)
        {
            var commentText = GetStatText();

            if (string.IsNullOrEmpty(commentText))
            {
                return;
            }
            var candles = chart.StockSeries.Data.Candles;

            // добавить комментарий с текстом
            var series    = chart.Owner.seriesComment;
            var indiTitle = MakeCommentTitle();
            var comment   = series.data.FirstOrDefault(c => c.Magic == CommentMagic && c.Text.StartsWith(indiTitle));

            if (comment != null)
            {
                comment.Text = commentText;
                return;
            }

            // таки создать новый комментарий
            comment = new ChartComment
            {
                ArrowAngle  = nextAngle,
                ArrowLength = 50,
                Magic       = CommentMagic,
                Text        = commentText,
                Owner       = series,
                PivotIndex  = candles.Count - 1,
                PivotPrice  = candles[candles.Count - 1].open,
            };
            nextAngle += 45;
            series.data.Add(comment);
        }
コード例 #2
0
        public ChartCommentEditDialog(ChartComment obj, CandleChartControl chart) : this()
        {
            comment = obj;//new ChartComment(); ChartComment.Copy(comment, obj);

            // отобразить содержание полей
            tbText.Text = comment.Text;
            btnColorPicker.BackColor         = comment.ColorText;
            tbText.ForeColor                 = comment.ColorText;
            tbText.BackColor                 = chart.chart.BackColor;
            cbShowArrow.Checked              = !comment.HideArrow;
            cbShowFrame.Checked              = comment.DrawFrame;
            btnColorLine.ForeColor           = comment.Color;
            btnColorFill.ForeColor           = comment.ColorFill;
            tbMagic.Text                     = comment.Magic.ToString();
            transparencyControl.Transparency = comment.FillTransparency;

            // настройки выпадающих списков
            //cbTextStyle.SelectedIndex = SeriesComment.FontBold
            var patterns = new CommentaryPatternsList().GetStandardValues();

            if (patterns == null)
            {
                return;
            }
            var items = new object[patterns.Count];

            patterns.CopyTo(items, 0);
            cbTemplates.Items.AddRange(items);
        }
コード例 #3
0
        protected void MakeChartGraph(List <TrendLine> lines)
        {
            if (removeOldSigns)
            {
                RemoveOldSigns();
            }

            int    totalLosses = 0, totalProfits = 0;
            double totalPoints = 0;

            foreach (var line in lines)
            {
                line.Owner = chart.seriesTrendLine;
                chart.seriesTrendLine.data.Add(line);
                var sign        = line.LineColor == ColorBuy ? 1 : -1;
                var deltaPoints = sign * (line.linePoints[1].Y - line.linePoints[0].Y);
                deltaPoints  = DalSpot.Instance.GetPointsValue(chart.Symbol, (float)deltaPoints);
                totalPoints += deltaPoints;
                if (deltaPoints > 0)
                {
                    totalProfits++;
                }
                if (deltaPoints < 0)
                {
                    totalLosses++;
                }

                var comment = new ChartComment
                {
                    Magic       = LineMagic,
                    PivotIndex  = line.linePoints[1].X,
                    PivotPrice  = line.linePoints[1].Y,
                    ArrowAngle  = 120,
                    ArrowLength = 30,
                    Color       = line.LineColor,
                    ColorText   = chart.chart.visualSettings.SeriesForeColor,
                    Text        = string.Format("{0:f1} пп", deltaPoints),
                    Owner       = chart.seriesComment
                };
                chart.seriesComment.data.Add(comment);
            }

            var message = string.Format("{0:f1} пунктов всего, {1} \"профитов\", {2} \"лоссов\"",
                                        totalPoints, totalProfits, totalLosses);

            MessageBox.Show(message);
        }
コード例 #4
0
        public override string ActivateScript(CandleChartControl chart, PointD worldCoords)
        {
            var comment = chart.seriesComment.data.FirstOrDefault(c => c.Name == CommentSpecName);

            // удалить существующий
            if (comment != null)
            {
                chart.seriesComment.data.Remove(comment);
                chart.RedrawChartSafe();
                return(string.Empty);
            }

            // добавить новый
            MarketOrder sumPos;
            string      scriptText;

            GetCommentText(chart, out scriptText, out sumPos);
            if (sumPos == null)
            {
                return(string.Empty);
            }

            var colorFill = sumPos.ResultDepo > 0
                                ? Color.LightGreen : sumPos.ResultDepo < 0 ? Color.LightCoral : Color.Gray;

            var colorText = chart.chart.BackColor.GetBrightness() < 0.4f ? Color.White : Color.Black;

            comment = new ChartComment
            {
                FillTransparency = 80,
                ColorFill        = colorFill,
                HideArrow        = true,
                ArrowAngle       = 90,
                ArrowLength      = 1,
                PivotIndex       = worldCoords.X,
                PivotPrice       = worldCoords.Y,
                Owner            = chart.seriesComment,
                Name             = CommentSpecName,
                Text             = scriptText,
                ColorText        = colorText,
                Color            = colorText
            };
            chart.seriesComment.data.Add(comment);
            chart.RedrawChartSafe();
            return(string.Empty);
        }
コード例 #5
0
 private void MakeCommentsByTags(List <DiverTag> tags)
 {
     foreach (var diverTag in tags)
     {
         var comm = new ChartComment
         {
             ArrowLength = arrowLengthPx,
             ArrowAngle  = diverTag.side > 0 ? 270 : 90,
             Text        = "!", //diverTag.description,
             PivotIndex  = diverTag.candleIndex,
             PivotPrice  = diverTag.price,
             HideArrow   = !ShowArrow,
             HideBox     = !ShowBox,
             ColorText   = Color.Red
         };
         seriesComment.data.Add(comm);
     }
 }
コード例 #6
0
        public override string ActivateScript(CandleChartControl chart, PointD worldCoords)
        {
            var robots      = MainForm.Instance.RobotFarm.GetRobotsAsIs().ToList();
            var commentText = GetCommentForChart(chart.Symbol, chart.Timeframe, robots);

            if (string.IsNullOrEmpty(commentText))
            {
                return("Нет роботов для " + chart.Symbol + " " +
                       BarSettingsStorage.Instance.GetBarSettingsFriendlyName(chart.Timeframe));
            }

            // разместить комментарий на графике в указанной точке, удалить такой же, если был добавлен
            var comment = chart.seriesComment.data.FirstOrDefault(c => c.Name == CommentSpecName);

            if (comment != null)
            {
                chart.seriesComment.data.Remove(comment);
                chart.RedrawChartSafe();
                return(string.Empty);
            }

            var colorFill = Color.LightGreen;
            var colorText = chart.chart.BackColor.GetBrightness() < 0.4f ? Color.White : Color.Black;

            comment = new ChartComment
            {
                FillTransparency = 80,
                ColorFill        = colorFill,
                HideArrow        = true,
                ArrowAngle       = 90,
                ArrowLength      = 1,
                PivotIndex       = worldCoords.X,
                PivotPrice       = worldCoords.Y,
                Owner            = chart.seriesComment,
                Name             = CommentSpecName,
                Text             = commentText,
                ColorText        = colorText,
                Color            = colorText
            };
            chart.seriesComment.data.Add(comment);
            chart.RedrawChartSafe();
            return(string.Empty);
        }
コード例 #7
0
        private void AddChartCommentOnRobotState(int dealsOpened)
        {
            var commentLines = new List <string>
            {
                selectedBot.GetUniqueName()
            };

            if (selectedBot is FiboLevelRobot)
            {
                var fiboBot = ((FiboLevelRobot)selectedBot);
                commentLines.Add("открыто " + dealsOpened + " из " + fiboBot.MaxDealsInSeries + " сделок");
                commentLines.Add("цена A: " + fiboBot.PriceA.ToStringUniformPriceFormat() + ", цена B: " +
                                 fiboBot.PriceB.ToStringUniformPriceFormat());
            }
            else
            {
                commentLines.Add("открыто " + dealsOpened + " сделок");
            }
            var commentStr = string.Join(Environment.NewLine, commentLines);

            // найти на графике существующий комментарий или создать новый
            var comment = chart.seriesComment.data.FirstOrDefault(c => c.Name == CommentSpecName);

            if (comment == null)
            {
                comment = new ChartComment
                {
                    Name       = CommentSpecName,
                    PivotIndex = scriptActivatedCoords.X,
                    PivotPrice = scriptActivatedCoords.Y,
                    HideArrow  = true,
                    Color      = chart.chart.visualSettings.SeriesForeColor,
                    ColorFill  = Color.DarkTurquoise,
                    Text       = commentStr,
                    Owner      = chart.seriesComment
                };
                chart.seriesComment.data.Add(comment);
            }
            else
            {
                comment.Text = commentStr;
            }
        }
コード例 #8
0
        /// <summary>
        /// начать визуальное редактировние (перетаскивание) ордера
        /// </summary>
        public override bool OnMouseButtonDown(MouseEventArgs e, Keys modifierKeys)
        {
            if (e.Button != MouseButtons.Left)
            {
                return(false);
            }

            draggedComment = null;
            var clientPoint = owner.PointToScreen(new Point(e.X, e.Y));
            var x           = clientPoint.X;
            var y           = clientPoint.Y;

            // перетаскиваем ордер суммарной позы?
            var selectedCommentsLastBar = seriesCommentLastBar.GetObjectsUnderCursor(x, y,
                                                                                     SeriesComment.DefaultMouseTolerance).Where(c => c.Name == "drag").ToList();

            if (selectedCommentsLastBar.Count > 0)
            {
                draggedComment       = (ChartComment)selectedCommentsLastBar[0];
                draggedCommentSource = DraggedCommentSource.SummaryPositionOrder;
            }
            else
            if (selectedOrder != null)
            {
                // перетаскиваем ордер открытой позы?
                var selectedCommentsHit = seriesCommentSelected.GetObjectsUnderCursor(x, y, SeriesComment.DefaultMouseTolerance);
                draggedComment       = (ChartComment)selectedCommentsHit.FirstOrDefault(c => c.Name == "drag");
                draggedCommentSource = DraggedCommentSource.MarketOrder;
            }

            if (draggedComment == null)
            {
                return(false);
            }

            startDragPrice           = (float)draggedComment.PivotPrice;
            draggedComment.DrawFrame = true;
            draggedComment.HideBox   = false;

            return(true);
        }
コード例 #9
0
        private void AddTotalDealSlTpComment(int pivotIndex, float price,
                                             string comment, Color cl)
        {
            var text = comment + " " + DalSpot.Instance.FormatPrice(owner.Symbol,
                                                                    price);
            var comm = new ChartComment
            {
                PivotIndex  = pivotIndex,
                PivotPrice  = price,
                ArrowAngle  = 0,
                ArrowLength = 20,
                Text        = text,
                Color       = cl,
                ColorText   = cl,
                HideArrow   = true,
                HideBox     = true,
                Name        = "drag"
            };

            seriesCommentLastBar.data.Add(comm);
        }
コード例 #10
0
        public CommentsResponse AddChartComment(ChartCommentDto comment)
        {
            var response = new CommentsResponse();

            try
            {
                var commentRepository = new ChartCommentRepository();
                var userRepository    = new UserProfileRepository();
                var newComment        = new ChartComment
                {
                    IdUser       = comment.IdUser,
                    DatePosted   = DateTime.Now,
                    Message      = comment.Message,
                    IdSmartChart = comment.IdSmartChart,
                    IsActive     = true
                };
                commentRepository.Add(newComment);
                commentRepository.SaveChanges();
                int userId = Convert.ToInt32(comment.IdUser);
                response.Comments.Add(new ChartCommentDto()
                {
                    Message    = newComment.Message,
                    DatePosted = newComment.DatePosted,
                    UserName   = userRepository.Query().FirstOrDefault(x => x.UserId == userId).UserName,
                    IdComment  = newComment.IdComment,
                    IdUser     = userId.ToString()
                });
                commentRepository.Dispose();
                response.Acknowledgment = true;
                response.Message        = "Success";
            }
            catch (Exception ex)
            {
                _logger.Error("Error adding comment. With the exception: " + ex.Message);
                response.Acknowledgment = false;
                response.Message        = "Error: " + ex.Message;
            }

            return(response);
        }
コード例 #11
0
        public override string ActivateScript(CandleChartControl chart, PointD worldCoords)
        {
            chartSymbol = chart.Symbol;
            var comment = chart
                          .seriesComment
                          .data
                          .FirstOrDefault(c => c.Name == CommentSpecName);

            // удалить существующий
            if (comment != null)
            {
                chart.seriesComment.data.Remove(comment);
                chart.RedrawChartSafe();
                return(string.Empty);
            }

            var accountData       = AccountStatus.Instance.AccountData;
            var accountStatistics = TradeSharpAccountStatistics.Instance.proxy.GetAccountProfit1000(accountData.ID);
            var ordersBySymbol    = GetMarketOrders(accountData.ID).Where(x => x.Symbol == chart.Symbol);
            var scriptText        = GetCommentText(accountData, accountStatistics, ordersBySymbol);

            comment = new ChartComment
            {
                FillTransparency = 80,
                ColorFill        = Color.Gray,
                HideArrow        = true,
                ArrowAngle       = 90,
                ArrowLength      = 1,
                PivotIndex       = worldCoords.X,
                PivotPrice       = worldCoords.Y,
                Owner            = chart.seriesComment,
                Name             = CommentSpecName,
                Text             = scriptText,
                ColorText        = Color.Black,
                Color            = Color.Black
            };
            chart.seriesComment.data.Add(comment);
            chart.RedrawChartSafe();
            return(string.Empty);
        }
コード例 #12
0
        /// <summary>
        /// опеределить попадание в ордер, дабы "подсветить" его и произвести определенные действия
        /// (показать линии SL - TP, редактировать ордера)
        /// </summary>
        public override bool OnMouseButtonUp(MouseEventArgs e, Keys modifierKeys)
        {
            // закончить драг текстовой меточки
            if (draggedComment != null)
            {
                var newPrice     = draggedComment.PivotPrice;
                var commentTitle = draggedComment.Text;
                // если цена сдвинута меньше, чем на 0.1 пп - ничего не предлагать
                var minDelta = DalSpot.Instance.GetAbsValue(owner.Symbol, 0.1f);

                // предложить пользователю изменить SL / TP
                if (commentTitle.Contains("SL") || commentTitle.Contains("TP"))
                {
                    var isSl = commentTitle.Contains("SL");
                    if (Math.Abs(newPrice - startDragPrice) > minDelta)
                    {
                        // меняем рыночный ордер?
                        if (draggedCommentSource == DraggedCommentSource.MarketOrder)
                        {
                            ModifyMarketOrderAfterDrag(newPrice, isSl, selectedOrder);
                        }
                        else if (draggedCommentSource == DraggedCommentSource.SummaryPositionOrder)
                        {
                            ModifySummaryOrderAfterDrag(newPrice, isSl, commentTitle);
                        }
                    }
                }

                // забыть о текстовой метке
                draggedComment.HideBox   = true;
                draggedComment.DrawFrame = false;
                draggedComment           = null;
            }

            if (e.Button != MouseButtons.Left)
            {
                return(false);
            }

            var screenPoint = owner.PointToScreen(new Point(e.X, e.Y));
            var x           = screenPoint.X;
            var y           = screenPoint.Y;

            // попали в специальные отметки для выделенного ордера (например, предложение редактировать
            // или закрыть ордер)?
            var selectedCommentsHit = seriesCommentSelected.GetObjectsUnderCursor(x, y, SeriesAsteriks.DefaultMouseTolerance);

            if (selectedCommentsHit.Count > 0)
            {
                if (selectedOrder.IsOpened)//selectedCommentsHit.Any(c => c.Name == "edit") && selectedOrder != null)
                {
                    // открыть окно редактирования ордера
                    owner.Owner.CallShowWindowEditMarketOrder(selectedOrder);
                }
                else
                if (selectedCommentsHit.Any(c => c.Name == "info") && selectedOrder != null)
                {
                    // показать информацию по закрытому ордеру
                    owner.Owner.CallShowWindowInfoOnClosedOrder(selectedOrder);
                }

                return(false);
            }

            // найти выделенные кликом коменты или астериксы
            var comments = seriesComment.GetObjectsUnderCursor(x, y, SeriesComment.DefaultMouseTolerance);
            var asters   = seriesAsteriks.GetObjectsUnderCursor(x, y, SeriesAsteriks.DefaultMouseTolerance);
            var orders   = comments.Where(p => p.Magic > 0).Select(p => p.Magic).ToList();

            orders.AddRange(asters.Where(a => a.Magic > 0).Select(a => a.Magic));

            // ордер не выбран и до того не был выбран
            if (orders.Count == 0 && selectedOrder == null)
            {
                return(false);
            }

            // ордер не выбран, но был уже выбран ранее - снять выделение
            if (selectedOrder != null)
            {
                DeselectOrder();
                return(true);
            }

            // найти ордер в списке открытых или закрытых позиций
            var order = openPositions.FirstOrDefault(p => orders.Contains(p.ID))
                        ?? closedPositions.FirstOrDefault(p => orders.Contains(p.ID));

            if (order == null)
            {
                return(false);
            }

            var ptPane = Conversion.ScreenToWorld(new PointD(e.X, e.Y), owner.StockPane.WorldRect,
                                                  owner.StockPane.CanvasRect);
            var pointTime = owner.StockSeries.GetCandleOpenTimeByIndex((int)Math.Round(ptPane.X));

            SelectOrder(order, pointTime);

            return(true);
        }
コード例 #13
0
        private void AddClosedOrderMarks(ChartControl chart, MarketOrder pos)
        {
            // отметка входа
            var indexEnter = (int)chart.StockSeries.GetDoubleIndexByTime(pos.TimeEnter, true);

            if (indexEnter >= 0)
            {
                var tipEnter = new AsteriskTooltip("c", string.Empty)
                {
                    Magic       = pos.ID,
                    Price       = pos.PriceEnter,
                    CandleIndex = indexEnter,
                    DateStart   = pos.TimeEnter,
                    Sign        = "",
                    Shape       = pos.Side > 0
                                                   ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                                   : AsteriskTooltip.ShapeType.СтрелкаВниз,
                    ColorFill = pos.Side > 0 ? ColorBuyClosed : ColorSellClosed,
                    ColorLine = Color.Black,
                    ColorText = Color.Black,
                    Radius    = ArrowSizeClosed
                };
                seriesAsteriks.data.Add(tipEnter);
            }
            if (pos.PriceExit == null || pos.TimeExit == null)
            {
                Logger.ErrorFormat("Индикатор ордеров: ошибка при отображении закрытой позиции №{0} - нет данных закрытия", pos.ID);
                return;
            }

            var indexExit = (int)chart.StockSeries.GetDoubleIndexByTime(pos.TimeExit.Value, true);

            if (indexExit >= 0)
            {
                var mark = pos.ExitReason == PositionExitReason.Closed
                               ? ""
                               : pos.ExitReason == PositionExitReason.ClosedFromUI
                                     ? "q"
                                     : pos.ExitReason == PositionExitReason.SL
                                           ? "SL"
                                           : pos.ExitReason == PositionExitReason.TP ? "TP"
                                           : pos.ExitReason == PositionExitReason.Stopout ? "STOP" : string.Empty;

                var tipExit = new AsteriskTooltip("q", mark)
                {
                    Magic       = pos.ID,
                    Price       = pos.PriceExit.Value,
                    CandleIndex = indexExit,
                    DateStart   = pos.TimeExit,
                    Sign        = "",
                    Shape       = pos.Side > 0
                                                  ? AsteriskTooltip.ShapeType.КрестВниз
                                                  : AsteriskTooltip.ShapeType.КрестВверх,
                    ColorFill = chart.StockSeries.BarNeutralColor,
                    ColorLine = Color.Black,
                    ColorText = Color.Black,
                    Radius    = ArrowSizeClosed
                };
                seriesAsteriks.data.Add(tipExit);
            }

            // комменты у стрелок входа / выхода
            if (ShowHistoryComments)
            {
                // коммент для входа
                if (indexEnter >= 0)
                {
                    var comm = new ChartComment
                    {
                        PivotIndex  = indexEnter,
                        PivotPrice  = pos.PriceEnter,
                        ArrowAngle  = 180,
                        ArrowLength = 3,
                        Text        = pos.Side == 1 ? "B" : "S",
                        Color       = chart.StockSeries.BarNeutralColor,
                        ColorText   = pos.Side > 0 ? ColorBuyClosed : ColorSellClosed,
                        HideArrow   = true,
                        HideBox     = true,
                        Name        = Localizer.GetString("TitlePositionNumber") + pos.ID,
                        Magic       = pos.ID
                    };
                    seriesComment.data.Add(comm);
                }

                // коммент для выхода
                // разобраться - выход был по ордеру либо просто закрытие
                if (indexExit >= 0)
                {
                    var commentMark =
                        pos.ExitReason == PositionExitReason.SL
                            ? "SL"
                            : pos.ExitReason == PositionExitReason.TP
                                  ? "TP"
                                  : "C";
                    var comm = new ChartComment
                    {
                        PivotIndex  = indexExit,
                        PivotPrice  = pos.PriceExit.Value,
                        ArrowAngle  = 180,
                        ArrowLength = 3,
                        Text        = commentMark,
                        Color       = pos.Side > 0 ? ColorBuyQuit : ColorSellQuit,
                        ColorText   = chart.StockSeries.BarNeutralColor,
                        HideArrow   = true,
                        HideBox     = true,
                        Name        = Localizer.GetString("TitlePositionNumber") + pos.ID,
                        Magic       = pos.ID
                    };
                    seriesComment.data.Add(comm);
                }
            }
        }
コード例 #14
0
        private void AddOpenPositionMarks(ChartControl chart,
                                          MarketOrder pos, double x)
        {
            var index = (int)x;

            if (index <= 0)
            {
                return;
            }

            var tip = new AsteriskTooltip("o", string.Empty)
            {
                Price       = pos.PriceEnter,
                Magic       = pos.ID,
                CandleIndex = index,
                DateStart   = pos.TimeEnter,
                Sign        = "",
                Shape       = pos.Side > 0
                                          ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                          : AsteriskTooltip.ShapeType.СтрелкаВниз,
                ColorFill = pos.Side > 0 ? ColorBuy : ColorSell,
                ColorLine = Color.Black,
                ColorText = Color.Black,
                Radius    = ArrowSizeOpened,
            };

            seriesAsteriks.data.Add(tip);

            if (ShowComments)
            {
                var currPrice  = chart.StockPane.StockSeries.Data[chart.StockPane.StockSeries.Data.Count - 1].close;
                var profit     = Math.Round(DalSpot.Instance.GetPointsValue(pos.Symbol, pos.Side * (currPrice - pos.PriceEnter)));
                var profitText = MakeCommentProfit(profit, pos.ResultDepo);

                // измерить высоту текста (необходимо для позиционирования текстовой метки)
                SizeF szText;
                using (var g = owner.CreateGraphics())
                {
                    using (var font = new Font(owner.Font.FontFamily,
                                               SeriesComment.FontSize,
                                               SeriesComment.FontBold ? FontStyle.Bold : FontStyle.Regular))
                    {
                        szText = g.MeasureString("BS", font);
                    }
                }
                var       h     = szText.Height / 2;
                const int l     = 15;
                var       arLen = (int)Math.Sqrt(h * h + l * l);
                var       angle = 180 - Math.Atan2(h, l) * 180 / Math.PI;

                var dealText = (pos.Side == 1 ? "Buy " : "Sell ") + pos.PriceEnter.ToStringUniformPriceFormat();
                var commPos  = new ChartComment
                {
                    PivotIndex  = x,
                    PivotPrice  = pos.PriceEnter,
                    ArrowAngle  = -angle,
                    ArrowLength = arLen,
                    Text        = dealText,
                    ColorText   = pos.Side > 0 ? ColorBuy : ColorSell,
                    HideArrow   = true,
                    HideBox     = true,
                    // ReSharper disable SpecifyACultureInStringConversionExplicitly
                    Name = pos.ID.ToString(),
                    // ReSharper restore SpecifyACultureInStringConversionExplicitly
                    Magic = pos.ID
                };
                seriesComment.data.Add(commPos);

                var commProfit = new ChartComment
                {
                    PivotIndex  = x,
                    PivotPrice  = pos.PriceEnter,
                    ArrowAngle  = angle,
                    ArrowLength = arLen,
                    Text        = profitText,
                    ColorText   = profit > 0 ? Color.Green : Color.Red,
                    HideArrow   = true,
                    HideBox     = true,
                    Name        = pos.ID + "PL",
                    Magic       = pos.ID,
                    TextCustom  = "p"
                };
                seriesComment.data.Add(commProfit);
            }
        }
コード例 #15
0
        /// <summary>
        /// добавить метки справа от крайнего бара: SL, TP, профит и прочая хрень
        /// </summary>
        private void AddLastBarMarks()
        {
            var pivotIndex = owner.StockPane.StockSeries.Data.Count - 1;

            // прибыль/убыток по сделкам
            var comm = new ChartComment
            {
                PivotIndex  = pivotIndex,
                PivotPrice  = owner.StockPane.StockSeries.Data[owner.StockPane.StockSeries.Data.Count - 1].close,
                ArrowAngle  = 330,
                ArrowLength = 23,
                Text        = "",
                Color       = owner.StockSeries.BarNeutralColor,
                ColorText   = owner.StockSeries.BarNeutralColor,
                HideArrow   = true,
                HideBox     = true,
                Name        = "CurrProfit"
            };

            seriesCommentLastBar.data.Add(comm);

            var commProfitAbs = new ChartComment
            {
                PivotIndex  = pivotIndex,
                PivotPrice  = owner.StockPane.StockSeries.Data[owner.StockPane.StockSeries.Data.Count - 1].close,
                ArrowAngle  = 0,
                ArrowLength = 20,
                Text        = "",
                Color       = owner.StockSeries.BarNeutralColor,
                ColorText   = owner.StockSeries.BarNeutralColor,
                HideArrow   = true,
                HideBox     = true,
                Name        = "CurrProfitAbs"
            };

            seriesCommentLastBar.data.Add(commProfitAbs);

            var commProfitPercent = new ChartComment
            {
                PivotIndex  = pivotIndex,
                PivotPrice  = owner.StockPane.StockSeries.Data[owner.StockPane.StockSeries.Data.Count - 1].close,
                ArrowAngle  = 30,
                ArrowLength = 23,
                Text        = "",
                Color       = owner.StockSeries.BarNeutralColor,
                ColorText   = owner.StockSeries.BarNeutralColor,
                HideArrow   = true,
                HideBox     = true,
                Name        = "CurrProfitPercent"
            };

            seriesCommentLastBar.data.Add(commProfitPercent);

            // стопы-тейки и прочая ерунда
            // раздельно по BUY и SELL
            float?buyStop = null, buyTake = null;       //, buyTrail = null;
            float?sellStop = null, sellTake = null;     //, sellTrail = null;
            int   buyVolumeSl = 0, buyVolumeTake = 0;   //, buyVolumeTrail = 0;
            int   sellVolumeSl = 0, sellVolumeTake = 0; //, sellVolumeTrail = 0;

            foreach (var pos in openPositions)
            {
                if (pos.Side > 0)
                {
                    if (pos.StopLoss.HasValue)
                    {
                        buyStop      = (buyStop ?? 0) + pos.StopLoss * pos.Volume;
                        buyVolumeSl += pos.Volume;
                    }
                    if (pos.TakeProfit.HasValue)
                    {
                        buyTake        = (buyTake ?? 0) + pos.TakeProfit * pos.Volume;
                        buyVolumeTake += pos.Volume;
                    }
                    continue;
                }
                if (pos.StopLoss.HasValue)
                {
                    sellStop      = (sellStop ?? 0) + pos.StopLoss * pos.Volume;
                    sellVolumeSl += pos.Volume;
                }
                if (pos.TakeProfit.HasValue)
                {
                    sellTake        = (sellTake ?? 0) + pos.TakeProfit * pos.Volume;
                    sellVolumeTake += pos.Volume;
                }
            }

            var hasMarksBuy   = buyStop.HasValue || buyTake.HasValue;
            var hasMarksSell  = sellStop.HasValue || sellTake.HasValue;
            var colorMarkBuy  = Color.Blue;
            var colorMarkSell = Color.Red;

            // добавить коменты
            if (buyStop.HasValue)
            {
                buyStop /= buyVolumeSl;
                AddTotalDealSlTpComment(pivotIndex, buyStop.Value, hasMarksSell
                                                                      ? "BUY SL"
                                                                      : "SL", colorMarkBuy);
            }
            if (buyTake.HasValue)
            {
                buyTake /= buyVolumeTake;
                AddTotalDealSlTpComment(pivotIndex, buyTake.Value, hasMarksSell
                                                                      ? "BUY TP"
                                                                      : "TP", colorMarkBuy);
            }
            if (sellStop.HasValue)
            {
                sellStop /= sellVolumeSl;
                AddTotalDealSlTpComment(pivotIndex, sellStop.Value, hasMarksBuy
                                                                      ? "SELL SL"
                                                                      : "SL", colorMarkSell);
            }
            if (sellTake.HasValue)
            {
                sellTake /= sellVolumeTake;
                AddTotalDealSlTpComment(pivotIndex, sellTake.Value, hasMarksBuy
                                                                      ? "SELL TP"
                                                                      : "TP", colorMarkSell);
            }
        }
コード例 #16
0
        /// <summary>
        /// добавить подробные коменты по сделке
        /// </summary>
        private void ShowSelectedDealComments(MarketOrder order, bool selectedByExitMark)
        {
            var listComments = new List <string>();

            // данные по входу в рынок
            var commentMain = new StringBuilder
                                  (((DealType)order.Side).ToString() + " "
                                  + order.Volume.ToStringUniformMoneyFormat() + " "
                                  + order.Symbol + Environment.NewLine +
                                  order.TimeEnter.ToString("dd MMM HH:mm") + ", "
                                  + order.PriceEnter.ToStringUniformPriceFormat(true));

            // SL, TP, результат выхода из рынка
            if (order.TimeExit.HasValue || order.StopLoss.HasValue || order.TakeProfit.HasValue)
            {
                commentMain.AppendLine();
                if (order.StopLoss.HasValue || order.TakeProfit.HasValue)
                {
                    if (order.StopLoss.HasValue)
                    {
                        commentMain.AppendFormat("SL: {0}", order.StopLoss.Value.ToStringUniformPriceFormat());
                    }
                    if (order.StopLoss.HasValue && order.TakeProfit.HasValue)
                    {
                        commentMain.Append(" ");
                    }
                    if (order.TakeProfit.HasValue)
                    {
                        commentMain.AppendFormat("TP: {0}", order.TakeProfit.Value.ToStringUniformPriceFormat());
                    }
                    if (order.TimeExit.HasValue)
                    {
                        commentMain.AppendLine();
                    }
                }
                if (order.TimeExit.HasValue)
                {
                    commentMain.AppendFormat("Закрыт {0} по {1}",
                                             order.TimeExit.Value.ToString("dd MMM HH:mm"),
                                             // ReSharper disable PossibleInvalidOperationException
                                             order.PriceExit.Value.ToStringUniformPriceFormat());
                    // ReSharper restore PossibleInvalidOperationException
                    commentMain.AppendLine();
                    commentMain.AppendFormat("Результат: {0}",
                                             order.ResultDepo.ToStringUniformMoneyFormat());
                }
            }

            listComments.Add(commentMain.ToString());

            // предложение закрыть или редактировать ордер
            //if (!order.TimeExit.HasValue)
            //    listComments.Add("Редактировать /" + Environment.NewLine + "Закрыть");

            // точка привязки (к маркеру входа или выхода)
            var pivot = selectedByExitMark
                        // ReSharper disable PossibleInvalidOperationException
                            ? new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeExit.Value, true),
                                         order.PriceExit.Value)
                        // ReSharper restore PossibleInvalidOperationException
                            : new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeEnter, true),
                                         order.PriceEnter);

            // по текущему результату определить, прибыльный ордер или убыточный
            var profitSide = Math.Sign(order.ResultDepo);

            if (order.IsOpened)
            {
                var curPrice = owner.StockSeries.Data.Candles[owner.StockSeries.DataCount - 1].close;
                profitSide = Math.Sign(order.Side * (curPrice - order.PriceEnter));
            }
            var colorFill = profitSide > 0
                                ? Color.LightGreen : profitSide < 0 ? Color.LightCoral : Color.BlanchedAlmond;

            // таки добавить коменты
            var       angle    = selectedDealCommentAngle;
            const int arrowLen = 90;

            foreach (var text in listComments)
            {
                var x       = pivot.X;
                var price   = pivot.Y;
                var comment = new ChartComment
                {
                    Text             = text,
                    ArrowLength      = arrowLen,
                    ArrowAngle       = angle,
                    HideBox          = false,
                    HideArrow        = false,
                    DrawFrame        = true,
                    FillTransparency = 200,
                    ColorFill        = colorFill,
                    Color            = owner.visualSettings.SeriesForeColor,
                    ColorText        = owner.visualSettings.SeriesForeColor,
                    PivotIndex       = x,
                    PivotPrice       = price
                };
                // развернуть комментарий так, чтобы он не накрывал ничего лишнего и не вылезал за пределы экрана
                AdjustDealCommentArrowAngle(comment, order);
                if (order.IsClosed)
                {
                    comment.Name = "info";
                }
                seriesCommentSelected.data.Add(comment);

                angle += 120;
            }

            // пометить комментарий с предложением редактировать / закрыть ордер
            if (!order.TimeExit.HasValue)
            {
                seriesCommentSelected.data[seriesCommentSelected.data.Count - 1].Name = "edit";
            }

            // сместить угол стрелок
            selectedDealCommentAngle += 45;
            if (selectedDealCommentAngle > 360)
            {
                selectedDealCommentAngle -= 360;
            }
        }
コード例 #17
0
        /// <summary>
        /// нарисовать "полочки" уровней SL - TP
        /// </summary>
        private void ShowSelectedDealSlTpLines(MarketOrder order)
        {
            if (order.StopLoss == null && order.TakeProfit == null)
            {
                return;
            }
            var indexStart = (int)owner.StockSeries.GetDoubleIndexByTime(order.TimeEnter);
            var indexEnd   = order.TimeExit.HasValue
                               ? (int)owner.StockSeries.GetDoubleIndexByTime(order.TimeExit.Value)
                               : indexStart;
            // линия не должна быть слишком короткой
            var sizePixel = Conversion.WorldToScreen(new SizeD(indexEnd - indexStart, 0),
                                                     owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            const int targetWidth = 35;

            if (sizePixel.Width < targetWidth)
            {
                var newSize = Conversion.ScreenToWorld(new SizeD(targetWidth, 0),
                                                       owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
                var len = (int)Math.Round(newSize.Width);
                indexEnd += len;
            }

            var prices = new List <float>();
            var tags   = new List <string>();

            if (order.StopLoss.HasValue)
            {
                prices.Add(order.StopLoss.Value);
                tags.Add("SL");
            }
            if (order.TakeProfit.HasValue)
            {
                prices.Add(order.TakeProfit.Value);
                tags.Add("TP");
            }

            // добавить линии
            var priceIndex = 0;

            foreach (var price in prices)
            {
                var posLine = new TrendLine
                {
                    LineColor      = owner.StockSeries.DownLineColor,
                    ShapeAlpha     = 255,
                    ShapeFillColor = owner.StockSeries.DownLineColor,
                    LineStyle      = TrendLine.TrendLineStyle.Отрезок,
                    PenWidth       = 1,
                    PenDashStyle   = DashStyle.Dot,
                    Name           = "drag"
                };
                posLine.AddPoint(indexStart, price);
                posLine.AddPoint(indexEnd, price);
                seriesSelectedLines.data.Add(posLine);

                // добавить с каждой стороны масенький комент: SL или TP
                var comment = new ChartComment
                {
                    Text        = tags[priceIndex],
                    PivotPrice  = price,
                    ArrowAngle  = 180,
                    ArrowLength = 2,
                    PivotIndex  = indexStart,
                    ColorText   = owner.visualSettings.SeriesForeColor,
                    Color       = owner.visualSettings.SeriesForeColor,
                    DrawFrame   = false,
                    HideBox     = true,
                    HideArrow   = true,
                    Name        = "drag"
                };
                seriesCommentSelected.data.Add(comment);
                comment = new ChartComment
                {
                    Text        = tags[priceIndex],
                    PivotPrice  = price,
                    ArrowAngle  = 0,
                    ArrowLength = 2,
                    PivotIndex  = indexEnd,
                    ColorText   = owner.visualSettings.SeriesForeColor,
                    Color       = owner.visualSettings.SeriesForeColor,
                    DrawFrame   = false,
                    HideBox     = true,
                    HideArrow   = true,
                    Name        = "drag"
                };
                seriesCommentSelected.data.Add(comment);
                priceIndex++;
            }
        }
コード例 #18
0
        private void AdjustDealCommentArrowAngle(ChartComment comment, MarketOrder order)
        {
            if (!order.TimeExit.HasValue)
            {
                return;
            }
            // получить основное направление
            // (продолжение линии open - close)
            var ptE = Conversion.WorldToScreen(
                new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeEnter), order.PriceEnter),
                owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptQ = Conversion.WorldToScreen(
                // ReSharper disable PossibleInvalidOperationException
                new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeExit.Value), order.PriceExit.Value),
                // ReSharper restore PossibleInvalidOperationException
                owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptPivot = Conversion.WorldToScreen(new PointD(comment.PivotIndex, comment.PivotPrice),
                                                   owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptStart   = (Math.Abs(ptPivot.X - ptE.X) < Math.Abs(ptPivot.X - ptQ.X)) ? ptQ : ptE;
            var mainAngle = Math.Atan2(ptPivot.Y - ptStart.Y, ptPivot.X - ptStart.X) * 180 / Math.PI;

            // "округлить" угол
            mainAngle = Math.Round(mainAngle / 15) * 15;

            // расставить направления по приоритету
            const int numAngles = 8;
            var       angles    = new double[numAngles];

            angles[0] = mainAngle;
            for (var i = 0; i < numAngles / 2 - 1; i++)
            {
                var delta = (i + 1) * 360 / numAngles;
                angles[i * 2 + 1] = mainAngle + delta;
                angles[i * 2 + 2] = mainAngle - delta;
            }
            angles[numAngles - 1] = -mainAngle;

            // выбрать направление, для которого комментарий не вылезает за рамки экрана
            var foundAngle = false;
            var screenRect = seriesComment.Owner.CanvasRect;

            using (var gr = owner.CreateGraphics())
                foreach (var angle in angles)
                {
                    comment.ArrowAngle = angle;
                    var commentRect = comment.GetCommentRectangle(gr,
                                                                  owner.StockPane.WorldRect,
                                                                  owner.StockPane.CanvasRect);
                    // не вылез ли комментарий за пределы экрана?
                    if (commentRect.Left < screenRect.Left || commentRect.Top < screenRect.Top ||
                        commentRect.Right > screenRect.Right || commentRect.Bottom > screenRect.Bottom)
                    {
                        continue;
                    }
                    foundAngle = true;
                    break;
                }

            // угол поворота по-умолчанию
            if (!foundAngle)
            {
                comment.ArrowAngle = angles[0];
            }
        }