Пример #1
0
        /// <summary>
        /// Отрисовать индекс на графике
        /// </summary>
        /// <param name="isHigh">тру - если фрактал верха</param>
        /// <param name="candle">текущая свеча</param>
        /// <param name="index">индекс текущей свечи</param>
        private void DrawIndi(bool isHigh, CandleData candle, int index)
        {
            //? Из за недостатка комментариев я не очень понял какие поля зачему нужны у этого класса
            // Думаю, что ты и так знаешь, но классы которыми нужно оперировать при отрисовке, надо бы описать в документации

            /* А
             * Конечно, надо :)
             */
            var tip = new AsteriskTooltip("fractal", string.Empty)
            {
                Price       = isHigh ? (candle.high + offset) : (candle.low - offset),
                CandleIndex = index,
                //DateStart = candle.timeOpen,//? Что это и нужно ли здесь
                Sign  = "", //? Что это и нужно ли здесь
                Shape = isHigh
                            ? AsteriskTooltip.ShapeType.ГалкаВверх
                            : AsteriskTooltip.ShapeType.ГалкаВниз,
                ColorFill = isHigh ? clArrowHigh : clArrowLow,
                ColorLine = Color.Black,
                ColorText = Color.Black,
                Radius    = 6 //? Что это и нужно ли здесь
            };

            /* А
             * Sign - текст, выводимый посередине
             * Radius - каждая фигурка задана в "векторной" форме, Radius задает ее измерение (ширину, вроде) в пикс., пропорционально меняется другое измерение
             * DateStart можно не указывать, если задан CandleIndex
             */
            series.data.Add(tip);
        }
Пример #2
0
        /// <summary>
        /// поставить отметку на графике
        /// </summary>
        private void ShowPriceOnChart(CandleChartControl chart, PointD worldCoords)
        {
            var text = PricePoint == PricePointType.A ? "A" : "B";
            var name = "ScriptSetFiboMark" + text;

            // удалить старую отметку с графика
            int index;

            chart.seriesAsteriks.FindObject(a => a.Name == name, out index);
            if (index >= 0)
            {
                chart.seriesAsteriks.RemoveObjectByNum(index);
            }

            // добавить новую отметку
            var mark = new AsteriskTooltip(name, text)
            {
                Price       = (float)worldCoords.Y,
                CandleIndex = (int)(Math.Round(worldCoords.X)),
                ColorLine   = chart.chart.visualSettings.SeriesForeColor,
                Sign        = text
            };

            mark.ColorText = mark.ColorLine;
            mark.ColorFill = chart.chart.visualSettings.ChartBackColor;
            mark.Shape     = AsteriskTooltip.ShapeType.Звезда;

            chart.seriesAsteriks.data.Add(mark);
        }
Пример #3
0
        private void AddRobotHintOnChart(RobotHint hint, ChartForm chart)
        {
            // добавить отрезочек с комментарием
            if (hint.RobotHintType == RobotMark.HintType.Линия)
            {
                AddRobotHintLineOnChart(hint, chart);
                return;
            }

            // добавить звездочку
            var toolTip = new AsteriskTooltip(hint.Title, hint.Text)
            {
                Owner       = chart.chart.seriesAsteriks,
                Price       = hint.Price.Value,
                CandleIndex =
                    chart.chart.chart.StockSeries.GetIndexByCandleOpen(
                        hint.Time.Value),
                DateStart = hint.Time.Value,
                Sign      = hint.Sign,
                Radius    = 5,
                Shape     =
                    hint.RobotHintType == RobotMark.HintType.Стоп
                                          ? AsteriskTooltip.ShapeType.Квадрат
                                          : hint.RobotHintType == RobotMark.HintType.Тейк
                                                ? AsteriskTooltip.ShapeType.Квадрат
                                                : hint.RobotHintType == RobotMark.HintType.Покупка
                                                      ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                                      : hint.RobotHintType == RobotMark.HintType.Продажа
                                                            ? AsteriskTooltip.ShapeType.СтрелкаВниз
                                                            : hint.RobotHintType ==
                    RobotMark.HintType.Поджатие
                                                                  ? AsteriskTooltip.ShapeType.Звезда
                                                                  : AsteriskTooltip.ShapeType.Круг
            };

            if (!string.IsNullOrEmpty(hint.HintCode))
            {
                toolTip.Name = hint.HintCode;
            }
            if (hint.ColorFill.HasValue)
            {
                toolTip.ColorFill = hint.ColorFill.Value;
            }
            if (hint.ColorLine.HasValue)
            {
                toolTip.ColorLine = hint.ColorLine.Value;
            }
            if (hint.ColorText.HasValue)
            {
                toolTip.ColorText = hint.ColorText.Value;
            }

            chart.chart.seriesAsteriks.data.Add(toolTip);
        }
        //public void BuildSeries2(ChartControl chart)
        //{
        //    tooltipSeries.data.Clear();
        //    averageRangeList.Clear();

        //    var candles = chart.StockSeries.Data.Candles;
        //    var minimumCandles = PointsRange > 0 ? 5 : MaPeriod + 5;
        //    if (candles == null || candles.Count < minimumCandles) return;

        //    var lastRanges = new RestrictedQueue<float>(MaPeriod);
        //    float targetSize = PointsRange > 0 ? DalSpot.Instance.GetAbsValue(chart.Symbol, (float)PointsRange) : 0;

        //    var series = 0;
        //    for (var i = 0; i < candles.Count; i++)
        //    {
        //        var candle = candles[i];
        //        var range = candle.high - candle.low;
        //        lastRanges.Add(range);
        //        if (lastRanges.Length < lastRanges.MaxQueueLength && PointsRange == 0)
        //        {
        //            averageRangeList.Add(0);
        //            continue;
        //        }
        //        var avgRange = lastRanges.Average();
        //        averageRangeList.Add(avgRange);

        //        var candlePercent = range * 100 / avgRange;
        //        var isNarrow = PointsRange > 0 ? range < targetSize
        //            : candlePercent <= NarrowPercent;

        //        if (!isNarrow && series > 0)
        //        {
        //            if (series >= CandlesToSignal)
        //            {
        //                // отметить, сколько процентов данная свеча составила от обычной волатильности
        //                AddMark($"{candlePercent:F0}%", $"{candlePercent:F0}%", i, candle.open, false);
        //            }
        //            series = 0;
        //            continue;
        //        }

        //        if (!isNarrow) continue;

        //        series++;
        //        if (series >= CandlesToSignal)
        //        {
        //            AddMark($"{series}", $"{series}", i, candle.close, true);
        //        }
        //    }
        //}

        private void AddMark(string name, string text, int index, float price,
                             bool inversed)
        {
            var line = new AsteriskTooltip(name, text)
            {
                ColorLine        = Color.White,
                ColorText        = inversed ? Color.White : Color.Black,
                ColorFill        = inversed ? Color.Black : Color.White,
                CandleIndex      = index,
                Price            = price,
                Sign             = name,
                Shape            = inversed ? AsteriskTooltip.ShapeType.Круг : AsteriskTooltip.ShapeType.Квадрат,
                TransparencyText = 255
            };

            tooltipSeries.data.Add(line);
        }
Пример #5
0
        private void SetupGrid()
        {
            var blank = new AsteriskTooltip();

            grid.Columns.Add(new FastColumn(blank.Property(p => p.Name), Localizer.GetString("TitleName"))
            {
                ColumnMinWidth = 50,
                SortOrder      = FastColumnSort.Ascending
            });
            grid.Columns.Add(new FastColumn(blank.Property(p => p.ClassName), Localizer.GetString("TitleType"))
            {
                ColumnMinWidth = 50
            });
            grid.Columns.Add(new FastColumn(blank.Property(p => p.DateStart), Localizer.GetString("TitleTime"))
            {
                ColumnWidth = 97
            });
            grid.CalcSetTableMinWidth();
            grid.UserHitCell += GridUserHitCell;
        }
        private void ShowRobotDataOnChart()
        {
            var orders = MarketOrdersStorage.Instance.MarketOrders.Where(o => o.Symbol == chart.Symbol &&
                                                                         o.Magic == selectedBot.Magic).ToList();

            // показать ордера на графике
            foreach (var order in orders)
            {
                var candleIndex = (int)Math.Round(chart.chart.StockSeries.GetDoubleIndexByTime(order.TimeEnter));
                var shape       = order.Side > 0
                                ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                : AsteriskTooltip.ShapeType.СтрелкаВниз;

                var objectExists = chart.seriesAsteriks.data.Any(a =>
                                                                 a.Price.RoughCompares(order.PriceEnter, 0.00001f) && a.CandleIndex == candleIndex &&
                                                                 a.Shape == shape);
                if (objectExists)
                {
                    continue;
                }

                var asterisk = new AsteriskTooltip(order.Side < 0 ? "SELL" : "BUY",
                                                   selectedBot.GetUniqueName() + ": " + order.ToStringShort())
                {
                    ColorFill   = order.Side < 0 ? colorSell : colorBuy,
                    Price       = order.PriceEnter,
                    CandleIndex = candleIndex,
                    DateStart   = order.TimeEnter,
                    Shape       = shape,
                    Sign        = order.Side > 0 ? "b" : "s",
                    Owner       = chart.seriesAsteriks
                };
                chart.seriesAsteriks.data.Add(asterisk);
            }

            AddChartCommentOnRobotState(orders.Count);
        }
        private void BuildChannel(List <CandleData> candles, int from)
        {
            var channel = new Cortege3 <PointD, PointD, PointD> {
            };
            var state   = ChannelStateInfo.НетКанала;

            switch (ChannelState)
            {
            case ChannelStateInfo.НетКанала:
                // канала еще нет, ищем сначала по верхним точкам, если не находим, пробуем по нижним найти
                var channelhigh = GetHighLineChannel(candles, from);
                var channellow  = GetLowLineChannel(candles, from);
                if ((channelhigh.a == new PointD(0, 0) || channelhigh.b == new PointD(0, 0)) &&
                    (channellow.a == new PointD(0, 0) || channellow.b == new PointD(0, 0)))
                {
                    break;
                }

                if (channelhigh.a == new PointD(0, 0) || channelhigh.b == new PointD(0, 0))
                {
                    state   = ChannelStateInfo.ПостроенПоМинимумам;
                    channel = channellow;
                    break;
                }
                if ((channellow.a == new PointD(0, 0) || channellow.b == new PointD(0, 0)))
                {
                    state   = ChannelStateInfo.ПостроенПоМаксимумам;
                    channel = channelhigh;
                    break;
                }

                if (channelhigh.b.X > channellow.b.X || (channelhigh.b.X == channellow.b.X && channelhigh.a.X > channellow.a.X))
                {
                    state   = ChannelStateInfo.ПостроенПоМаксимумам;
                    channel = channelhigh;
                    break;
                }
                state   = ChannelStateInfo.ПостроенПоМинимумам;
                channel = channellow;
                break;

            case ChannelStateInfo.ПостроенПоМаксимумам:
                channel = GetLowLineChannel(candles, from);
                if (channel.a == new PointD(0, 0) || channel.b == new PointD(0, 0))
                {
                    return;
                }
                state = ChannelStateInfo.ПостроенПоМинимумам;
                break;

            case ChannelStateInfo.ПостроенПоМинимумам:
                channel = GetHighLineChannel(candles, from);
                if (channel.a == new PointD(0, 0) || channel.b == new PointD(0, 0))
                {
                    return;
                }
                state = ChannelStateInfo.ПостроенПоМаксимумам;
                break;
            }



            if (lastIndexB == 0 && lastIndexA == 0)
            {
                lastIndexA = channel.a.X;
                lastIndexB = channel.b.X;
            }

            if (lastIndexB == channel.b.X && lastIndexA < channel.a.X)
            {
                // найденный канал старше текущего, игнорируем
                return;
            }

            if (!ShowAllChannels && lastIndexB > channel.b.X)
            {
                // найденный канал уже старый, игнорируем его
                channel = currChannel;
            }
            var a = channel.a;
            var b = channel.b;
            var k = (b.Y - a.Y) / (b.X - a.X);

            // стираем старый канал
            if (!ShowAllChannels)
            {
                series.data.Clear();
            }

            // находим точку на текущей свече + 1, туда и продлим канал
            var bx = 0;

            if (series.data.Count == 0)
            {
                bx = candles.Count;
            }
            else
            {
                bx = (int)b.X + CountAfter + CountForward;
            }

            if (TradePoints)
            {
                // просто покажем точки входа и все
                // посчитаем точки входа если они есть
                for (var i = (int)b.X + CountAfter + 1; i < b.X + CountAfter + CountForward; i++)
                {
                    if (candles.Count <= i)
                    {
                        break;
                    }
                    var highY = b.Y + k * (i - b.X);
                    var lowY  = channel.c.Y + k * (i - channel.c.X);
                    if (highY <= candles[i].high && highY >= candles[i].low)
                    {
                        var detailed = string.Format("S {0}", highY);
                        var tip      = new AsteriskTooltip(detailed, detailed)
                        {
                            Price       = (float)highY,
                            CandleIndex = i,
                            DateStart   = candles[i].timeOpen,
                            Sign        = "e",
                            Shape       = AsteriskTooltip.ShapeType.СтрелкаВниз,
                            ColorFill   = Color.Pink,
                            ColorLine   = Color.Black,
                            ColorText   = Color.Black
                        };
                        commentSeries.data.Add(tip);
                        break;
                    }
                    if (lowY >= candles[i].low && lowY <= candles[i].high)
                    {
                        var detailed = string.Format("B {0}", lowY);
                        var tip      = new AsteriskTooltip(detailed, detailed)
                        {
                            Price       = (float)lowY,
                            CandleIndex = i,
                            DateStart   = candles[i].timeOpen,
                            Sign        = "e",
                            Shape       = AsteriskTooltip.ShapeType.СтрелкаВверх,
                            ColorFill   = Color.Green,
                            ColorLine   = Color.Black,
                            ColorText   = Color.Black
                        };
                        commentSeries.data.Add(tip);
                        break;
                    }
                }
            }
            else
            {
                var line = new TrendLine
                {
                    LineColor = state == ChannelStateInfo.ПостроенПоМаксимумам ? ClUpLine : ClDownLine,
                    LineStyle = TrendLine.TrendLineStyle.Отрезок
                };
                // линия по двум экстремумам
                line.linePoints.Add(new PointD(a.X - countBefore, b.Y + k * (a.X - countBefore - b.X)));
                line.linePoints.Add(new PointD(bx, b.Y + k * (bx - b.X)));
                series.data.Add(line);


                line = new TrendLine
                {
                    LineColor = state == ChannelStateInfo.ПостроенПоМаксимумам ? ClUpLine : ClDownLine,
                    LineStyle = TrendLine.TrendLineStyle.Отрезок
                };
                var c = channel.c;
                // линия по одному экстремуму
                line.linePoints.Add(new PointD(a.X - countBefore, c.Y + k * (a.X - countBefore - c.X)));
                line.linePoints.Add(new PointD(bx, c.Y + k * (bx - c.X)));
                series.data.Add(line);
            }
            ChannelState = state;
            currChannel  = channel;
            lastIndexA   = currChannel.a.X;
            lastIndexB   = currChannel.b.X;
        }
Пример #8
0
        /// <summary>
        /// результаты моделирования необходимо отобразить на графиках
        /// (в виде коментариев и т.д.)
        /// </summary>
        private void OnRobotResultsBoundToCharts(Dictionary <BaseRobot, ChartWindowSettings> robotBindings,
                                                 List <RobotLogEntry> robotLogEntries, List <MarketOrder> posClosed, List <MarketOrder> posOpened)
        {
            // предложить убрать коментарии с графиков,
            // выбрать коментарии
            var dlg = new ResultDisplaySettingsForm();

            if (dlg.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            // убрать коментарии?
            var removeOldComments = dlg.RemoveOldMarkers;

            if (removeOldComments)
            {
                var chartsToPurge = Charts.Where(c => robotBindings.Any(
                                                     rb => rb.Value.TabPageId == c.bookmarkId && rb.Value.Symbol == c.chart.Symbol &&
                                                     rb.Value.Timeframe == c.chart.timeframeString));
                foreach (var chart in chartsToPurge)
                {
                    chart.chart.seriesAsteriks.data.Clear();
                }
            }

            foreach (var robotBinding in robotBindings)
            {
                // найти график для робота
                var timeframe = robotBinding.Value.Timeframe;
                var ticker    = robotBinding.Value.Symbol;
                var pageId    = robotBinding.Value.TabPageId;
                var robot     = robotBinding.Key;
                var chart     = Charts.First(c => c.chart.timeframeString == timeframe && c.chart.Symbol == ticker &&
                                             c.bookmarkId == pageId);

                // выбрать все сообщения для графика
                var logEntries        = robotLogEntries.Where(l => l.Robot == robot);
                var messagesPlainList = new List <string>();
                foreach (var logEntry in logEntries)
                {
                    messagesPlainList.AddRange(logEntry.Messages);
                }

                // добавить коментарии на график
                foreach (var msg in messagesPlainList)
                {
                    var mark = RobotMark.ParseString(msg);
                    if (mark == null || mark is RobotHint == false)
                    {
                        continue;
                    }

                    var hint = (RobotHint)mark;
                    if (!hint.Price.HasValue || !hint.Time.HasValue)
                    {
                        continue;
                    }

                    AddOrRemoveRobotHintOnChart(hint, chart);
                }

                // добавить информацию о сделках
                if (!dlg.ShowMarkers)
                {
                    continue;
                }

                // выбрать сделки для отображения
                var deals4Chart = posClosed.Where(p => p.Symbol == chart.chart.Symbol).ToList();
                deals4Chart.AddRange(posOpened.Where(p => p.Symbol == chart.chart.Symbol));

                foreach (var deal in deals4Chart)
                {
                    // отметки входа
                    if (dlg.ShowEnters)
                    {
                        var detailed = string.Format("#{0} {1} {2:dd.MM.yyyy HH:mm} по {3}",
                                                     deal.ID, deal.Side > 0 ? "B" : "S", deal.TimeEnter, deal.PriceEnter);
                        if (deal.IsClosed)
                        {
                            var result = (deal.PriceExit.Value - deal.PriceEnter) * deal.Side;
                            var points = DalSpot.Instance.GetPointsValue(deal.Symbol, result);
                            detailed += string.Format(" - {0:dd.MM.yyyy HH:mm} по {1}, {2:f0} пп",
                                                      deal.TimeExit.Value, deal.PriceExit.Value,
                                                      points);
                        }
                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price       = deal.PriceEnter,
                            CandleIndex = chart.chart.chart.StockSeries.GetIndexByCandleOpen(deal.TimeEnter),
                            DateStart   = deal.TimeEnter,
                            Sign        = "e",
                            Shape       = deal.Side > 0 ? AsteriskTooltip.ShapeType.СтрелкаВверх :
                                          AsteriskTooltip.ShapeType.СтрелкаВниз,
                            ColorFill = deal.Side > 0 ? Color.Green : Color.Salmon,
                            ColorLine = Color.Black,
                            ColorText = Color.Black,
                            Radius    = 5
                        };
                        if (!dlg.ShowDetailedEnters)
                        {
                            tip.Name = string.Format("Сделка #{0}, {1}", deal.ID, deal.Side > 0 ? "Buy" : "Sell");
                        }
                        chart.chart.seriesAsteriks.data.Add(tip);
                    }

                    if (dlg.ShowExits && deal.IsClosed)
                    {
                        var detailed = string.Format("Выход #{0} {1} {2:dd.MM.yyyy HH:mm} по {3} - {4:dd.MM.yyyy HH:mm} по {5}",
                                                     deal.ID, deal.Side > 0 ? "B" : "S", deal.TimeEnter, deal.PriceEnter,
                                                     deal.TimeExit.Value, deal.PriceExit.Value);

                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price       = deal.PriceExit.Value,
                            CandleIndex =
                                chart.chart.chart.StockSeries.GetIndexByCandleOpen(
                                    deal.TimeExit.Value),
                            DateStart = deal.TimeExit.Value,
                            Sign      = "q",
                            Shape     = AsteriskTooltip.ShapeType.Квадрат,
                            ColorFill = deal.Side > 0 ? Color.Green : Color.Salmon,
                            ColorLine = Color.Black,
                            ColorText = Color.Black,
                            Radius    = 5
                        };
                        if (!dlg.ShowDetailedExits)
                        {
                            tip.Name = string.Format("Закрытие #{0}, {1}", deal.ID, deal.Side > 0 ? "Buy" : "Sell");
                        }
                        chart.chart.seriesAsteriks.data.Add(tip);
                    }
                }
            }
        }
Пример #9
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);
                }
            }
        }
Пример #10
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);
            }
        }
        /// <summary>
        /// поставить отметку на графике
        /// </summary>
        private void ShowPriceOnChart(CandleChartControl chart, PointD worldCoords)
        {
            var text = PricePoint == PricePointType.A ? "A" : "B";
            var name = "ScriptSetFiboMark" + text;

            // удалить старую отметку с графика
            int index;
            chart.seriesAsteriks.FindObject(a => a.Name == name, out index);
            if (index >= 0)
                chart.seriesAsteriks.RemoveObjectByNum(index);

            // добавить новую отметку
            var mark = new AsteriskTooltip(name, text)
                           {
                               Price = (float) worldCoords.Y,
                               CandleIndex = (int) (Math.Round(worldCoords.X)),
                               ColorLine = chart.chart.visualSettings.SeriesForeColor,
                               Sign = text
                           };
            mark.ColorText = mark.ColorLine;
            mark.ColorFill = chart.chart.visualSettings.ChartBackColor;
            mark.Shape = AsteriskTooltip.ShapeType.Звезда;

            chart.seriesAsteriks.data.Add(mark);
        }
Пример #12
0
        /// <summary>
        /// Отрисовать индекс на графике
        /// </summary>
        /// <param name="isHigh">тру - если фрактал верха</param>
        /// <param name="candle">текущая свеча</param>
        /// <param name="index">индекс текущей свечи</param>
        private void DrawIndi(bool isHigh, CandleData candle, int index)
        {
            //? Из за недостатка комментариев я не очень понял какие поля зачему нужны у этого класса
            // Думаю, что ты и так знаешь, но классы которыми нужно оперировать при отрисовке, надо бы описать в документации

            /* А
               Конечно, надо :)
              */
            var tip = new AsteriskTooltip("fractal", string.Empty)
            {
                Price = isHigh ? (candle.high + offset) : (candle.low - offset),
                CandleIndex = index,
                //DateStart = candle.timeOpen,//? Что это и нужно ли здесь
                Sign = "", //? Что это и нужно ли здесь
                Shape = isHigh
                            ? AsteriskTooltip.ShapeType.ГалкаВверх
                            : AsteriskTooltip.ShapeType.ГалкаВниз,
                ColorFill = isHigh ? clArrowHigh : clArrowLow,
                ColorLine = Color.Black,
                ColorText = Color.Black,
                Radius = 6 //? Что это и нужно ли здесь
            };
            /* А
               Sign - текст, выводимый посередине
               Radius - каждая фигурка задана в "векторной" форме, Radius задает ее измерение (ширину, вроде) в пикс., пропорционально меняется другое измерение
               DateStart можно не указывать, если задан CandleIndex
             */
            series.data.Add(tip);
        }
Пример #13
0
        private void BuildChannel(List<CandleData> candles, int from)
        {
            var channel = new Cortege3<PointD, PointD, PointD> { };
            var state = ChannelStateInfo.НетКанала;
            switch (ChannelState)
            {
                case ChannelStateInfo.НетКанала:
                    // канала еще нет, ищем сначала по верхним точкам, если не находим, пробуем по нижним найти
                    var channelhigh = GetHighLineChannel(candles, from);
                    var channellow = GetLowLineChannel(candles, from);
                    if ((channelhigh.a == new PointD(0, 0) || channelhigh.b == new PointD(0, 0))
                        && (channellow.a == new PointD(0, 0) || channellow.b == new PointD(0, 0)))
                        break;

                    if (channelhigh.a == new PointD(0, 0) || channelhigh.b == new PointD(0, 0))
                    {
                        state = ChannelStateInfo.ПостроенПоМинимумам;
                        channel = channellow;
                        break;
                    }
                    if ((channellow.a == new PointD(0, 0) || channellow.b == new PointD(0, 0)))
                    {
                        state = ChannelStateInfo.ПостроенПоМаксимумам;
                        channel = channelhigh;
                        break;
                    }

                    if (channelhigh.b.X > channellow.b.X || (channelhigh.b.X == channellow.b.X && channelhigh.a.X > channellow.a.X))
                    {
                        state = ChannelStateInfo.ПостроенПоМаксимумам;
                        channel = channelhigh;
                        break;
                    }
                    state = ChannelStateInfo.ПостроенПоМинимумам;
                    channel = channellow;
                    break;

                case ChannelStateInfo.ПостроенПоМаксимумам:
                    channel = GetLowLineChannel(candles, from);
                    if (channel.a == new PointD(0, 0) || channel.b == new PointD(0, 0))
                        return;
                    state = ChannelStateInfo.ПостроенПоМинимумам;
                    break;
                case ChannelStateInfo.ПостроенПоМинимумам:
                    channel = GetHighLineChannel(candles, from);
                    if (channel.a == new PointD(0, 0) || channel.b == new PointD(0, 0))
                        return;
                    state = ChannelStateInfo.ПостроенПоМаксимумам;
                    break;
            }

            if (lastIndexB == 0 && lastIndexA == 0)
            {
                lastIndexA = channel.a.X;
                lastIndexB = channel.b.X;
            }

            if (lastIndexB == channel.b.X && lastIndexA < channel.a.X)
            {
                // найденный канал старше текущего, игнорируем
                return;
            }

            if (!ShowAllChannels && lastIndexB > channel.b.X)
            {
                // найденный канал уже старый, игнорируем его
                channel = currChannel;
            }
            var a = channel.a;
            var b = channel.b;
            var k = (b.Y - a.Y) / (b.X - a.X);
            // стираем старый канал
            if (!ShowAllChannels)
                series.data.Clear();

            // находим точку на текущей свече + 1, туда и продлим канал
            var bx = 0;
            if (series.data.Count == 0)
                bx = candles.Count;
            else
                bx = (int)b.X + CountAfter + CountForward;

            if (TradePoints)
            {
                // просто покажем точки входа и все
                // посчитаем точки входа если они есть
                for (var i = (int)b.X + CountAfter + 1; i < b.X + CountAfter + CountForward; i++)
                {
                    if (candles.Count <= i) break;
                    var highY = b.Y + k*(i - b.X);
                    var lowY = channel.c.Y + k*(i - channel.c.X);
                    if (highY <= candles[i].high && highY >= candles[i].low)
                    {
                        var detailed = string.Format("S {0}", highY);
                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price = (float)highY,
                            CandleIndex = i,
                            DateStart = candles[i].timeOpen,
                            Sign = "e",
                            Shape = AsteriskTooltip.ShapeType.СтрелкаВниз,
                            ColorFill = Color.Pink,
                            ColorLine = Color.Black,
                            ColorText = Color.Black
                        };
                        commentSeries.data.Add(tip);
                        break;
                    }
                    if (lowY >= candles[i].low && lowY <= candles[i].high)
                    {
                        var detailed = string.Format("B {0}", lowY);
                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price = (float)lowY,
                            CandleIndex = i,
                            DateStart = candles[i].timeOpen,
                            Sign = "e",
                            Shape = AsteriskTooltip.ShapeType.СтрелкаВверх,
                            ColorFill = Color.Green,
                            ColorLine = Color.Black,
                            ColorText = Color.Black
                        };
                        commentSeries.data.Add(tip);
                        break;
                    }
                }
            }
            else
            {
                var line = new TrendLine
                               {
                                   LineColor = state == ChannelStateInfo.ПостроенПоМаксимумам ? ClUpLine : ClDownLine,
                                   LineStyle = TrendLine.TrendLineStyle.Отрезок
                               };
                // линия по двум экстремумам
                line.linePoints.Add(new PointD(a.X - countBefore, b.Y + k*(a.X - countBefore - b.X)));
                line.linePoints.Add(new PointD(bx, b.Y + k*(bx - b.X)));
                series.data.Add(line);

                line = new TrendLine
                           {
                               LineColor = state == ChannelStateInfo.ПостроенПоМаксимумам ? ClUpLine : ClDownLine,
                               LineStyle = TrendLine.TrendLineStyle.Отрезок
                           };
                var c = channel.c;
                // линия по одному экстремуму
                line.linePoints.Add(new PointD(a.X - countBefore, c.Y + k*(a.X - countBefore - c.X)));
                line.linePoints.Add(new PointD(bx, c.Y + k*(bx - c.X)));
                series.data.Add(line);
            }
            ChannelState = state;
            currChannel = channel;
            lastIndexA = currChannel.a.X;
            lastIndexB = currChannel.b.X;
        }
Пример #14
0
        /// <summary>
        /// результаты моделирования необходимо отобразить на графиках
        /// (в виде коментариев и т.д.)
        /// </summary>        
        private void OnRobotResultsBoundToCharts(Dictionary<BaseRobot, ChartWindowSettings> robotBindings,
            List<RobotLogEntry> robotLogEntries, List<MarketOrder> posClosed, List<MarketOrder> posOpened)
        {
            // предложить убрать коментарии с графиков,
            // выбрать коментарии
            var dlg = new ResultDisplaySettingsForm();
            if (dlg.ShowDialog() == DialogResult.Cancel) return;
            // убрать коментарии?
            var removeOldComments = dlg.RemoveOldMarkers;
            if (removeOldComments)
            {
                var chartsToPurge = Charts.Where(c => robotBindings.Any(
                    rb => rb.Value.TabPageId == c.bookmarkId && rb.Value.Symbol == c.chart.Symbol &&
                        rb.Value.Timeframe == c.chart.timeframeString));
                foreach (var chart in chartsToPurge)
                    chart.chart.seriesAsteriks.data.Clear();
            }

            foreach (var robotBinding in robotBindings)
            {
                // найти график для робота
                var timeframe = robotBinding.Value.Timeframe;
                var ticker = robotBinding.Value.Symbol;
                var pageId = robotBinding.Value.TabPageId;
                var robot = robotBinding.Key;
                var chart = Charts.First(c => c.chart.timeframeString == timeframe && c.chart.Symbol == ticker
                    && c.bookmarkId == pageId);

                // выбрать все сообщения для графика
                var logEntries = robotLogEntries.Where(l => l.Robot == robot);
                var messagesPlainList = new List<string>();
                foreach (var logEntry in logEntries)
                    messagesPlainList.AddRange(logEntry.Messages);

                // добавить коментарии на график
                foreach (var msg in messagesPlainList)
                {
                    var mark = RobotMark.ParseString(msg);
                    if (mark == null || mark is RobotHint == false)
                        continue;

                    var hint = (RobotHint) mark;
                    if (!hint.Price.HasValue || !hint.Time.HasValue) continue;

                    AddOrRemoveRobotHintOnChart(hint, chart);
                }

                // добавить информацию о сделках
                if (!dlg.ShowMarkers) continue;

                // выбрать сделки для отображения
                var deals4Chart = posClosed.Where(p => p.Symbol == chart.chart.Symbol).ToList();
                deals4Chart.AddRange(posOpened.Where(p => p.Symbol == chart.chart.Symbol));

                foreach (var deal in deals4Chart)
                {
                    // отметки входа
                    if (dlg.ShowEnters)
                    {
                        var detailed = string.Format("#{0} {1} {2:dd.MM.yyyy HH:mm} по {3}",
                            deal.ID, deal.Side > 0 ? "B" : "S", deal.TimeEnter, deal.PriceEnter);
                        if (deal.IsClosed)
                        {
                            var result = (deal.PriceExit.Value - deal.PriceEnter) * deal.Side;
                            var points = DalSpot.Instance.GetPointsValue(deal.Symbol, result);
                            detailed += string.Format(" - {0:dd.MM.yyyy HH:mm} по {1}, {2:f0} пп",
                                                     deal.TimeExit.Value, deal.PriceExit.Value,
                                                     points);
                        }
                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price = deal.PriceEnter,
                            CandleIndex = chart.chart.chart.StockSeries.GetIndexByCandleOpen(deal.TimeEnter),
                            DateStart = deal.TimeEnter,
                            Sign = "e",
                            Shape = deal.Side > 0 ? AsteriskTooltip.ShapeType.СтрелкаВверх :
                                                AsteriskTooltip.ShapeType.СтрелкаВниз,
                            ColorFill = deal.Side > 0 ? Color.Green : Color.Salmon,
                            ColorLine = Color.Black,
                            ColorText = Color.Black,
                            Radius = 5
                        };
                        if (!dlg.ShowDetailedEnters)
                            tip.Name = string.Format("Сделка #{0}, {1}", deal.ID, deal.Side > 0 ? "Buy" : "Sell");
                        chart.chart.seriesAsteriks.data.Add(tip);
                    }

                    if (dlg.ShowExits && deal.IsClosed)
                    {
                        var detailed = string.Format("Выход #{0} {1} {2:dd.MM.yyyy HH:mm} по {3} - {4:dd.MM.yyyy HH:mm} по {5}",
                                                     deal.ID, deal.Side > 0 ? "B" : "S", deal.TimeEnter, deal.PriceEnter,
                                                     deal.TimeExit.Value, deal.PriceExit.Value);

                        var tip = new AsteriskTooltip(detailed, detailed)
                        {
                            Price = deal.PriceExit.Value,
                            CandleIndex =
                                chart.chart.chart.StockSeries.GetIndexByCandleOpen(
                                    deal.TimeExit.Value),
                            DateStart = deal.TimeExit.Value,
                            Sign = "q",
                            Shape = AsteriskTooltip.ShapeType.Квадрат,
                            ColorFill = deal.Side > 0 ? Color.Green : Color.Salmon,
                            ColorLine = Color.Black,
                            ColorText = Color.Black,
                            Radius = 5
                        };
                        if (!dlg.ShowDetailedExits)
                            tip.Name = string.Format("Закрытие #{0}, {1}", deal.ID, deal.Side > 0 ? "Buy" : "Sell");
                        chart.chart.seriesAsteriks.data.Add(tip);
                    }
                }
            }
        }
Пример #15
0
        private void AddRobotHintOnChart(RobotHint hint, ChartForm chart)
        {
            // добавить отрезочек с комментарием
            if (hint.RobotHintType == RobotMark.HintType.Линия)
            {
                AddRobotHintLineOnChart(hint, chart);
                return;
            }

            // добавить звездочку
            var toolTip = new AsteriskTooltip(hint.Title, hint.Text)
                              {
                                  Owner = chart.chart.seriesAsteriks,
                                  Price = hint.Price.Value,
                                  CandleIndex =
                                      chart.chart.chart.StockSeries.GetIndexByCandleOpen(
                                          hint.Time.Value),
                                  DateStart = hint.Time.Value,
                                  Sign = hint.Sign,
                                  Radius = 5,
                                  Shape =
                                      hint.RobotHintType == RobotMark.HintType.Стоп
                                          ? AsteriskTooltip.ShapeType.Квадрат
                                          : hint.RobotHintType == RobotMark.HintType.Тейк
                                                ? AsteriskTooltip.ShapeType.Квадрат
                                                : hint.RobotHintType == RobotMark.HintType.Покупка
                                                      ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                                      : hint.RobotHintType == RobotMark.HintType.Продажа
                                                            ? AsteriskTooltip.ShapeType.СтрелкаВниз
                                                            : hint.RobotHintType ==
                                                              RobotMark.HintType.Поджатие
                                                                  ? AsteriskTooltip.ShapeType.Звезда
                                                                  : AsteriskTooltip.ShapeType.Круг
                              };
            if (!string.IsNullOrEmpty(hint.HintCode))
                toolTip.Name = hint.HintCode;
            if (hint.ColorFill.HasValue) toolTip.ColorFill = hint.ColorFill.Value;
            if (hint.ColorLine.HasValue) toolTip.ColorLine = hint.ColorLine.Value;
            if (hint.ColorText.HasValue) toolTip.ColorText = hint.ColorText.Value;

            chart.chart.seriesAsteriks.data.Add(toolTip);
        }
Пример #16
0
        private void ShowRobotDataOnChart()
        {
            var orders = MarketOrdersStorage.Instance.MarketOrders.Where(o => o.Symbol == chart.Symbol
                && o.Magic == selectedBot.Magic).ToList();

            // показать ордера на графике
            foreach (var order in orders)
            {
                var candleIndex = (int)Math.Round(chart.chart.StockSeries.GetDoubleIndexByTime(order.TimeEnter));
                var shape = order.Side > 0
                                ? AsteriskTooltip.ShapeType.СтрелкаВверх
                                : AsteriskTooltip.ShapeType.СтрелкаВниз;

                var objectExists = chart.seriesAsteriks.data.Any(a =>
                    a.Price.RoughCompares(order.PriceEnter, 0.00001f) && a.CandleIndex == candleIndex &&
                    a.Shape == shape);
                if (objectExists) continue;

                var asterisk = new AsteriskTooltip(order.Side < 0 ? "SELL" : "BUY",
                                                   selectedBot.GetUniqueName() + ": " + order.ToStringShort())
                {
                    ColorFill = order.Side < 0 ? colorSell : colorBuy,
                    Price = order.PriceEnter,
                    CandleIndex = candleIndex,
                    DateStart = order.TimeEnter,
                    Shape = shape,
                    Sign = order.Side > 0 ? "b" : "s",
                    Owner = chart.seriesAsteriks
                };
                chart.seriesAsteriks.data.Add(asterisk);
            }

            AddChartCommentOnRobotState(orders.Count);
        }