void DrawOrders(GraphicsWrapper g, int index, PointF drawingPoint, float itemWidth, float itemMargin, List <Order> openingOrders, List <Order> closingOrders, DataBar orderBarData, float lastBarX) { // Width is same as items in real coordinates. float actualImageHeight = _imageDown.Height / Math.Abs(g.DrawingSpaceTransformClone.Elements[3]); float yToXScaling = Math.Abs(g.DrawingSpaceTransformClone.Elements[0] / g.DrawingSpaceTransformClone.Elements[3]); PointF updatedImageDrawingPoint = drawingPoint; foreach (Order order in openingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, true); } foreach (Order order in closingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, false); } }
/// <summary> /// Create a dataDelivery bar based on quote. /// </summary> /// <param name="quote"></param> /// <returns></returns> public DataBar UpdateCurrentBar(DataBar currentBar, Quote quote) { if (quote.Bid.HasValue == false || quote.Ask.HasValue == false) { return(currentBar); } currentBar.Low = Math.Min(quote.Bid.Value, currentBar.Low); currentBar.High = Math.Max(quote.Bid.Value, currentBar.High); currentBar.Close = quote.Bid.Value; if (quote.Volume.HasValue) { currentBar.Volume = quote.Volume.Value; } return(currentBar); }
public DataBar?BarFromQuote(DataBar?previousBar, DateTime time, Quote quote) { if ((quote.IsFullySet == false && previousBar.HasValue == false) || (quote.Ask.HasValue == false || quote.Bid.HasValue == false)) {// We need at least previous bar if quote is not fully set. return(null); } decimal open = quote.Open.HasValue ? quote.Open.Value : previousBar.Value.Close; decimal close = quote.Bid.Value; DataBar result = new DataBar(time, open, Math.Max(open, close), Math.Min(open, close), close, 0); return(result); }
/// <summary> /// Enter locked. /// </summary> void DrawBar(GraphicsWrapper g, ref PointF startingPoint, DataBar barData, float itemWidth, float itemMargin, int itemUnitification) { float xMiddle = startingPoint.X + itemWidth / 2; float xHalfWidth = itemWidth / 2; Pen pen = _risingBarPen; if (barData.IsRising == false) { pen = _fallingBarPen; } if (pen == null) { return; } float yDisplacement = startingPoint.Y; g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Low, xMiddle, yDisplacement + (float)barData.High); g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Open, xMiddle - xHalfWidth, yDisplacement + (float)barData.Open); g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Close, xMiddle + xHalfWidth, yDisplacement + (float)barData.Close); }
void DrawOrder(GraphicsWrapper g, ref PointF updatedImageDrawingPoint, Order order, float itemWidth, float itemMargin, float yToXScaling, DataBar orderBarData, float lastBarX, bool drawOpening) { Image image = _imageUp; Brush brush = Brushes.Green; Pen dashedPen = _buyDashedPen; Pen pen = Pens.GreenYellow; if (order.IsBuy == false) { image = _imageDown; brush = Brushes.Red; pen = Pens.Red; dashedPen = _sellDashedPen; } if (drawOpening == false) { image = _imageCross; } if (order.OpenPrice.HasValue == false) { SystemMonitor.OperationError("Order with no open price assigned for drawing.", TracerItem.PriorityEnum.Low); return; } float price = (float)order.OpenPrice.Value; if (drawOpening == false) { if (order.ClosePrice.HasValue == false) { return; } price = (float)order.ClosePrice.Value; } if (drawOpening && _showPendingOrdersTracing && (order is ActiveOrder && order.State == OrderStateEnum.Executed) && _dataProvider.Quotes.Bid.HasValue && _dataProvider.Quotes.Ask.HasValue) {// Open orders tracking line. PointF point1 = new PointF(updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + price); float sellPrice = (float)_dataProvider.Quotes.Bid; if (order.IsBuy == false) { sellPrice = (float)_dataProvider.Quotes.Ask; } PointF point2 = new PointF(lastBarX - itemWidth / 2f, updatedImageDrawingPoint.Y + sellPrice); g.DrawLine(dashedPen, point1, point2); } //if (drawOpening && _showClosedOrdersTracing && order.IsOpen == false) //{// Closed order tracking. // Close order tracing is implemented in main draw function. //} if (_showOrderSpot) { PointF basePoint = new PointF(updatedImageDrawingPoint.X, updatedImageDrawingPoint.Y + price); float height = (yToXScaling * itemWidth); if (order.IsBuy == false) { height = -height; } if (drawOpening) { g.FillPolygon(brush, new PointF[] { basePoint, new PointF(basePoint.X + itemWidth, basePoint.Y), new PointF(basePoint.X + (itemWidth / 2f), basePoint.Y + height) }); g.DrawPolygon(Pens.White, new PointF[] { basePoint, new PointF(basePoint.X + itemWidth, basePoint.Y), new PointF(basePoint.X + (itemWidth / 2f), basePoint.Y + height) }); float drawToLeft = (float)(1.5 * itemWidth); float drawToRight = (float)(2.5 * itemWidth); // Take profit level. if (order.TakeProfit.HasValue && order.TakeProfit.Value != 0) { g.DrawLine(pen, updatedImageDrawingPoint.X - drawToLeft, updatedImageDrawingPoint.Y + (float)order.TakeProfit, updatedImageDrawingPoint.X + drawToRight, updatedImageDrawingPoint.Y + (float)order.TakeProfit); g.DrawLine(pen, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.TakeProfit, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.TakeProfit - height); } // Stop loss level. if (order.StopLoss.HasValue && order.StopLoss.Value != 0) { g.DrawLine(pen, updatedImageDrawingPoint.X - drawToLeft, updatedImageDrawingPoint.Y + (float)order.StopLoss, updatedImageDrawingPoint.X + drawToRight, updatedImageDrawingPoint.Y + (float)order.StopLoss); g.DrawLine(pen, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.StopLoss, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.StopLoss + height); } } else { g.DrawRectangle(Pens.White, basePoint.X, basePoint.Y, itemWidth, yToXScaling * itemWidth); } } float imageHeight = 2 * (yToXScaling * itemWidth); if (_showOrderArrow) { float x = updatedImageDrawingPoint.X - (itemWidth / 2f); float y = updatedImageDrawingPoint.Y + (float)orderBarData.Low - (yToXScaling * itemWidth); float width = 2 * itemWidth; float height = -imageHeight; GraphicsWrapper.NormalizedRectangle(ref x, ref y, ref width, ref height); RectangleF rectange = new RectangleF(x, y, width, height); // Draw up image. g.DrawImage(image, rectange.X, rectange.Y, rectange.Width, rectange.Height); if (order == _selectedOrder) {// This is selected order. g.DrawRectangle(Pens.White, rectange); } _ordersArrows[order] = rectange; updatedImageDrawingPoint.Y -= 1.2f * imageHeight; } }
/// <summary> /// Enter locked. /// </summary> void DrawCandleStick(GraphicsWrapper g, ref PointF startingPoint, DataBar barData, float itemWidth, float itemMargin, int itemUnitification) { if (barData.IsRising) { if (_risingBarFill != null) { g.FillRectangle(_risingBarFill, startingPoint.X, startingPoint.Y + (float)barData.Open, itemWidth, (float)barData.AbsoluteBodyHeight); } if (_risingBarPen != null) { if (itemWidth > 4) { g.DrawRectangle(_risingBarPen, startingPoint.X, startingPoint.Y + (float)barData.Open, itemWidth, (float)barData.AbsoluteBodyHeight); } else { g.FillRectangle(Brushes.Green, startingPoint.X, startingPoint.Y + (float)barData.Open, itemWidth, (float)barData.AbsoluteBodyHeight); } // Draw a horizontal line for 0 height bars. if (barData.AbsoluteBodyHeight == 0) { g.DrawLine(_fallingBarPen, startingPoint.X, startingPoint.Y + (float)barData.Close, startingPoint.X + itemWidth, startingPoint.Y + (float)barData.Close); } // Lower shadow g.DrawLine(_risingBarPen, startingPoint.X + itemWidth / 2, startingPoint.Y + (float)barData.Low, startingPoint.X + itemWidth / 2, startingPoint.Y + (float)barData.Open); // Upper shadow g.DrawLine(_risingBarPen, startingPoint.X + itemWidth / 2, (float)(startingPoint.Y + (float)barData.High), startingPoint.X + itemWidth / 2, (float)(startingPoint.Y + (float)barData.Close)); } } else { if (_fallingBarFill != null) { g.FillRectangle(_fallingBarFill, startingPoint.X, startingPoint.Y + (float)barData.Close, itemWidth, (float)barData.AbsoluteBodyHeight); } if (_fallingBarPen != null) { if (itemWidth >= 4) {// Only if an item is clearly visible, show the border, otherwise, hide to improve. overal visibility. // Showing this border adds nice detail on close zooming, but not useful otherwise. g.DrawRectangle(_fallingBarPen, startingPoint.X, startingPoint.Y + (float)barData.Close, itemWidth, (float)barData.AbsoluteBodyHeight); } // Draw a horizontal line for 0 height bars. if (barData.AbsoluteBodyHeight == 0) { g.DrawLine(_fallingBarPen, startingPoint.X, startingPoint.Y + (float)barData.Close, startingPoint.X + itemWidth, startingPoint.Y + (float)barData.Close); } // Lower shadow g.DrawLine(_fallingBarPen, startingPoint.X + itemWidth / 2, startingPoint.Y + (float)barData.Low, startingPoint.X + itemWidth / 2, startingPoint.Y + (float)barData.Close); // Upper shadow g.DrawLine(_fallingBarPen, startingPoint.X + itemWidth / 2, (float)(startingPoint.Y + (float)barData.High), startingPoint.X + itemWidth / 2, (float)(startingPoint.Y + (float)barData.Open)); } } }
/// <summary> /// Drawing routine, invoke from child class to draw dataDelivery bars in common uniform way. /// </summary> /// <param name="g"></param> /// <param name="unitsUnification">Draw a few units as one. Used when zooming is too big to show each unit - so unify them. 1 means no unification, 10 means unify 10 units together</param> /// <param name="clippingRectangle"></param> /// <param name="itemWidth"></param> /// <param name="itemMargin"></param> public void Draw(GraphicsWrapper g, ReadOnlyCollection <DataBar> dataBars, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin, float maxVolume, object tag) { if (Visible == false) { return; } PointF drawingPoint = new PointF(); lock (this) { if (_chartType == ChartTypeEnum.Line) { base.DrawItemSet(LinesChartSeries.ChartTypeEnum.Line, g, _risingBarPen, null, unitsUnification, clippingRectangle, itemWidth, itemMargin, null); } else if (_chartType == ChartTypeEnum.Histogram) { base.DrawItemSet(LinesChartSeries.ChartTypeEnum.Histogram, g, _risingBarPen, _risingBarFill, unitsUnification, clippingRectangle, itemWidth, itemMargin, tag); } else if (_chartType == ChartTypeEnum.ColoredArea) { base.DrawItemSet(LinesChartSeries.ChartTypeEnum.ColoredArea, g, _risingBarPen, _risingBarFill, unitsUnification, clippingRectangle, itemWidth, itemMargin, tag); } else if (_chartType == ChartTypeEnum.CandleStick || _chartType == ChartTypeEnum.BarChart) {// Unit unification is done trough combining many bars together. List <DataBar> combinationDatas = new List <DataBar>(); bool timeGapFound = false; int startIndex, endIndex; GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); float volumeDisplayRange = clippingRectangle.Height / 4f; decimal volumeDisplayMultiplicator = 0; if (maxVolume > 0) { volumeDisplayMultiplicator = (decimal)(volumeDisplayRange / maxVolume); } for (int i = startIndex; i < endIndex && i < dataBars.Count; i++) { combinationDatas.Add(dataBars[i]); if (unitsUnification == 1 && ShowTimeGaps && i > 0 && dataBars[i].DateTime - dataBars[i - 1].DateTime != _period) { timeGapFound = true; } if (i % unitsUnification == 0) { DataBar combinedData = DataBar.CombinedBar(combinationDatas.ToArray()); combinationDatas.Clear(); if (combinedData.HasDataValues) //&& drawingPoint.X >= clippingRectangle.X //&& drawingPoint.X <= clippingRectangle.X + clippingRectangle.Width) { if (timeGapFound && ShowTimeGaps && _timeGapsLinePen != null) {// Draw time gap. timeGapFound = false; g.DrawLine(_timeGapsLinePen, new PointF(drawingPoint.X, clippingRectangle.Y), new PointF(drawingPoint.X, clippingRectangle.Y + clippingRectangle.Height)); //g.DrawLine(_timeGapsLinePen, new PointF(drawingPoint.X, clippingRectangle.Y), new PointF(drawingPoint.X, (float)(dataDelivery.High))); //g.DrawLine(_timeGapsLinePen, new PointF(drawingPoint.X, (float)(dataDelivery.High + dataDelivery.BarTotalLength / 2f)), new PointF(drawingPoint.X, clippingRectangle.Y + clippingRectangle.Height)); } if (_chartType == ChartTypeEnum.CandleStick) { DrawCandleStick(g, ref drawingPoint, combinedData, itemWidth, itemMargin, unitsUnification); } else { DrawBar(g, ref drawingPoint, combinedData, itemWidth, itemMargin, unitsUnification); } // Draw closeVolume for this bar. if (_showVolume) { float actualHeight = (float)(combinedData.Volume * volumeDisplayMultiplicator); g.DrawLine(_volumePen, drawingPoint.X, clippingRectangle.Y, drawingPoint.X, clippingRectangle.Y + actualHeight); } } drawingPoint.X = (i + 1) * (itemMargin + itemWidth); } } } } }