Example #1
0
        public override Cursor GetCursor(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, Point point)
        {
            if (!IsVisible)
            {
                return(null);
            }

            switch (DrawingState)
            {
            case DrawingState.Building: return(Cursors.Pen);

            case DrawingState.Moving: return(IsLocked ? Cursors.No : Cursors.SizeAll);

            case DrawingState.Editing:
                if (IsLocked)
                {
                    return(Cursors.No);
                }
                return(editingAnchor == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE);

            default:
                Point startAnchorPixelPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale);

                ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point);
                if (closest != null)
                {
                    if (IsLocked)
                    {
                        return(Cursors.Arrow);
                    }
                    return(closest == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE);
                }

                // Check the anchor lines for cursor
                Point  endAnchorPixelPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale);
                Point  extAnchorPixelPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale);
                Point  midAnchorPixelPoint = new Point((endAnchorPixelPoint.X + extAnchorPixelPoint.X) / 2, (endAnchorPixelPoint.Y + extAnchorPixelPoint.Y) / 2);
                Vector startToEndVec       = endAnchorPixelPoint - startAnchorPixelPoint;
                Vector endToExtVec         = extAnchorPixelPoint - endAnchorPixelPoint;
                Vector startToMidVec       = midAnchorPixelPoint - startAnchorPixelPoint;

                foreach (Tuple <Point, Point> endPoint in GetAndrewsEndPoints(chartControl, chartScale))
                {
                    Vector andrewVector = endPoint.Item1 - endPoint.Item2;
                    if (MathHelper.IsPointAlongVector(point, endPoint.Item2, andrewVector, cursorSensitivity))
                    {
                        return(IsLocked ? Cursors.Arrow : Cursors.SizeAll);
                    }
                }

                return(MathHelper.IsPointAlongVector(point, startAnchorPixelPoint, startToEndVec, cursorSensitivity) ||
                       MathHelper.IsPointAlongVector(point, endAnchorPixelPoint, endToExtVec, cursorSensitivity) ||
                       MathHelper.IsPointAlongVector(point, startAnchorPixelPoint, startToMidVec, cursorSensitivity) ?
                       (IsLocked ? Cursors.Arrow : Cursors.SizeAll) : null);
            }
        }
Example #2
0
        public override bool IsVisibleOnChart(ChartControl chartControl, ChartScale chartScale, DateTime firstTimeOnChart, DateTime lastTimeOnChart)
        {
            // First check any of the actual anchors are visible, we are immediately done
            foreach (ChartAnchor anchor in Anchors)
            {
                if (anchor.IsEditing || anchor.Time >= firstTimeOnChart && anchor.Time <= lastTimeOnChart)
                {
                    return(true);
                }
            }

            // Calculate extensions and see if they extend into our visible times
            ChartPanel chartPanel           = chartControl.ChartPanels[PanelIndex];
            Point      anchorStartPoint     = StartAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorEndPoint       = EndAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      midPointExtension    = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2);

            if (CalculationMethod == AndrewsPitchforkCalculationMethod.Schiff)
            {
                anchorStartPoint = new Point(anchorStartPoint.X, (anchorStartPoint.Y + anchorEndPoint.Y) / 2);
            }
            else if (CalculationMethod == AndrewsPitchforkCalculationMethod.ModifiedSchiff)
            {
                anchorStartPoint = new Point((anchorEndPoint.X + anchorStartPoint.X) / 2, (anchorEndPoint.Y + anchorStartPoint.Y) / 2);
            }

            double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price;
            double startPrice      = ExtensionAnchor.Price;

            foreach (PriceLevel priceLevel in PriceLevels.Where(pl => pl.IsVisible && pl.Stroke != null))
            {
                double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange));
                float  pixelY     = chartScale.GetYByValue(levelPrice);
                float  pixelX     = anchorExtensionPoint.X > anchorEndPoint.X ?
                                    (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) :
                                    (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)));

                Point startPoint    = new Point(pixelX, pixelY);
                Point endPoint      = new Point(startPoint.X + (midPointExtension.X - anchorStartPoint.X), startPoint.Y + (midPointExtension.Y - anchorStartPoint.Y));
                Point maxLevelPoint = GetExtendedPoint(startPoint, endPoint);

                double padding = 5d;
                foreach (Point chkPoint in new[] { startPoint, maxLevelPoint, endPoint })
                {
                    if (chkPoint.X >= chartPanel.X - padding && chkPoint.X <= chartPanel.W + chartPanel.X + padding &&
                        chkPoint.Y >= chartPanel.Y - padding && chkPoint.Y <= chartPanel.Y + chartPanel.H + padding)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Example #3
0
        public override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale)
        {
            if (!IsVisible)
            {
                return(new Point[0]);
            }

            ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex];
            Point      startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      endPoint   = EndAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      midPoint   = new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2);
            Point      extPoint   = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale);

            return(new[] { startPoint, midPoint, endPoint, extPoint });
        }
Example #4
0
        private IEnumerable <Tuple <Point, Point> > GetAndrewsEndPoints(ChartControl chartControl, ChartScale chartScale)
        {
            ChartPanel panel                = chartControl.ChartPanels[PanelIndex];
            double     totalPriceRange      = EndAnchor.Price - ExtensionAnchor.Price;
            double     startPrice           = ExtensionAnchor.Price;
            Point      anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, panel, chartScale);
            Point      anchorStartPoint     = StartAnchor.GetPoint(chartControl, panel, chartScale);
            Point      anchorEndPoint       = EndAnchor.GetPoint(chartControl, panel, chartScale);
            Point      midPointExtension    = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2);

            foreach (PriceLevel pl in PriceLevels.Where(pl => pl.IsVisible))
            {
                double levelPrice = (startPrice + ((pl.Value / 100) * totalPriceRange));
                float  pixelY     = chartScale.GetYByValue(levelPrice);
                float  pixelX     = anchorExtensionPoint.X > anchorEndPoint.X ?
                                    (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (pl.Value / 100)))) :
                                    (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (pl.Value / 100)));

                Point startPoint    = new Point(pixelX, pixelY);
                Point endPoint      = new Point(startPoint.X + (midPointExtension.X - anchorStartPoint.X), startPoint.Y + (midPointExtension.Y - anchorStartPoint.Y));
                Point maxLevelPoint = GetExtendedPoint(startPoint, endPoint);
                yield return(new Tuple <Point, Point>(new Point(Math.Max(maxLevelPoint.X, 1), Math.Max(maxLevelPoint.Y, 1)), startPoint));
            }
        }
Example #5
0
        public override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            if (Anchors.All(a => a.IsEditing))
            {
                return;
            }

            RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;

            ChartPanel chartPanel           = chartControl.ChartPanels[PanelIndex];
            Point      anchorStartPoint     = StartAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorEndPoint       = EndAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      midPointExtension    = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2);

            if (CalculationMethod == AndrewsPitchforkCalculationMethod.Schiff)
            {
                anchorStartPoint = new Point(anchorStartPoint.X, (anchorStartPoint.Y + anchorEndPoint.Y) / 2);
            }
            else if (CalculationMethod == AndrewsPitchforkCalculationMethod.ModifiedSchiff)
            {
                anchorStartPoint = new Point((anchorEndPoint.X + anchorStartPoint.X) / 2, (anchorEndPoint.Y + anchorStartPoint.Y) / 2);
            }

            AnchorLineStroke.RenderTarget      = RenderTarget;
            RetracementLineStroke.RenderTarget = RenderTarget;

            // Align to full pixel to avoid unneeded aliasing
            double strokePixAdj   = AnchorLineStroke.Width % 2 == 0 ? 0.5d : 0d;
            Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj);

            SharpDX.Vector2         startVec = (anchorStartPoint + pixelAdjustVec).ToVector2();
            SharpDX.Vector2         endVec   = (anchorEndPoint + pixelAdjustVec).ToVector2();
            SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : AnchorLineStroke.BrushDX;

            SharpDX.Vector2 startOriginVec = (StartAnchor.GetPoint(chartControl, chartPanel, chartScale) + pixelAdjustVec).ToVector2();

            RenderTarget.DrawLine(startOriginVec, endVec, tmpBrush, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle);

            // Is second anchor set yet? Check both so we correctly re-draw during extension anchor editing
            if (ExtensionAnchor.IsEditing && EndAnchor.IsEditing)
            {
                return;
            }

            SharpDX.Vector2 extVector = anchorExtensionPoint.ToVector2();
            tmpBrush = IsInHitTest ? chartControl.SelectionBrush : RetracementLineStroke.BrushDX;
            RenderTarget.DrawLine(endVec, extVector, tmpBrush, RetracementLineStroke.Width, RetracementLineStroke.StrokeStyle);

            // If we're doing a hit test pass, don't draw price levels at all, we dont want those to count for
            // hit testing
            if (IsInHitTest || PriceLevels == null || !PriceLevels.Any())
            {
                return;
            }

            SetAllPriceLevelsRenderTarget();

            // Calculate total y range for % calculation on each level
            double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price;
            double startPrice      = ExtensionAnchor.Price;
            float  minLevelY       = float.MaxValue;
            float  maxLevelY       = float.MinValue;

            // Store values to use in correct render order
            Point  lastEndPoint   = new Point(0, 0);
            Point  lastStartPoint = new Point(0, 0);
            Stroke lastStroke     = null;
            List <Tuple <PriceLevel, Point> > textPoints = new List <Tuple <PriceLevel, Point> >();

            foreach (PriceLevel priceLevel in PriceLevels.Where(pl => pl.IsVisible && pl.Stroke != null).OrderBy(pl => pl.Value))
            {
                double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange));
                float  pixelY     = chartScale.GetYByValue(levelPrice);
                float  pixelX     = anchorExtensionPoint.X > anchorEndPoint.X ?
                                    priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) : (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))):
                                    priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))) : (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))));
                Point startPoint    = new Point(pixelX, pixelY);
                Point endPoint      = new Point(startPoint.X + (midPointExtension.X - anchorStartPoint.X), startPoint.Y + (midPointExtension.Y - anchorStartPoint.Y));
                Point maxLevelPoint = GetExtendedPoint(startPoint, endPoint);
                if (priceLevel.Value == 50)
                {
                    RenderTarget.DrawLine(startVec, maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle);
                }
                else
                {
                    RenderTarget.DrawLine(startPoint.ToVector2(), maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle);
                }

                if (lastStroke == null)
                {
                    lastStroke = new Stroke();
                }
                else
                {
                    SharpDX.Direct2D1.PathGeometry lineGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
                    SharpDX.Direct2D1.GeometrySink sink         = lineGeometry.Open();
                    sink.BeginFigure(lastEndPoint.ToVector2(), SharpDX.Direct2D1.FigureBegin.Filled);
                    // Does the fill color need to fill a corner?  Check and add a point
                    if (lastEndPoint.Y != maxLevelPoint.Y && lastEndPoint.X != maxLevelPoint.X)
                    {
                        double boundaryX;
                        double boundaryY;

                        if (lastEndPoint.Y <= ChartPanel.Y || lastEndPoint.Y >= ChartPanel.Y + ChartPanel.H)
                        {
                            boundaryY = lastEndPoint.Y;
                            boundaryX = maxLevelPoint.X;
                        }
                        else
                        {
                            boundaryY = maxLevelPoint.Y;
                            boundaryX = lastEndPoint.X;
                        }
                        sink.AddLine(new SharpDX.Vector2((float)boundaryX, (float)boundaryY));
                    }
                    sink.AddLine(maxLevelPoint.ToVector2());
                    sink.AddLine(startPoint.ToVector2());
                    sink.AddLine(lastStartPoint.ToVector2());
                    sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed);
                    sink.Close();
                    RenderTarget.FillGeometry(lineGeometry, lastStroke.BrushDX);
                    lineGeometry.Dispose();
                }

                if (IsTextDisplayed)
                {
                    textPoints.Add(new Tuple <PriceLevel, Point>(priceLevel, maxLevelPoint));
                }

                priceLevel.Stroke.CopyTo(lastStroke);
                lastStroke.Opacity = PriceLevelOpacity;
                lastStartPoint     = startPoint;
                lastEndPoint       = maxLevelPoint;
                minLevelY          = Math.Min(pixelY, minLevelY);
                maxLevelY          = Math.Max(pixelY, maxLevelY);
            }

            // Render text last so it's on top of the price level colors
            if (IsTextDisplayed)
            {
                foreach (Tuple <PriceLevel, Point> textPoint in textPoints)
                {
                    DrawPriceLevelText(0, 0, textPoint.Item2, textPoint.Item1, chartPanel);
                }
            }
        }
Example #6
0
        public override bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values,
                                                  ChartControl chartControl, ChartScale chartScale)
        {
            PriceLevel priceLevel = conditionItem.Tag as PriceLevel;

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

            ChartPanel chartPanel           = chartControl.ChartPanels[PanelIndex];
            Point      anchorStartPoint     = StartAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorEndPoint       = EndAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale);
            Point      midPointExtension    = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2);

            if (CalculationMethod == AndrewsPitchforkCalculationMethod.Schiff)
            {
                anchorStartPoint = new Point(anchorStartPoint.X, (anchorStartPoint.Y + anchorEndPoint.Y) / 2);
            }
            else if (CalculationMethod == AndrewsPitchforkCalculationMethod.ModifiedSchiff)
            {
                anchorStartPoint = new Point((anchorEndPoint.X + anchorStartPoint.X) / 2, (anchorEndPoint.Y + anchorStartPoint.Y) / 2);
            }

            double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price;
            double startPrice      = ExtensionAnchor.Price;

            double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange));
            float  pixelY     = chartScale.GetYByValue(levelPrice);
            float  pixelX     = anchorExtensionPoint.X > anchorEndPoint.X ?
                                (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) :
                                (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)));

            Point alertStartPoint = new Point(pixelX, pixelY);
            Point endPoint        = new Point(alertStartPoint.X + (midPointExtension.X - anchorStartPoint.X), alertStartPoint.Y + (midPointExtension.Y - anchorStartPoint.Y));
            Point alertEndPoint   = GetExtendedPoint(alertStartPoint, endPoint);

            double firstBarX = values[0].ValueType == ChartAlertValueType.StaticValue ? pixelX : chartControl.GetXByTime(values[0].Time);
            double firstBarY = chartScale.GetYByValue(values[0].Value);
            Point  barPoint  = new Point(firstBarX, firstBarY);

            // Check bars are not yet to our drawing tool
            if (firstBarX < alertStartPoint.X || firstBarX > alertEndPoint.X)
            {
                return(false);
            }

            // NOTE: 'left / right' is relative to if line was vertical. It can end up backwards too
            MathHelper.PointLineLocation pointLocation = MathHelper.GetPointLineLocation(alertStartPoint, alertEndPoint, barPoint);
            // For vertical things, think of a vertical line rotated 90 degrees to lay flat, where it's normal vector is 'up'
            switch (condition)
            {
            case Condition.Greater:                 return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove);

            case Condition.GreaterEqual:    return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine);

            case Condition.Less:                    return(pointLocation == MathHelper.PointLineLocation.RightOrBelow);

            case Condition.LessEqual:               return(pointLocation == MathHelper.PointLineLocation.RightOrBelow || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine);

            case Condition.Equals:                  return(pointLocation == MathHelper.PointLineLocation.DirectlyOnLine);

            case Condition.NotEqual:                return(pointLocation != MathHelper.PointLineLocation.DirectlyOnLine);

            case Condition.CrossAbove:
            case Condition.CrossBelow:
                Predicate <ChartAlertValue> predicate = v =>
                {
                    double barX         = chartControl.GetXByTime(v.Time);
                    double barY         = chartScale.GetYByValue(v.Value);
                    Point  stepBarPoint = new Point(barX, barY);
                    // NOTE: 'left / right' is relative to if line was vertical. It can end up backwards too
                    MathHelper.PointLineLocation ptLocation = MathHelper.GetPointLineLocation(alertStartPoint, alertEndPoint, stepBarPoint);
                    if (condition == Condition.CrossAbove)
                    {
                        return(ptLocation == MathHelper.PointLineLocation.LeftOrAbove);
                    }
                    return(ptLocation == MathHelper.PointLineLocation.RightOrBelow);
                };
                return(MathHelper.DidPredicateCross(values, predicate));
            }

            return(false);
        }