internal void UpdateValues() { Debug.Assert(_values.Count == _items.Count); _values.Start(); foreach (InfoPanelItem item in _items) { Label label = _values.GetPaintObject(); label._textBlock.Text = item.ValueEx; } _values.Stop(); }
internal void ShowSelection(bool bShow) { _selectionVisible = bShow; SetCursor(); if (!_selectionVisible) { _selectionDots.RemoveAll(); return; } _selectionDots.C = C; _selectionDots.Start(); foreach (SelectionDotInfo point in GetSelectionPoints()) { SelectionDot dot = _selectionDots.GetPaintObject(point.Corner, point.Clickable); dot.SetPos(point.Position); dot.Tag = this; //dot.SetClip(Clip); Shape shape = dot.Shape; shape.Clip = GetClip(Canvas.GetLeft(shape), Canvas.GetTop(shape), _paintableRect); dot.ZIndex = ZIndexConstants.SelectionPoint1; } _selectionDots.Stop(); }
internal void ShowSelection() { if (!_selectable) { return; } _selected = true; double dx = 0; DataEntryCollection data = _chartPanel._chartX._dataManager[_seriesIndex].Data; _selectionDots.C = _chartPanel._rootCanvas; _selectionDots.Start(); for (int i = _chartPanel._chartX._startIndex; i < _chartPanel._chartX._endIndex; i++) { if (!data[i].Value.HasValue) { continue; } double x = _chartPanel._chartX.GetXPixel(i - _chartPanel._chartX._startIndex); if (x - dx <= 50) { continue; } dx = x; SelectionDot dot = _selectionDots.GetPaintObject(Types.Corner.MoveAll); dot.SetPos(new Point(dx, GetY(data[i].Value.Value))); dot.Tag = this; } _selectionDots.Stop(); _selectionDots.Do(dot => dot.ZIndex = ZIndexConstants.SelectionPoint1); }
internal override void DrawLineStudy(Types.RectEx rect, LineStatus lineStatus) { rect.Normalize(); _lines.C = C; _lines.Start(); Utils.DrawLine(rect.Left, rect.Top, rect.Left, rect.Bottom, Stroke, StrokeType, StrokeThickness, _lines); Utils.DrawLine(rect.Right, rect.Top, rect.Right, rect.Bottom, Stroke, StrokeType, StrokeThickness, _lines); foreach (double d in _fib) { double x = rect.Left + rect.Width * d; Utils.DrawLine(x, rect.Top, x, rect.Bottom, Stroke, StrokeType, StrokeThickness, _lines); } _lines.Stop(); _internalObjectCreated = true; if (_firstPaint) { _firstPaint = false; _lines.Do(l => { l._line.Tag = this; l.ZIndex = ZIndexConstants.LineStudies1; }); _contextLine = new ContextLine(this); _chartX.InvokeLineStudyCreated(new StockChartX.LineStudyCreatedEventArgs(this)); } }
public override bool Paint() { if (_series.OHLCType != SeriesTypeOHLC.High && _series.OHLCType != SeriesTypeOHLC.Low) { return(false); } StockChartX chartX = _series._chartPanel._chartX; Series high = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.Painted || high.RecordCount == 0) { return(false); } Series low = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.Painted || low.RecordCount == 0) { return(false); } high.Painted = low.Painted = true; Brush upBrush = new SolidColorBrush(_series._upColor.HasValue ? _series.UpColor.Value : chartX.UpColor); Brush downBrush = new SolidColorBrush(_series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor); double width = chartX.PaintableWidth; double max = chartX.GetMax(high, true); double min = chartX.GetMin(low, true); double boxSize = chartX._priceStyleParams[0]; if (boxSize > 50 || boxSize < 0.00000000000000000000001) { boxSize = (max - min) / 25; } double reversalSize = chartX._priceStyleParams[1]; if (reversalSize > 50 || reversalSize < 1) { reversalSize = 3; } chartX._priceStyleParams[0] = boxSize; chartX._priceStyleParams[1] = reversalSize; double nHigh, nLow, nLastHigh = 0, nLastLow = 0; int column = 0; // X=1 O=2 int columnHeight = 0; int totalColumns = 0; int boxes; const int Xs = 1; const int Os = 2; chartX._psValues1.Clear(); chartX._psValues2.Clear(); chartX._psValues3.Clear(); chartX._xMap = new double[chartX._endIndex - chartX._startIndex + 1]; int cnt = 0; // Count columns int n; for (n = chartX._startIndex; n < chartX._endIndex; n++) { if (!high[n].Value.HasValue || !low[n].Value.HasValue) { continue; } // Calculate Point and Figure nHigh = high[n].Value.Value; nLow = low[n].Value.Value; switch (column) { case Xs: boxes = (int)((nHigh - nLastHigh) / boxSize); if (boxes >= boxSize) { // Add one X box columnHeight += 1; nLastHigh += boxSize; if (nLastHigh > max) { max = nLastHigh; } } else { // Check for O's reversal boxes = (int)((nLastHigh - nLow) / boxSize); if (boxes >= reversalSize) { column = Os; columnHeight = boxes; totalColumns++; nLastLow = nLastHigh - (boxes * boxSize); if (nLastLow < min && min != 0) { min = nLastLow; } } } break; case Os: boxes = (int)((nLastLow - nLow) / boxSize); if (boxes >= boxSize) { // Add one O box columnHeight += 1; nLastLow -= boxSize; if (nLastLow < min && min != 0) { min = nLastLow; } } else { // Check for X's reversal boxes = (int)((nHigh - nLastLow) / boxSize); if (boxes >= reversalSize) { column = Xs; columnHeight = boxes; totalColumns++; nLastHigh = nLastLow + (boxes * boxSize); if (nLastHigh > max) { max = nLastHigh; } } } break; } if (column != 0) { continue; // Prime first column } column = Xs; boxes = (int)Math.Floor(((nHigh - (nLow + (boxSize * reversalSize))) / boxSize) + 0.5); columnHeight = boxes; nLastHigh = nHigh; nLastLow = nHigh - (boxes * boxSize); totalColumns = 1; } chartX._xCount = totalColumns; column = 0; double x = chartX.LeftChartSpace; if (totalColumns == 0) { return(false); } double space = width / totalColumns; totalColumns = 0; _lines.C = _ellipses.C = _series._chartPanel._rootCanvas; _lines.Start(); _ellipses.Start(); // Calculate from beginning, but only show between startIndex and endIndex for (n = 0; n < chartX._endIndex; n++) { if (high[n].Value.HasValue && low[n].Value.HasValue) { // Calculate Point and Figure nHigh = high[n].Value.Value; nLow = low[n].Value.Value; double y1; double y2; switch (column) { case Xs: boxes = (int)((nHigh - nLastHigh) / boxSize); if (boxes >= boxSize) { // Add one X box columnHeight += 1; nLastHigh += boxSize; } else { // Check for O's reversal boxes = (int)((nLastHigh - nLow) / boxSize); if (boxes >= reversalSize) { // Paint the previous X column if (n >= chartX._startIndex && n <= chartX._endIndex) { double y = nLastHigh; if (columnHeight > 0) { for (int col = 0; col < columnHeight; ++col) { y1 = _series._chartPanel.GetY(y); y -= boxSize; y2 = _series._chartPanel.GetY(y); double x1 = x; double x2 = x + space; Utils.DrawLine(x1, y1, x2, y2, upBrush, _series._strokePattern, _series._strokeThickness, _series._opacity, _lines); Utils.DrawLine(x2, y1, x1, y2, upBrush, _series._strokePattern, _series._strokeThickness, _series._opacity, _lines); } } } // Create new O column column = Os; columnHeight = boxes; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalColumns++; x += space; } nLastLow = nLastHigh - (boxes * boxSize); } } break; case Os: boxes = (int)((nLastLow - nLow) / boxSize); if (boxes >= boxSize) { // Add one O box columnHeight += 1; nLastLow -= boxSize; } else { // Check for X's reversal boxes = (int)((nHigh - nLastLow) / boxSize); if (boxes >= reversalSize) { // Paint the previous O's column if (n >= chartX._startIndex && n <= chartX._endIndex) { double y = nLastLow - boxSize; if (columnHeight > 0) { for (int col = 0; col < columnHeight; ++col) { y2 = _series._chartPanel.GetY(y); y += boxSize; y1 = _series._chartPanel.GetY(y); System.Windows.Shapes.Ellipse ellipse = _ellipses.GetPaintObject()._ellipse; Types.RectEx bounds = new Types.RectEx(x, y1, x + space, y2); Canvas.SetLeft(ellipse, bounds.Left); Canvas.SetTop(ellipse, bounds.Top); ellipse.Width = bounds.Width; ellipse.Height = bounds.Height; ellipse.Stroke = downBrush; ellipse.StrokeThickness = _series._strokeThickness; ellipse.Fill = _series._chartPanel.Background; } } } // Create new X column column = Xs; columnHeight = boxes; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalColumns++; x += space; } nLastHigh = nLastLow + (boxes * boxSize); } } break; } if (column == 0) { // Prime first column column = Xs; boxes = (int)Math.Floor(((nHigh - (nLow + (boxSize * reversalSize))) / boxSize) + 0.5); columnHeight = boxes; nLastHigh = nHigh; nLastLow = nHigh - (boxes * boxSize); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalColumns = 1; } x = chartX.LeftChartSpace; } // Record the x value if (n >= chartX._startIndex && n <= chartX._endIndex) { chartX._xMap[cnt] = x + (space / 2); cnt++; } } chartX._psValues3.Add(new PriceStyleValue(high[n].TimeStamp, column == 1 ? 1 : -1)); chartX._psValues1.Add(new PriceStyleValue(high[n].TimeStamp, columnHeight)); // Once the direction changes, we need to // go backwards until the previous change // and fill in the values. if (chartX._psValues3.Count <= 1) { continue; } for (int prev = chartX._psValues3.Count - 1; prev >= 0; --prev) { if (chartX._psValues3[prev].Value != column) { break; } chartX._psValues1[prev].Value = columnHeight; } } _lines.Stop(); _ellipses.Stop(); _lines.Do(l => l.ZIndex = ZIndexConstants.PriceStyles1); _ellipses.Do(e => e.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
private void PaintSideVolumeDepthBars() { if (_sideVolumeDepthBars == 0) //remove { _rectsSideVolumeDepth.RemoveAll(); return; } if (_chartX._endIndex == 0) { return; } if (_series.Count < 3) { return; } Series open = null; foreach (Series series in _series) { if (series.OHLCType != SeriesTypeOHLC.Open) { continue; } open = series; break; } if (open == null) { return; } Series close = GetSeriesOHLCV(open, SeriesTypeOHLC.Close); if (close == null) { return; } Series volume = _chartX.GetSeriesOHLCV(open, SeriesTypeOHLC.Volume); if (volume == null) { return; } double maxVolume = double.MinValue, minVolume = double.MaxValue; int i; for (i = _chartX._startIndex; i < _chartX._endIndex; i++) { if (!volume[i].Value.HasValue) { continue; } if (volume[i].Value.Value > maxVolume) { maxVolume = volume[i].Value.Value; } else if (volume[i].Value.Value < minVolume) { minVolume = volume[i].Value.Value; } } double range = maxVolume - minVolume; double barVolumeIncrement = range / _sideVolumeDepthBars; double barHeight = _rootCanvas.ActualHeight / _sideVolumeDepthBars; double volBar = minVolume; int[] volBarsPos = new int[_sideVolumeDepthBars]; int[] volBarsNeg = new int[_sideVolumeDepthBars]; for (int n = 0; n < _sideVolumeDepthBars; n++) { for (int j = _chartX._startIndex; j < _chartX._endIndex; j++) { if (!volume[j].Value.HasValue) { continue; } double v = volume[j].Value.Value; if (v < volBar || v > volBar + barVolumeIncrement) { continue; } if (close[j].Value > open[j].Value) { volBarsPos[n]++; } else if (close[j].Value < open[j].Value) { volBarsNeg[n]++; } } volBar += barVolumeIncrement; } double[] volBarsWidthPos = new double[_sideVolumeDepthBars]; double[] volBarsWidthNeg = new double[_sideVolumeDepthBars]; double maxVolBars = Math.Max(Algorithms.Maximum(volBarsPos), Algorithms.Maximum(volBarsNeg)); double minVolBars = Math.Min(Algorithms.Minimum(volBarsPos), Algorithms.Minimum(volBarsNeg)); double volumeBarScaleWidth = _rootCanvas.ActualWidth * 0.15; //15% for positive values and 15% for negative values _rectsSideVolumeDepth.C = _rootCanvas; _rectsSideVolumeDepth.Start(); for (int n = 0; n < _sideVolumeDepthBars; n++) { volBarsWidthPos[n] = (volBarsPos[n] - minVolBars) / (maxVolBars - minVolBars); volBarsWidthNeg[n] = (volBarsNeg[n] - minVolBars) / (maxVolBars - minVolBars); volBarsWidthPos[n] *= volumeBarScaleWidth; volBarsWidthNeg[n] *= volumeBarScaleWidth; double x1 = _chartX.LeftChartSpace; double y1 = n * barHeight; double x2 = _chartX.LeftChartSpace + volBarsWidthPos[n]; double y2 = (n + 1) * barHeight; Utils.DrawRectangle(x1, y1, x2, y2, Brushes.Blue, _rectsSideVolumeDepth); x1 = x2; x2 = x1 + volBarsWidthNeg[n]; Utils.DrawRectangle(x1, y1, x2, y2, Brushes.Red, _rectsSideVolumeDepth); } _rectsSideVolumeDepth.Stop(); _rectsSideVolumeDepth.Do(r => { r.ZIndex = ZIndexConstants.VolumeDepthBars; r._rectangle.Opacity = 0.5; r._rectangle.IsHitTestVisible = false; }); }
internal override void Paint() { if (Painted || !_visible || RecordCount < 0 || RecordCount < _chartPanel._chartX._startIndex) { return; } Painted = true; InitPainting(); if (_chartPanel._chartX.OptimizePainting) { PaintOptimized(); return; } Brush strokeUpBrush = new SolidColorBrush(UpColor == null ? _chartPanel._chartX.UpColor : UpColor.Value); strokeUpBrush.Freeze(); Brush strokeDownBrush = new SolidColorBrush(DownColor == null ? _chartPanel._chartX.DownColor : DownColor.Value); strokeDownBrush.Freeze(); Brush strokeNormalBrush = new SolidColorBrush(_strokeColor); strokeNormalBrush.Freeze(); Brush currentBrush = strokeNormalBrush; _lines.C = _chartPanel._rootCanvas; _lines.Start(); double x2 = _chartPanel._chartX.GetXPixel(0); double?y1; double?y2 = null; int cnt = 0; for (int i = _chartPanel._chartX._startIndex; i < _chartPanel._chartX._endIndex; i++, cnt++) { //cnt++; double x1 = _chartPanel._chartX.GetXPixel(cnt); y1 = this[i].Value; if (!y1.HasValue) { continue; } y1 = GetY(y1.Value); if (i == _chartPanel._chartX._startIndex) { y2 = y1.Value; } if (_volumeUpDown) { if (i > 0) { if (_seriesClose[i].Value > _seriesClose[i - 1].Value) { currentBrush = _seriesTypeOHLC == SeriesTypeOHLC.Volume ? strokeUpBrush : strokeDownBrush; //up } else if (_seriesClose[i].Value < _seriesClose[i - 1].Value) { currentBrush = _seriesTypeOHLC == SeriesTypeOHLC.Volume ? strokeDownBrush : strokeUpBrush; //down } else { currentBrush = strokeNormalBrush; } } else { currentBrush = strokeNormalBrush; } } else if ((_chartPanel._chartX._useLineSeriesColors || _upColor.HasValue)) // +/- change colors { if (!_isOscillator) { if (i > 0) { if (this[i].Value > this[i - 1].Value) { currentBrush = strokeUpBrush; } else { currentBrush = this[i].Value < this[i - 1].Value ? strokeDownBrush : strokeNormalBrush; } } else { currentBrush = strokeNormalBrush; } } else { if (this[i].Value > 0) { currentBrush = strokeUpBrush; } else { currentBrush = this[i].Value < 0 ? strokeDownBrush : strokeNormalBrush; } } } if (_seriesType == SeriesTypeEnum.stVolumeChart || ForceOscilatorPaint) { if (this[i].Value.HasValue && y2.HasValue) { // Make sure at least 2 or 3 pixels show // if the value is the same as the min Y. double minY = GetY(SeriesEntry._min); double nY1 = y1.Value; if (minY - 3 < nY1) { nY1 -= 3; } DrawLine(x1, nY1, x1, _isOscillator ? GetY(0) : minY, _chartPanel._chartX.GetBarBrush(FullName, i, currentBrush)); } } else if ((_seriesType == SeriesTypeEnum.stLineChart || _seriesType == SeriesTypeEnum.stIndicator) && i > _chartPanel._chartX._startIndex) { if (this[i].Value.HasValue && y2.HasValue) { DrawLine(x1, y1.Value, x2, y2.Value, currentBrush); } } y2 = y1; x2 = x1; } _lines.Stop(); _lines.Do(l => { l.ZIndex = ZIndexConstants.PriceStyles1; if (l._line.Tag == null) { l._line.Tag = this; } }); if (Selected) { ShowSelection(); } }
public override bool Paint() { /* * pCtrl->priceStyleParams[0] = lines * 7 columns * width = 300 * 300 / 7 = 42.85 pixels per column */ if (_series.OHLCType != SeriesTypeOHLC.Close) { return(false); } Series close = _series; StockChartX chartX = _series._chartPanel._chartX; double width = chartX.PaintableWidth; double boxSize = chartX._priceStyleParams[0]; if (boxSize > 50 || boxSize < 0.0001) { boxSize = 1; } chartX._priceStyleParams[0] = boxSize; double nClose, nHH = 0, nLL = 0; const int white = 1; const int black = 2; int brick = 0; // black or white int totalBricks = 0; chartX._xMap = new double[chartX._endIndex - chartX._startIndex + 1]; int cnt = 0; chartX._psValues1.Clear(); chartX._psValues2.Clear(); chartX._psValues3.Clear(); int n; // Calculate from beginning, but only show between startIndex and endIndex for (n = 0; n < chartX._endIndex; n++) { if (!close[n].Value.HasValue) { continue; } nClose = close[n].Value.Value; if (brick == 0) { // Prime first brick double nClose2 = close[n + 1].Value.Value; if (nClose2 > nClose) { brick = white; nHH = nClose + boxSize; nLL = nClose; } else { brick = black; nHH = nClose2; nLL = nClose2 - boxSize; } if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBricks = 1; } } if (nClose < nLL - boxSize) { brick = black; nHH = nLL; nLL = nHH - boxSize; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBricks++; } } else if (nClose > nHH + boxSize) { brick = white; nLL = nHH; nHH = nLL + boxSize; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBricks++; } } } chartX._xCount = totalBricks; // Paint columns brick = 0; double x = chartX.LeftChartSpace; if (totalBricks == 0) { return(false); } double space = width / totalBricks; Color upColor = _series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor; Color downColor = _series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor; Brush upBrush = new SolidColorBrush(upColor); Brush downBrush = new SolidColorBrush(downColor); Brush upGradBrush = Utils.CreateFadeVertBrush(upColor, Colors.Black); Brush downGradBrush = Utils.CreateFadeVertBrush(downColor, Colors.Black); _rects.C = _series._chartPanel._rootCanvas; _rects.Start(); totalBricks = 0; for (n = 0; n < chartX._endIndex; n++) { if (close[n].Value.HasValue) { // Calculate Renko nClose = (double)close[n].Value; if (brick == 0) { // Prime first brick double nClose2 = (double)close[n + 1].Value; if (nClose2 > nClose) { brick = white; nHH = nClose + boxSize; nLL = nClose; } else { brick = black; nHH = nClose2; nLL = nClose2 - boxSize; } if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBricks = 1; } x = chartX.LeftChartSpace; } if (nClose < nLL - boxSize) { // Paint last white brick if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, brick); totalBricks++; x += space; } brick = black; nHH = nLL; nLL = nHH - boxSize; } else if (nClose > nHH + boxSize) { // Paint last black brick if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, brick); totalBricks++; x += space; } brick = white; nLL = nHH; nHH = nLL + boxSize; } // Record the x value if (n >= chartX._startIndex && n <= chartX._endIndex) { chartX._xMap[cnt] = x + (space / 2); cnt++; } } chartX._psValues1.Add(new PriceStyleValue(close[n].TimeStamp, nHH)); chartX._psValues2.Add(new PriceStyleValue(close[n].TimeStamp, nLL)); chartX._psValues3.Add(new PriceStyleValue(close[n].TimeStamp, brick == white ? 1 : -1)); } _rects.Stop(); _rects.Do(r => r.ZIndex = r.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
public override bool Paint() { StockChartX chartX = _series._chartPanel._chartX; chartX._psValues1.Clear(); chartX._psValues2.Clear(); chartX._psValues3.Clear(); if (_series.OHLCType != SeriesTypeOHLC.Close) { return(false); } Series close = _series; Series low = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null) { return(false); } Series high = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null) { return(false); } /* * Initial box top is the high of day 1. * * The first step is to find a new high that is higher than the high of day 1. * The high can be found anytime - even after 5 days. * But once the bottom has been found, the box is complete. * * To find the bottom, the low must be after day 2 of the day the last box * top was found and must be lower than the low of original day 1 low. * * The bottom is always found last and a new high may not be found once * the bottom is locked in - the Darvas box is complete then. * * A new box is started when the price breaks out of top or bottom, * * The bottom stop loss box is drawn as a percentage of the last price. */ Brush brDarvas = new SolidColorBrush(Color.FromArgb(0xFF, 0, 0, 255)); Brush brDarvaseIncomplete = new SolidColorBrush(Color.FromArgb(0xFF, 100, 115, 255)); Brush topLeft = new SolidColorBrush(Color.FromArgb(0xFF, 240, 240, 240)); Brush bottomRight = new SolidColorBrush(Color.FromArgb(0xFF, 150, 150, 150)); Brush brGradStopLoss = Utils.CreateFadeVertBrush(Color.FromArgb(0xFF, 255, 255, 255), Colors.Red); double boxTop = 0; double boxBottom = 0; int bottomFound = 0; int cnt = 0; int start = 0; int state = 0; _rects.C = _rects3D.C = _series._chartPanel._rootCanvas; _rects3D.Start(); _rects.Start(); for (int n = chartX._startIndex; n < chartX._endIndex; n++, cnt++) { if (!close[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue) { continue; } double x1; double x2; double y1; double y2; if (n == chartX._endIndex - 1) { x1 = chartX.GetXPixel(start); x2 = chartX.GetXPixel(cnt); y1 = _series._chartPanel.GetY(boxTop); y2 = _series._chartPanel.GetY(boxBottom); if (state == 5) // draw the last COMPLETED box { Rectangle rect = Utils.DrawRectangle(x1, y1, x2 + 2, y2, brDarvas, _rects); rect._rectangle.Opacity = 0.5; Utils.Draw3DRectangle(x1, y1, x2 + 2, y2, topLeft, bottomRight, _rects3D); } else if (bottomFound > 0) { Rectangle rect = Utils.DrawRectangle(x1, y1, x2 + 2, y2, brDarvaseIncomplete, _rects); rect._rectangle.Opacity = 0.5; Utils.Draw3DRectangle(x1, y1, x2 + 2, y2, topLeft, bottomRight, _rects3D); } // Gradient stop loss box double y3 = _series._chartPanel.GetY(boxBottom - (boxBottom * chartX._darvasPct)); if (y3 < y2) { y3 = y2; } Utils.DrawRectangle(x1, y2, x2 + 2, y3, brGradStopLoss, _rects); break; } if (state == 0) { // Start of a new box // Save new box top and bottom start = cnt; bottomFound = 0; boxTop = high[n].Value.Value; boxBottom = -1; state = 1; } switch (state) { case 1: if (high[n].Value.Value > boxTop) { boxTop = high[n].Value.Value; state = 1; } else { state = 2; } break; case 2: if (high[n].Value.Value > boxTop) { boxTop = high[n].Value.Value; state = 1; } else { bottomFound = n; boxBottom = low[n].Value.Value; state = 3; } break; case 3: if (high[n].Value.Value > boxTop) { boxTop = high[n].Value.Value; state = 1; } else { if (low[n].Value.Value < boxBottom) { boxBottom = low[n].Value.Value; bottomFound = n; state = 3; } else { state = 4; } } break; case 4: if (high[n].Value.Value > boxTop) { boxTop = high[n].Value.Value; state = 1; } else { if (low[n].Value.Value < boxBottom) { boxBottom = low[n].Value.Value; bottomFound = n; state = 3; } else { state = 5; // Darvas box is complete } } break; } if (state != 5) { continue; } if (low[n].Value.Value >= boxBottom && high[n].Value.Value <= boxTop) { continue; } x1 = chartX.GetXPixel(start); x2 = chartX.GetXPixel(cnt); y1 = _series._chartPanel.GetY(boxTop); y2 = _series._chartPanel.GetY(boxBottom); Rectangle rectangle = Utils.DrawRectangle(x1, y1, x2, y2, brDarvas, _rects); rectangle._rectangle.Opacity = 0.5; Utils.Draw3DRectangle(x1, y1, x2, y2, topLeft, bottomRight, _rects3D); Utils.DrawRectangle(x1, y2, x2, _series._chartPanel.GetY(boxBottom - (boxBottom * chartX._darvasPct)), brGradStopLoss, _rects); state = 0; cnt--; n--; } _rects3D.Stop(); _rects.Stop(); _rects.Do(r => r.ZIndex = ZIndexConstants.DarvasBoxes1); _rects3D.Do(r => r.ZIndex = ZIndexConstants.DarvasBoxes2); return(true); }
internal void RecalculateLayout() { Debug.Assert(_chartX != null); _values.Start(); _labels.Start(); _values.C = this; _labels.C = this; double labelsMaxWidth = double.MinValue; double valuesMaxWidth = double.MinValue; double valuesNoCaptionMaxWidth = double.MinValue; int valueIndex; _entries.Clear(); foreach (InfoPanelItem item in _items) { _entries.Add(new Tuple <string, string>(item.Caption, item.ValueEx)); if (!item._noCaption) { Label labelCaption = _labels.GetPaintObject(); labelCaption._textBlock.Text = item.Caption; labelCaption._textBlock.FontFamily = _chartX.InfoPanelFontFamily; labelCaption._textBlock.FontSize = _chartX.InfoPanelFontSize; labelCaption._textBlock.Foreground = _chartX.InfoPanelLabelsForeground; SetZIndex(labelCaption._textBlock, 5); } Label labelValue = _values.GetPaintObject(); labelValue._textBlock.Text = item.ValueEx; labelValue._textBlock.FontFamily = _chartX.InfoPanelFontFamily; labelValue._textBlock.FontSize = _chartX.InfoPanelFontSize; labelValue._textBlock.Foreground = _chartX.InfoPanelValuesForeground; SetZIndex(labelValue._textBlock, 5); } _values.Stop(); _labels.Stop(); int labelIndex = valueIndex = 0; double top = 1; foreach (InfoPanelItem item in _items) { Label labelValue = _values[valueIndex++]; if (!item._noCaption) { Label labelCaption = _labels[labelIndex++]; if (labelCaption._textBlock.ActualWidth > labelsMaxWidth) { labelsMaxWidth = labelCaption._textBlock.ActualWidth; } SetLeft(labelCaption._textBlock, 1); SetTop(labelCaption._textBlock, top - 1); } top += labelValue._textBlock.ActualHeight + 2; } top = 1; valueIndex = 0; foreach (InfoPanelItem item in _items) { Label labelValue = _values[valueIndex++]; if (item._noCaption) { SetLeft(labelValue._textBlock, 2); if (labelValue._textBlock.ActualWidth > valuesNoCaptionMaxWidth) { valuesNoCaptionMaxWidth = labelValue._textBlock.ActualWidth; } } else { SetLeft(labelValue._textBlock, labelsMaxWidth + 3); if (labelValue._textBlock.ActualWidth > valuesMaxWidth) { valuesMaxWidth = labelValue._textBlock.ActualWidth; } } SetTop(labelValue._textBlock, top - 1); top += labelValue._textBlock.ActualHeight + 2; } double maxWidth = labelsMaxWidth + valuesMaxWidth + 4; Width = Math.Max(maxWidth, valuesNoCaptionMaxWidth); if (_rectLabels == null) { _rectLabels = new Rectangle { Stroke = null, StrokeThickness = 0 }; Children.Add(_rectLabels); _rectValues = new Rectangle { Stroke = null, StrokeThickness = 0 }; Children.Add(_rectValues); } SetLeft(_rectLabels, 0); SetTop(_rectLabels, 0); _rectLabels.Width = labelsMaxWidth + 2; _rectLabels.Height = top; _rectLabels.Fill = _chartX.InfoPanelLabelsBackground; SetLeft(_rectValues, GetLeft(_rectLabels) + _rectLabels.Width); SetTop(_rectValues, 0); _rectValues.Width = Math.Max(maxWidth, valuesNoCaptionMaxWidth) - labelsMaxWidth + 2; _rectValues.Height = top; _rectValues.Fill = _chartX.InfoPanelValuesBackground; Height = top; }
internal override void DrawLineStudy(Types.RectEx rect, LineStatus lineStatus) { if (lineStatus == LineStatus.StartPaint) { return; } rect.Normalize(); if (rect.Width == 0 || rect.Left < 0) { return; } int revX1 = (int)(_chartX.GetReverseXInternal(rect.Left) + _chartX._startIndex); int revX2 = (int)(_chartX.GetReverseXInternal(rect.Right) + _chartX._startIndex); if (revX1 < 0) { revX1 = 0; } if (revX2 < 0) { revX2 = 0; } if (revX1 == revX2) { return; } // Note: this code makes the vague assumption // that only one symbol exists on this panel. // Get the close series Series sClose = GetSeriesOHLC(SeriesTypeOHLC.Close); if (sClose == null) { return; } //Debug.Assert(sClose.RecordCount == _chartX.RecordCount); if (revX1 >= _chartX.RecordCount) { revX1 = _chartX.RecordCount - 1; } if (revX2 >= _chartX.RecordCount) { revX2 = _chartX.RecordCount - 1; } // Get the highest high of the high series. double highestHigh = 0; Series sHigh = GetSeriesOHLC(SeriesTypeOHLC.High); if (sHigh == null) { return; } //Debug.Assert(revX1 <= revX2); for (int i = revX1; i <= revX2; i++) { if (sHigh[i].Value > highestHigh) { highestHigh = sHigh[i].Value.Value; } } //Get the lowest low of the low series. double lowestLow = highestHigh; Series sLow = GetSeriesOHLC(SeriesTypeOHLC.Low); if (sLow == null) { return; } for (int i = revX1; i <= revX2; i++) { if (sLow[i].Value < lowestLow) { lowestLow = sLow[i].Value.Value; } } double range = (highestHigh - lowestLow) * 0.5; if (_rangeScale.HasValue) { range = (highestHigh - lowestLow) * _rangeScale.Value; } // Perform linear regression on the data double xSum = 0, ySum = 0, xSquaredSum = 0, xYSum = 0; int x = revX2 - revX1; int j, n; for (n = 1; n != x + 1; ++n) { j = revX1 + n - 1; xSum += n; ySum += sClose[j].Value.Value; xSquaredSum += (n * n); xYSum += (sClose[j].Value.Value * n); } n = x; double q1 = n != 0 ? (xYSum - ((xSum * ySum) / n)) : 0; double q2 = n != 0 ? (xSquaredSum - ((xSum * xSum) / n)) : 0; double slope = q2 != 0 ? (q1 / q2) : 0; double leftValue = slope != 0 ? (((1 / (double)n) * ySum) - (((int)((double)n / 2)) * slope)) : 0.0; double rightValue = ((n * slope) + leftValue); double inc = (x - 1) != 0 ? (rightValue - leftValue) / (x - 1) : 0; j = 0; double prevVal = 0; double lX1 = rect.Left; //_chartX.GetX(revX1 - _chartX._startIndex); double lX2 = rect.Right; // _chartX.GetX((revX2 - 1) - _chartX._startIndex + 1); if (_linesError.Count == 0) { for (int i = 0; i < 3; i++) { System.Windows.Shapes.Line line = new System.Windows.Shapes.Line { Tag = this }; Canvas.SetZIndex(line, ZIndexConstants.LineStudies1); C.Children.Add(line); _linesError.Add(line); } _contextLine = new ContextLine(this); _chartX.InvokeLineStudyCreated(new StockChartX.LineStudyCreatedEventArgs(this)); } _internalObjectCreated = true; _lines.C = C; _lines.Start(); for (n = revX1; n <= revX2; n++, j++) { double val = leftValue + inc * (j - 1); //double lX1 = _chartX.GetX(n - _chartX._startIndex); //double lX2 = _chartX.GetX(n - _chartX._startIndex + 1); double lY1 = _chartPanel.GetY(prevVal + range); double lY2 = _chartPanel.GetY(val + range); if (prevVal != 0.0) { _errorLines[2].Y1 = lY1; _errorLines[2].Y2 = lY2; Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _linesError[0]); } lY1 = _chartPanel.GetY(prevVal - range); lY2 = _chartPanel.GetY(val - range); if (prevVal != 0.0) { _errorLines[0].Y1 = lY1; _errorLines[0].Y2 = lY2; Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _linesError[1]); } lY1 = _chartPanel.GetY(prevVal); lY2 = _chartPanel.GetY(val); if (prevVal != 0.0) { _errorLines[1].Y1 = lY1; _errorLines[1].Y2 = lY2; Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _linesError[2]); } prevVal = val; } if (lineStatus == LineStatus.Moving || lineStatus == LineStatus.Painting) { Utils.DrawLine(rect.Left, 0, rect.Left, _chartPanel.Height, Stroke, StrokeType, StrokeThickness, _lines); Utils.DrawLine(rect.Right, 0, rect.Right, _chartPanel.Height, Stroke, StrokeType, StrokeThickness, _lines); } _lines.Stop(); _lines.Do(l => l.ZIndex = ZIndexConstants.LineStudies1); _errorLines[0].X1 = rect.Left; _errorLines[0].X2 = rect.Right; _errorLines[1].X1 = rect.Left; _errorLines[1].X2 = rect.Right; _errorLines[2].X1 = rect.Left; _errorLines[2].X2 = rect.Right; if (_contextLine == null && _linesError.Count > 0) { _contextLine = new ContextLine(this); } }
public override bool Paint() { /* * highestVolume = highest volume up to current record (not after) * * x = volume / highestVolume * if x = 0 then x = 1 * * 1,0.25,0.5,0.75,0.25,0.5,1 * total=4.25 * * /4.25 total * 0.235,0.058,0.117,0.176,0.058,0.117,0.235=1 * * 300* pixels * 70.5,17.4,35.1,52.8,17.4,35.1,70.5=300 * */ if (_series.OHLCType == SeriesTypeOHLC.Volume) { return(false); } StockChartX chartX = _series._chartPanel._chartX; Series open = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Open); if (open == null || open.Painted || open.RecordCount == 0) { return(false); } Series high = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.Painted || high.RecordCount == 0) { return(false); } Series low = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.Painted || low.RecordCount == 0) { return(false); } Series close = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (close == null || close.Painted || close.RecordCount == 0) { return(false); } Series volume = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Volume); if (volume == null || volume.RecordCount == 0) { return(false); } open.Painted = high.Painted = low.Painted = close.Painted = true; double width = chartX.PaintableWidth; const int up = 1; const int down = 2; double highestVolume; double x; double equiVol; double total = 0; Types.RectEx box; Brush customBrush = new SolidColorBrush(_series._strokeColor); Brush upBrush = new SolidColorBrush(_series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor); Brush downBrush = new SolidColorBrush(_series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor); Brush upGradBrush = Utils.CreateFadeVertBrush(_series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor, Colors.Black); Brush downGradBrush = Utils.CreateFadeVertBrush(Colors.Black, _series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor); chartX._xMap = new double[chartX._endIndex - chartX._startIndex + 1]; int cnt = 0; _lines.C = _rects.C = _rects3D.C = _series._chartPanel._rootCanvas; _lines.Start(); _rects.Start(); _rects3D.Start(); // Count total Equi-Volume int n; for (n = chartX._startIndex; n < chartX._endIndex; n++) { if (!open[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue || !volume[n].Value.HasValue) { continue; } // Calculate Equi-Volume highestVolume = HighestVolumeToRecord(n, volume); x = highestVolume != 0.0 ? volume[n].Value.Value / highestVolume : 0; total += x; if (!chartX._darwasBoxes) { continue; } equiVol = volume[n].Value.Value / highestVolume; equiVol = equiVol / total; equiVol = width * equiVol; x += equiVol; // Record the x value chartX._xMap[cnt] = x; cnt++; } cnt = 0; x = chartX.LeftChartSpace; double px = x; for (n = chartX._startIndex; n < chartX._endIndex; n++) { if (!open[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue || !volume[n].Value.HasValue) { continue; } // Calculate Equi-Volume highestVolume = HighestVolumeToRecord(n, volume); equiVol = highestVolume != 0 ? volume[n].Value.Value / highestVolume : 0.0; equiVol = equiVol / total; equiVol = width * equiVol; x += equiVol; // Record the x value chartX._xMap[cnt] = x; cnt++; double x1 = px; double x2 = x; double y1 = _series._chartPanel.GetY(high[n].Value.Value); double y2 = _series._chartPanel.GetY(low[n].Value.Value); if (y2 == y1) { y1 = y2 - 2; } box = new Types.RectEx(x1, y1, x2, y2); Types.RectEx frame = box; if (chartX._priceStyle == PriceStyleEnum.psEquiVolumeShadow) { if (close[n].Value > open[n].Value) { box.Top = _series._chartPanel.GetY(close[n].Value.Value); } else { box.Bottom = _series._chartPanel.GetY(close[n].Value.Value); } } double wx = x1 + (x2 - x1) / 2; if (chartX._priceStyle == PriceStyleEnum.psCandleVolume) { if (close[n].Value > open[n].Value) { box.Top = _series._chartPanel.GetY(close[n].Value.Value); box.Bottom = _series._chartPanel.GetY(open[n].Value.Value); } else { box.Top = _series._chartPanel.GetY(open[n].Value.Value); box.Bottom = _series._chartPanel.GetY(close[n].Value.Value); } if (box.Bottom == box.Top) { box.Top = box.Bottom - 2; } Utils.DrawLine(wx, y1, wx, y2, customBrush, _series.StrokePattern, _series._strokeThickness, _lines); frame = box; } // Is the bar up or down? int direction; if (n == 0) { direction = close[n].Value > open[n].Value ? up : down; } else { direction = close[n].Value > close[n - 1].Value ? up : down; } if (chartX.ThreeDStyle) { if (direction == up) { Utils.DrawRectangle(box, upGradBrush, _rects); if (chartX._priceStyle == PriceStyleEnum.psEquiVolumeShadow) { Utils.Draw3DRectangle(frame, upBrush, downBrush, _rects3D); } } else { Utils.DrawRectangle(box, downGradBrush, _rects); if (chartX._priceStyle == PriceStyleEnum.psEquiVolumeShadow) { Utils.Draw3DRectangle(frame, upBrush, downBrush, _rects3D); } } } else { if (direction == up) { Utils.DrawRectangle(box, upBrush, _rects); if (chartX._priceStyle == PriceStyleEnum.psEquiVolumeShadow) { Utils.Draw3DRectangle(frame, upBrush, upBrush, _rects3D); } } else { Utils.DrawRectangle(box, downBrush, _rects); if (chartX._priceStyle == PriceStyleEnum.psEquiVolumeShadow) { Utils.Draw3DRectangle(frame, downBrush, downBrush, _rects3D); } } } px = x; } _lines.Stop(); _rects.Stop(); _rects3D.Stop(); _lines.Do(l => l.ZIndex = ZIndexConstants.PriceStyles1); _rects.Do(r => r.ZIndex = ZIndexConstants.PriceStyles2); _rects3D.Do(r => r.ZIndex = ZIndexConstants.PriceStyles3); return(true); }
public override bool Paint() { if (_series.OHLCType == SeriesTypeOHLC.Volume) { return(false); } //Find Series Series open = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Open); if (open == null || open.RecordCount == 0 || open.Painted) { return(false); } Series high = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.RecordCount == 0 || high.Painted) { return(false); } Series low = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.RecordCount == 0 || low.Painted) { return(false); } Series close = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (close == null || close.RecordCount == 0 || close.Painted) { return(false); } _series = close; open.Painted = high.Painted = low.Painted = close.Painted = true; CalculateCandleSpacing(); if (ChartX._barSpacing < 0) { return(false); } _upColor = _series._upColor.HasValue ? _series._upColor.Value : ChartX.UpColor; _downColor = _series._downColor.HasValue ? _series._downColor.Value : ChartX.DownColor; if (_oldOptimizePainting.HasValue && _oldOptimizePainting.Value != ChartX.OptimizePainting) { if (!ChartX.OptimizePainting) { Canvas c = _series._chartPanel._rootCanvas; c.Children.Remove(_pathCandlesDown); c.Children.Remove(_pathCandlesUp); c.Children.Remove(_pathWicksUp); c.Children.Remove(_pathWicksDown); _pathCandlesDown = null; _pathCandlesUp = null; _pathWicksUp = null; _pathWicksDown = null; } else { _candles.RemoveAll(); } } _oldOptimizePainting = ChartX.OptimizePainting; if (ChartX.OptimizePainting) { return(PaintOptimized(new[] { open, high, low, close }, _series)); } if (!_subscribedToCustomBrush) { _subscribedToCustomBrush = true; ChartX.OnCandleCustomBrush += ChartX_OnCandleCustomBrush; } //bool setBrushes = false; if (!_old3DStyle.HasValue || _old3DStyle.Value != ChartX.ThreeDStyle || !_oldUpColor.HasValue || _oldUpColor.Value != _upColor || !_oldDownColor.HasValue || _oldDownColor.Value != _downColor || (ChartX._candleDownOutlineColor.HasValue && ChartX._candleDownOutlineColor.Value != _oldCandleDownOutline) || ChartX._candleUpOutlineColor.HasValue && ChartX._candleUpOutlineColor.Value != _oldCandleUpOutline) { //setBrushes = true; _old3DStyle = ChartX.ThreeDStyle; _oldUpColor = _upColor; _oldDownColor = _downColor; _upBrush = !ChartX.ThreeDStyle ? (Brush) new SolidColorBrush(_upColor) : new LinearGradientBrush { StartPoint = new Point(0, 0.5), EndPoint = new Point(1, 0.5), GradientStops = { new GradientStop { Color = _upColor, Offset = 0 }, new GradientStop { Color = Constants.FadeColor, Offset = 1.25 } } }; #if WPF _upBrush.Freeze(); #endif _downBrush = !ChartX.ThreeDStyle ? (Brush) new SolidColorBrush(_downColor) : new LinearGradientBrush { StartPoint = new Point(0, 0.5), EndPoint = new Point(1, 0.5), GradientStops = { new GradientStop { Color = _downColor, Offset = 0 }, new GradientStop { Color = Constants.FadeColor, Offset = 1.25 } } }; #if WPF _downBrush.Freeze(); #endif if (ChartX._candleDownOutlineColor.HasValue) { _oldCandleDownOutline = ChartX._candleDownOutlineColor.Value; _candleDownOutlineBrush = new SolidColorBrush(ChartX._candleDownOutlineColor.Value); #if WPF _candleDownOutlineBrush.Freeze(); #endif } if (ChartX._candleUpOutlineColor.HasValue) { _oldCandleUpOutline = ChartX._candleUpOutlineColor.Value; _candleUpOutlineBrush = new SolidColorBrush(ChartX._candleUpOutlineColor.Value); #if WPF _candleUpOutlineBrush.Freeze(); #endif } } int n; _candles.C = _series._chartPanel._rootCanvas; _candles.Start(); for (n = ChartX._startIndex; n < ChartX._endIndex; n++) { if (!open[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue) { continue; } Candle candle = _candles.GetPaintObject(_upBrush, _downBrush); candle.Init(_series); //if (setBrushes) //because if we have a small number of bars, then enlarge the new brushes won't be propagated to new candles. candle.SetBrushes(_upBrush, _downBrush, _candleUpOutlineBrush, _candleDownOutlineBrush); candle.SetValues(open[n].Value.Value, high[n].Value.Value, low[n].Value.Value, close[n].Value.Value, ChartX._barSpacing, _halfwick, n - ChartX._startIndex); } _candles.Stop(); _candles.Do(c => c.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
public override bool Paint() { if (_series.OHLCType == SeriesTypeOHLC.Open || _series.OHLCType == SeriesTypeOHLC.Volume) { return(false); } Series sHigh = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (sHigh == null || sHigh.RecordCount == 0 || sHigh.Painted) { return(false); } Series sLow = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (sLow == null || sLow.RecordCount == 0 || sLow.Painted) { return(false); } Series sClose = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (sClose == null || sClose.RecordCount == 0 || sClose.Painted) { return(false); } sHigh.Painted = sLow.Painted = sClose.Painted = true; StockChartX chartX = _series._chartPanel._chartX; double reversalSize = chartX._priceStyleParams[0]; if (reversalSize > 50 || reversalSize < 0.0001) { reversalSize = 1; } double ptsOrPct = chartX._priceStyleParams[1]; if (ptsOrPct != 2 && ptsOrPct != 1) { ptsOrPct = 1; // Points = 1, Percent = 2 } chartX._priceStyleParams[1] = ptsOrPct; chartX._priceStyleParams[0] = reversalSize; double reverse; chartX._psValues1.Clear(); chartX._psValues2.Clear(); chartX._psValues3.Clear(); double nClose = 0, nClose2; double start = 0; const int percent = 2; const int up = 1; const int down = 2; int direction = 0; // up or down int weight = 0; // thick or thin int totalBars = 0; double max = 0, min = 0; double oldMax = 0, oldMin = 0; if (sClose.RecordCount < 3) { return(false); } chartX._xMap = new double[chartX._endIndex - chartX._startIndex + 1]; int cnt = 0; // Count columns that will fit on screen int n; for (n = 0; n < chartX._endIndex + 1; n++) { if (n >= sClose.RecordCount) { continue; } if (!sClose[n].Value.HasValue) { continue; } nClose = sClose[n].Value.Value; if (ptsOrPct == percent) { reverse = nClose * reversalSize; // Percent } else { reverse = reversalSize; // Points } if (direction == 0) { // First bar nClose2 = sClose[n + 1].Value.Value; if (nClose2 > nClose) { direction = up; weight = thick; start = nClose; max = nClose; } else { direction = down; weight = thin; start = nClose2; min = nClose2; } } switch (direction) { case up: if (nClose > max) { max = nClose; if (max > start) { weight = thick; } } else if (nClose < max - reverse) { direction = down; start = max; min = nClose; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBars++; } } break; case down: if (nClose < min) { min = nClose; if (min < start) { weight = thin; } } else if (nClose > min + reverse) { direction = up; start = min; max = nClose; if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBars++; } } break; } } chartX._xCount = totalBars; if (totalBars == 0) { return(false); } double space = chartX.PaintableWidth / totalBars; totalBars = 0; direction = 0; int pWeight = 0; _lines.C = _series._chartPanel._rootCanvas; _lines.Start(); // Calculate from beginning, but only show between startIndex and endIndex double x = _series._chartPanel._chartX.LeftChartSpace; for (n = 0; n < chartX._endIndex; n++) { if (sClose[n].Value.HasValue) { nClose = sClose[n].Value.Value; if (ptsOrPct == percent) { reverse = nClose * reversalSize; // Percent } else { reverse = reversalSize; // Points } if (direction == 0) { // First bar nClose2 = sClose[n + 1].Value.Value; if (nClose2 > nClose) { direction = up; weight = thick; max = nClose; min = nClose; oldMin = nClose2; oldMax = nClose; pWeight = thick; } else { direction = down; weight = thin; min = nClose2; max = nClose2; oldMin = nClose; oldMax = nClose2; pWeight = thin; } } switch (direction) { case up: if (nClose > max) { max = nClose; if (max > oldMax) { weight = thick; } } else if (nClose < max - reverse) { // Paint previous up bar if (weight == pWeight) { oldMax = 0; } if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBar(x, space, max, min, up, weight, oldMax); x += space; } pWeight = weight; direction = down; oldMin = min; min = nClose; totalBars++; } break; case down: if (nClose < min) { min = nClose; if (min < oldMin) { weight = thin; } } else if (nClose > min + reverse) { // Paint previous down bar if (weight == pWeight) { oldMin = 0; } if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBar(x, space, max, min, down, weight, oldMin); x += space; } pWeight = weight; direction = up; oldMax = max; max = nClose; totalBars++; } break; } // Record the x value if (n >= chartX._startIndex && n <= chartX._endIndex) { chartX._xMap[cnt] = x + (space / 2); cnt++; } } chartX._psValues1.Add(new PriceStyleValue(sClose[n].TimeStamp, max)); chartX._psValues2.Add(new PriceStyleValue(sClose[n].TimeStamp, min)); chartX._psValues3.Add(new PriceStyleValue(sClose[n].TimeStamp, (direction == up) ? 1 : -1)); } switch (direction) { case up: if (nClose > max) { max = nClose; if (max >= oldMax) { weight = thick; } } if (weight == pWeight) { oldMax = 0; } break; case down: if (nClose <= min) { min = nClose; if (min < oldMin) { weight = thin; } } if (weight == pWeight) { oldMin = 0; } break; } if (direction == down) { PaintBar(x, 0, max, min, down, weight, oldMin); } else { PaintBar(x, 0, max, min, up, weight, oldMax); } chartX._psValues1.Add(new PriceStyleValue(sClose[n - 1].TimeStamp, max)); chartX._psValues2.Add(new PriceStyleValue(sClose[n - 1].TimeStamp, min)); chartX._psValues3.Add(new PriceStyleValue(sClose[n - 1].TimeStamp, (direction == up) ? 1 : -1)); _lines.Stop(); _lines.Do(l => l.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
public override bool Paint() { //Find Series Series open = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Open); if (open == null || open.RecordCount == 0 || open.Painted) return false; Series high = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.RecordCount == 0 || high.Painted) return false; Series low = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.RecordCount == 0 || low.Painted) return false; Series close = _series._chartPanel.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (close == null || close.RecordCount == 0 || close.Painted) return false; open.Painted = high.Painted = low.Painted = close.Painted = true; StockChartX chartX = _series._chartPanel._chartX; chartX._xMap = new double[chartX._xCount = 0]; const int iStep = 1; int rcnt = chartX.RecordCount; double x2 = chartX.GetXPixel(rcnt); double x1 = chartX.GetXPixel(rcnt - 1); double space = ((x2 - x1) / 2) - chartX._barWidth / 2; if (space > 20) space = 20; if (space > _series._chartPanel._chartX._barSpacing) _series._chartPanel._chartX._barSpacing = space; space = Math.Ceiling(space * 0.75); Color upColor = _series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor; Color downColor = _series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor; _upBrush = !chartX.ThreeDStyle ? (Brush)new SolidColorBrush(upColor) : new LinearGradientBrush { StartPoint = new Point(0, 0.5), EndPoint = new Point(1, 0.5), GradientStops = { new GradientStop { Color = upColor, Offset = 0 }, new GradientStop { Color = Constants.FadeColor, Offset = 1.25 } } }; _downBrush = !chartX.ThreeDStyle ? (Brush)new SolidColorBrush(downColor) : new LinearGradientBrush { StartPoint = new Point(0, 0.5), EndPoint = new Point(1, 0.5), GradientStops = { new GradientStop { Color = downColor, Offset = 0 }, new GradientStop { Color = Constants.FadeColor, Offset = 1.25 } } }; if (chartX._candleDownOutlineColor.HasValue) _candleDownOutlineBrush = new SolidColorBrush(chartX._candleDownOutlineColor.Value); if (chartX._candleUpOutlineColor.HasValue) _candleUpOutlineBrush = new SolidColorBrush(chartX._candleUpOutlineColor.Value); double wick = chartX._barWidth; double halfwick = wick / 2; if (halfwick < 1) halfwick = 1; int n; //int t = Environment.TickCount; _candles.C = _series._chartPanel._rootCanvas; _candles.Start(); Debug.WriteLine("StartIndex " + chartX._startIndex + " EndIndex " + chartX._endIndex); for (n = chartX._startIndex; n < chartX._endIndex; n += iStep) { if (n == 0 && (!open[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue)) continue; if (n > 0 && (!open[n].Value.HasValue || !high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue || !open[n - 1].Value.HasValue || !close[n - 1].Value.HasValue)) continue; CandleHeikinAshi candle = _candles.GetPaintObject(_upBrush, _downBrush); candle.Init(_series); candle.SetBrushes(_upBrush, _downBrush, _candleUpOutlineBrush, _candleDownOutlineBrush); candle.SetValues(open[n], high[n], low[n], close[n], space, halfwick, n - chartX._startIndex); } _candles.Stop(); _candles.Do(c => c.ZIndex = ZIndexConstants.PriceStyles1); Debug.WriteLine("Candles count " + _candles.Count); return true; }
public override bool Paint() { if (_series._seriesTypeOHLC != SeriesTypeOHLC.Close) { return(false); } StockChartX chartX = _series._chartPanel._chartX; Series open = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Open); Series high = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.Painted || high.RecordCount == 0) { return(false); } Series low = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.Painted || low.RecordCount == 0) { return(false); } Series close = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (close == null || close.Painted || close.RecordCount == 0) { return(false); } high.Painted = low.Painted = close.Painted = true; if (!_subscribedToCustomBrush) { _subscribedToCustomBrush = true; chartX.OnCandleCustomBrush += ChartX_OnCandleCustomBrush; } bool changeBrushes = false; Color upColor = _series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor; Color downColor = _series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor; if (!_oldUpColor.HasValue || _oldUpColor.Value != upColor) { _upBrush = new SolidColorBrush(upColor); _upBrush.Freeze(); _oldUpColor = upColor; changeBrushes = true; } if (!_oldDownColor.HasValue || _oldDownColor.Value != downColor) { _downBrush = new SolidColorBrush(_series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor); _downBrush.Freeze(); _oldDownColor = downColor; changeBrushes = true; } if (!_oldStrokeColor.HasValue || _oldStrokeColor.Value != _series._strokeColor) { _customBrush = new SolidColorBrush(_series._strokeColor); _customBrush.Freeze(); _oldStrokeColor = _series._strokeColor; changeBrushes = true; } int rcnt = chartX.RecordCount; double x2 = chartX.GetXPixel(rcnt); double x1 = chartX.GetXPixel(rcnt - 1); double space = ((x2 - x1) / 2) - chartX._barWidth / 2; if (space > 20) { space = 20; } chartX._barSpacing = space; int cnt = 0; ((ModulusFE.Stock)_series)._priceStyleStock = this; _stocks.C = _series._chartPanel._rootCanvas; _stocks.Start(); for (int n = chartX._startIndex; n < chartX._endIndex; n++, cnt++) { if (!high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue) { continue; } PaintObjects.Stock stock = _stocks.GetPaintObject(_upBrush, _downBrush, _customBrush); stock.Init(_series); if (changeBrushes) { stock.SetBrushes(_upBrush, _downBrush, _customBrush); } stock.SetValues(open != null ? open[n].Value : null, high[n].Value.Value, low[n].Value.Value, close[n].Value.Value, space, n - chartX._startIndex); } _stocks.Stop(); _stocks.Do(s => s.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
public override bool Paint() { /* * pCtrl->priceStyleParams[0] = lines * 7 columns * width = 300 * 300 / 7 = 42.85 pixels per column */ if (_series.OHLCType == SeriesTypeOHLC.Open) { return(false); } StockChartX chartX = _series._chartPanel._chartX; Series high = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.High); if (high == null || high.Painted || high.RecordCount == 0) { return(false); } Series low = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Low); if (low == null || low.Painted || low.RecordCount == 0) { return(false); } Series close = chartX.GetSeriesOHLCV(_series, SeriesTypeOHLC.Close); if (close == null || close.Painted || close.RecordCount == 0) { return(false); } high.Painted = low.Painted = close.Painted = true; double width = chartX.PaintableWidth; double lines = chartX._priceStyleParams[0]; if (lines > 50 || lines < 1) { lines = 3; chartX._priceStyleParams[0] = lines; } _highs = new double[(int)lines]; _lows = new double[(int)lines]; double nClose, nHH = 0, nLL = 0; const int white = 1; const int black = 2; double nStart = 0; int block = 0; // black or white int totalBlocks = 0; chartX._xMap = new double[chartX._endIndex - chartX._startIndex + 1]; int cnt = 0; chartX._psValues1.Clear(); chartX._psValues2.Clear(); chartX._psValues3.Clear(); // Count columns that will fit on screen int n; for (n = 0; n < chartX._endIndex; n++) { if (!high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue) { continue; } // Calculate N Line Break nClose = (double)close[n].Value; switch (block) { case white: if (IsNewBlock(-1, nClose)) { nHH = nStart; // New black block nLL = nClose; nStart = nClose; block = black; AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks++; } } if (IsNewBlock(1, nClose)) { nHH = nClose; // New white block nLL = nStart; nStart = nClose; block = white; AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks++; } } break; case black: if (IsNewBlock(1, nClose)) { nHH = nClose; // New white block nLL = nStart; nStart = nClose; block = white; AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks++; } } if (IsNewBlock(-1, nClose)) { nHH = nStart; // New black block nLL = nClose; nStart = nClose; block = black; AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks++; } } break; } if (block != 0) { continue; // Prime first block } double nClose2 = (double)close[n + 1].Value; if (nClose2 > nClose) { block = white; nHH = nClose2; nLL = nClose; nStart = nClose; } else { block = black; nHH = nClose; nLL = nClose2; nStart = nClose2; } AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks++; } } chartX._xCount = totalBlocks; _highs = new double[(int)lines]; _lows = new double[(int)lines]; Color upColor = _series._upColor.HasValue ? _series._upColor.Value : chartX.UpColor; Color downColor = _series._downColor.HasValue ? _series._downColor.Value : chartX.DownColor; Brush upBrush = new SolidColorBrush(upColor); Brush downBrush = new SolidColorBrush(downColor); Brush upGradBrush = Utils.CreateFadeVertBrush(upColor, Colors.Black); Brush downGradBrush = Utils.CreateFadeVertBrush(downColor, Colors.Black); _rects.C = _series._chartPanel._rootCanvas; _rects.Start(); // Paint columns block = 0; double x = chartX.LeftChartSpace; if (totalBlocks == 0) { return(false); } double space = width / totalBlocks; totalBlocks = 0; // Calculate from beginning, but only show between startIndex and endIndex for (n = 0; n < chartX._endIndex; n++) { if (!high[n].Value.HasValue || !low[n].Value.HasValue || !close[n].Value.HasValue) { continue; } // Calculate N Line Break nClose = (double)close[n].Value; switch (block) { case white: if (IsNewBlock(-1, nClose)) { // Paint last white block if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, 1, n, close); x += space; } nHH = nStart; // New black block nLL = nClose; nStart = nClose; block = black; AddBlock(nHH, nLL); totalBlocks++; } if (IsNewBlock(1, nClose)) { // Paint last black block if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, 1, n, close); x += space; } nHH = nClose; // New white block nLL = nStart; nStart = nClose; block = white; AddBlock(nHH, nLL); totalBlocks++; } break; case black: if (IsNewBlock(1, nClose)) { // Paint last white block if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, -1, n, close); x += space; } nHH = nClose; // New white block nLL = nStart; nStart = nClose; block = white; AddBlock(nHH, nLL); totalBlocks++; } if (IsNewBlock(-1, nClose)) { // Paint last black block if (n >= chartX._startIndex && n <= chartX._endIndex) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, -1, n, close); x += space; } nHH = nStart; // New black block nLL = nClose; nStart = nClose; block = black; AddBlock(nHH, nLL); totalBlocks++; } break; } if (block == 0) { // Prime first block double nClose2 = (double)close[n + 1].Value; if (nClose2 > nClose) { block = white; nHH = nClose2; nLL = nClose; nStart = nClose; } else { block = black; nHH = nClose; nLL = nClose2; nStart = nClose2; } AddBlock(nHH, nLL); if (n >= chartX._startIndex && n <= chartX._endIndex) { totalBlocks = 1; } x = chartX.LeftChartSpace; } // Record the x value if (n >= chartX._startIndex && n <= chartX._endIndex) { chartX._xMap[cnt] = x + (space / 2); cnt++; } } // Finish last block if (block == black) { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, -1, n, close); } else { PaintBox(upBrush, downBrush, upGradBrush, downGradBrush, x, space, nHH, nLL, 1, n, close); } _rects.Stop(); _rects.Do(r => r.ZIndex = ZIndexConstants.PriceStyles1); return(true); }
internal override void Paint() { //Debug.WriteLine("ChartPanel heat map paint"); if (!_templateLoaded || _painting) { _timers.StopTimerWork(TimerSizeChanged); return; } _rects.C = _rootCanvas; _rects.Start(); _labels.C = _rootCanvas; _labels.Start(); List <Series> indicators = _chartX.IndicatorsCollection.Cast <Series>().ToList(); var seriesForHeatMap = _chartX.SeriesCollection.Where(s => s.ShowInHeatMap); indicators.AddRange(seriesForHeatMap); //IEnumerable<Indicator> indicators = _chartX.IndicatorsCollection; if (indicators.Count() == 0) { _timers.StopTimerWork(TimerSizeChanged); _rects.Stop(); _labels.Stop(); return; } _painting = true; double panelHeight = _rootCanvas.ActualHeight / indicators.Count; double rectWidth = _chartX.PaintableWidth / (_chartX._endIndex - _chartX._startIndex); int indicatorIndex = 0; foreach (Series indicator in indicators) { double min; double max; indicator.DM.VisibleMinMax(indicator.SeriesIndex, out min, out max); if (indicator.RecordCount == 0) { continue; } int cnt = 0; for (int i = _chartX._startIndex; i < _chartX._endIndex; i++, cnt++) { double?value = indicator[i].Value; if (!value.HasValue || min == max) { continue; } Brush brush = _brushes[(int)((_brushes.Length - 1) * (value.Value - min) / (max - min))]; double x = cnt * rectWidth + _chartX.LeftChartSpace; double y = indicatorIndex * panelHeight; Rectangle rectangle = Utils.DrawRectangle(x, y, x + rectWidth + 1, y + panelHeight, brush, _rects); rectangle._rectangle.Stroke = brush; } Label lbl = Utils.DrawText(_chartX.LeftChartSpace + 10, indicatorIndex * panelHeight + 2, indicator.Title, _chartX.HeatPanelLabelsForeground, _chartX.HeatPanelLabelsFontSize, _chartX.FontFamily, _labels); #if WPF lbl._textBlock.Background = _chartX.HeatPanelLabelsBackground; #endif indicatorIndex++; } _rects.Stop(); _labels.Stop(); _rects.Do(r => r.ZIndex = ZIndexConstants.DarvasBoxes1); _labels.Do(l => l.ZIndex = ZIndexConstants.DarvasBoxes2); _painting = false; _timers.StopTimerWork(TimerSizeChanged); }
internal override void DrawLineStudy(Types.RectEx rect, LineStatus lineStatus) { if (lineStatus == LineStatus.StartPaint) { for (int i = 0; i < _lines.Length; i++) { _lines[i] = new System.Windows.Shapes.Line { Tag = this }; Canvas.SetZIndex(_lines[i], ZIndexConstants.LineStudies1); C.Children.Add(_lines[i]); } if (_contextLine == null) { _contextLine = new ContextLine(this); _chartX.InvokeLineStudyCreated(new StockChartX.LineStudyCreatedEventArgs(this)); } _internalObjectCreated = true; return; } rect.Normalize(); if (rect.Width == 0) { return; } int revX1 = (int)(_chartX.GetReverseXInternal(rect.Left) + _chartX._startIndex); int revX2 = (int)(_chartX.GetReverseXInternal(rect.Right) + _chartX._startIndex); if (revX1 < 0) { revX1 = 0; } if (revX2 < 0) { revX2 = 0; } if (revX1 == revX2) { return; } // Get the highest high of the high series. // Note: this code makes the vague assumption // that only one symbol exists on this panel. Series sHigh = GetSeriesOHLC(SeriesTypeOHLC.High); if (sHigh == null) { return; } Series sLow = GetSeriesOHLC(SeriesTypeOHLC.Low); if (sLow == null) { return; } Series sClose = GetSeriesOHLC(SeriesTypeOHLC.Close); if (revX1 >= sHigh.RecordCount) { revX1 = sHigh.RecordCount; } if (revX2 >= sHigh.RecordCount) { revX2 = sHigh.RecordCount; } //********** // Perform linear regression on the data double xSum = 0, ySum = 0, xSquaredSum = 0, xYSum = 0; int n, j; if (revX1 > revX2) { revX2 = revX1; } int x = revX2 - revX1; for (n = 1; n != x + 1; ++n) { j = revX1 + n - 1; xSum += n; ySum += sClose[j].Value.Value; xSquaredSum += (n * n); xYSum += (sClose[j].Value.Value * n); } n = x; double q1 = n != 0 ? (xYSum - ((xSum * ySum) / n)) : 0; double q2 = n != 0 ? (xSquaredSum - ((xSum * xSum) / n)) : 0; double slope = q2 != 0 ? (q1 / q2) : 0; double leftValue = slope != 0 ? (((1 / (double)n) * ySum) - (((int)((double)n / 2)) * slope)) : 0.0; double rightValue = ((n * slope) + leftValue); double right = (x - 1); double inc = 0; if (right != 0) { inc = (rightValue - leftValue) / right; } double prevVal = 0.0; j = 0; // Find max distance from linear regression line double lowestLow = sHigh[0].Value.Value; double highestHigh = 0; for (n = revX1; n < revX2; ++n) { j++; double val = leftValue + inc * (j - 1); if (prevVal != 0) { if (sHigh[n].Value.Value - val > highestHigh) { highestHigh = sHigh[n].Value.Value - val; } if (val - sLow[n].Value.Value < lowestLow && val - sLow[n].Value.Value > 0) { lowestLow = val - sLow[n].Value.Value; } } prevVal = val; } if (highestHigh > lowestLow) { lowestLow = highestHigh; } if (lowestLow > highestHigh) { highestHigh = lowestLow; } _linesSel.C = C; double lX1 = _chartX.GetXPixel(revX1 - _chartX._startIndex); double lX2 = _chartX.GetXPixel(revX2 - _chartX._startIndex + 1); j = 0; for (n = revX1; n < revX2; n++, j++) { double val = leftValue + inc * (j - 1); double lY1 = _chartPanel.GetY(prevVal - lowestLow); double lY2 = _chartPanel.GetY(val - lowestLow); if (prevVal != 0) { Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _lines[0]); } lY1 = _chartPanel.GetY(prevVal); lY2 = _chartPanel.GetY(val); if (prevVal != 0) { Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _lines[1]); } lY1 = _chartPanel.GetY(prevVal + highestHigh); lY2 = _chartPanel.GetY(val + highestHigh); if (prevVal != 0) { Utils.DrawLine(lX1, lY1, lX2, lY2, Stroke, StrokeType, StrokeThickness, _lines[2]); } prevVal = val; } _linesSel.Start(); if (lineStatus == LineStatus.Moving || lineStatus == LineStatus.Painting) { Utils.DrawLine(lX1, 0, lX1, C.ActualHeight, Stroke, LinePattern.Dot, StrokeThickness, _linesSel); Utils.DrawLine(lX2, 0, lX2, C.ActualHeight, Stroke, LinePattern.Dot, StrokeThickness, _linesSel); } _linesSel.Stop(); _linesSel.Do(l => l.ZIndex = ZIndexConstants.LineStudies1); }
internal void Paint() { try { if (_painting) { return; } _painting = true; _timerRepaint.StopTimerWork(TimerRepaint); #if WPF #if DEMO if (!string.IsNullOrEmpty(_demoText) && _labelDemo == null) { _labelDemo = new Label(); _labelDemo.AddTo(this); _labelDemo.Left = 10; _labelDemo.Top = 2; // _labelDemo._textBlock.Opacity = 0.7; _labelDemo._textBlock.Foreground = Brushes.Red; _labelDemo.Text = _demoText; _labelDemo._textBlock.FontSize = 16; _labelDemo.ZIndex = 100; } #endif #endif Rect rcBounds = new Rect(0, 0, ActualWidth, ActualHeight); if (_linesPath == null) { _linesPath = new Path { Stroke = _chartX.GridStroke, StrokeThickness = 1, }; Children.Add(_linesPath); } //Background = _chartX.Background; //_lines.C = this; _labels.C = this; //_lines.Start(); _labels.Start(); int startIndex = _chartX._startIndex; GeometryGroup lines = new GeometryGroup(); //Utils.DrawLine(rcBounds.Left, 0, rcBounds.Right, 0, _chartX.GridStroke, LinePattern.Solid, 1, _lines); lines.Children.Add(new LineGeometry { StartPoint = new Point(rcBounds.Left, 0), EndPoint = new Point(rcBounds.Right, 0), }); int rcnt = _chartX.VisibleRecordCount; double periodPixels = _chartX.GetXPixel(rcnt) / rcnt; if (periodPixels < 1) { periodPixels = 1; } _chartX._xGridMap.Clear(); double tradeWeek = periodPixels * 5; // 5 trading days in a week (avg) double tradeMonth = periodPixels * 20; // 20 trading days in a month (avg) double tradeYear = periodPixels * 253; // 253 trading days in a year (avg) double averageCharWidth = _chartX.GetTextWidth("0"); // Level 1: // YYYY double level1 = averageCharWidth * 4; // Level 2: // YY F M A M J J A S O N D double level2 = averageCharWidth * 2; // Level 3: // YY Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec double level3 = averageCharWidth * 3; // Level 4: // YYYY February March April May June July August September October November December double level4 = averageCharWidth * 9; // Level 5: // From -5 periods on right end, begin: // Jan DD Feb DD Mar DD Apr DD May DD Jun DD Jul DD Aug DD Sep DD Oct DD Nov DD Dec DD double level5 = averageCharWidth * 6; // Level 6 // Jan DD HH:MM double level6 = averageCharWidth * 10; double incr; int xGrid = 0; double x, lx = 0; if (_chartX.RealTimeXLabels) { string prevDay = ""; incr = level6; string timeFormat = "HH:mm"; if (_chartX.ShowSeconds) { incr += averageCharWidth * 2; timeFormat = "HH:mm:ss"; } for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); if (x == lx) { continue; } DateTime dDate = DM.GetTimeStampByIndex(period + startIndex); //if (dDate.Minute % 15 != 0) continue; if (incr > level6) { incr = 0; //Draw vertical line //_renderDevice.PlotUnitSeparator((float)x, true, 0); //Utils.DrawLine(x, 0, x, rcBounds.Height / 2, _chartX.GridStroke, LinePattern.Solid, 1, _lines); lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); string szTime = dDate.ToString(timeFormat); string szDay = dDate.ToString("dd"); string szMonth = dDate.ToString("MMM"); string szDate; if (prevDay != szDay) { prevDay = szDay; szDate = szMonth + " " + szDay + " " + szTime; level6 = averageCharWidth * 12; lx += level6 / 2; } else { szDate = szTime; } //_renderDevice.PlotUnitText((float)x, szDate, 0); var lb = _labels.GetPaintObject(); lb.Left = x; lb.Top = 1; lb.Text = szDate; //Utils.DrawText(x, 1, szDate, _chartX.FontForeground, _chartX.FontSize, _chartX.FontFamily, _labels); _chartX._xGridMap[xGrid++] = x; } incr += x - lx; lx = x; } _painting = false; _linesPath.Data = (System.Windows.Media.Geometry)lines.GetAsFrozen(); //_lines.Stop(); _labels.Stop(); return; } lx = 0; double oldX = -1; string sCache = "#"; string sDate; DateTime timestamp; DateTime?prevDate = null; if (level5 <= tradeWeek) { incr = level5; for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); timestamp = DM.GetTimeStampByIndex(period + startIndex); if (prevDate.HasValue && prevDate.Value.Year != timestamp.Year) { sDate = timestamp.ToString("yyyy MMM"); } else { sDate = timestamp.ToString("dd MMM"); } prevDate = timestamp; if (incr > level5 && sCache != sDate && oldX != x) { incr = 0; //Reset lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); var lb = _labels.GetPaintObject(); lb.Left = x + 2; lb.Top = 1; lb.Text = sDate; sCache = sDate; oldX = x; _chartX._xGridMap[xGrid++] = x; } incr += (x - lx); lx = x; } } else if (level4 <= tradeMonth) { incr = level4; for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); timestamp = DM.GetTimeStampByIndex(period + startIndex); sDate = timestamp.ToString("MMMM"); if (timestamp.Month == 1) { sDate = timestamp.ToString("yyyy MMM"); } if (incr > level4 && sDate != sCache) { incr = 0; lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); var lb = _labels.GetPaintObject(); lb.Left = x; lb.Top = 1; lb.Text = sDate; xGrid++; } sCache = sDate; incr += (x - lx); lx = x; _chartX._xGridMap[xGrid] = x; } } else if (level3 + 2 <= tradeMonth) { incr = level3; sCache = "#"; for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); timestamp = DM.GetTimeStampByIndex(period + startIndex); sDate = timestamp.ToString("MMM"); if (timestamp.Month == 1) { sDate = timestamp.ToString("yy"); } if (incr > level3 && sCache != sDate) { incr = 0; lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); var lb = _labels.GetPaintObject(); lb.Left = x; lb.Top = 1; lb.Text = sDate; xGrid++; } sCache = sDate; incr += (x - lx); lx = x; _chartX._xGridMap[xGrid] = x; } } else if (level2 <= tradeMonth) { incr = level2; sCache = "#"; for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); timestamp = DM.GetTimeStampByIndex(period + startIndex); sDate = timestamp.ToString("MMM"); string sTemp; if (timestamp.Month == 1) { sDate = timestamp.ToString("yy"); sTemp = sDate; } else { sTemp = sDate.Substring(0, 1); } if (incr > level2 && sCache != sDate) { incr = 0; lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); var lb = _labels.GetPaintObject(); lb.Left = x; lb.Top = 1; lb.Text = sTemp; xGrid++; } sCache = sDate; incr += (x - lx); lx = x; _chartX._xGridMap[xGrid] = x; } } else if (level1 <= tradeYear) { incr = level1; sCache = "#"; for (int period = 0; period < rcnt; period++) { x = _chartX.GetXPixel(period); if (x == -1) { break; } timestamp = DM.GetTimeStampByIndex(period + startIndex); sDate = timestamp.ToString("yyyy"); if (incr > level1 && sDate != sCache) { incr = 0; lines.Children.Add(new LineGeometry { StartPoint = new Point(x, 0), EndPoint = new Point(x, rcBounds.Height / 2) }); var lb = _labels.GetPaintObject(); lb.Left = x; lb.Top = 1; lb.Text = sDate; xGrid++; } sCache = sDate; incr += (x - lx); lx = x; _chartX._xGridMap[xGrid] = x; } } //_lines.Stop(); _linesPath.Data = (System.Windows.Media.Geometry)lines.GetAsFrozen(); _labels.Stop(); } finally { _painting = false; //after calendar is painted must instruct each panel to repaint the X Grid if needed if (_chartX.XGrid) { foreach (var panel in _chartX.PanelsCollection) { panel.PaintXGrid(); } } } }
internal override void DrawLineStudy(Types.RectEx rect, LineStatus lineStatus) { if (lineStatus == LineStatus.StartPaint) { for (int i = 0; i < _lines.Length; i++) { _lines[i] = new Line { Tag = this }; Canvas.SetZIndex(_lines[i], ZIndexConstants.LineStudies1); C.Children.Add(_lines[i]); } if (_contextLine == null) { _contextLine = new ContextLine(this); _chartX.InvokeLineStudyCreated(new StockChartX.LineStudyCreatedEventArgs(this)); } return; } // **************************************************************** // *Note: This line study requires OHLC series in the owner panel!* // **************************************************************** rect.Normalize(); if (rect.Width == 0) { return; } int revX1 = (int)(_chartX.GetReverseXInternal(rect.Left) + _chartX._startIndex); int revX2 = (int)(_chartX.GetReverseXInternal(rect.Right) + _chartX._startIndex); if (revX1 < 0) { revX1 = 0; } if (revX2 < 0) { revX2 = 0; } if (revX1 == revX2) { return; } // Get the highest high of the high series. // Note: this code makes the vague assumption // that only one symbol exists on this panel. Series sHigh = GetSeriesOHLC(SeriesTypeOHLC.High); if (sHigh == null) { return; } Series sLow = GetSeriesOHLC(SeriesTypeOHLC.Low); if (sLow == null) { return; } double highestHigh = sHigh.MaxFromInterval(ref revX1, ref revX2); double lowestLow = sLow.MinFromInterval(ref revX1, ref revX2); double value = highestHigh + ((highestHigh - lowestLow) / 4); _linesSel.C = C; _linesSel.Start(); for (int i = 0; i < _lines.Length; i++) { value -= ((highestHigh - lowestLow) / 4); rect.Top = _chartPanel.GetY(value); Utils.DrawLine(rect.Left, rect.Top, rect.Right, rect.Top, Stroke, i == 2 ? LinePattern.Dot : StrokeType, StrokeThickness, Opacity, _lines[i]); } if (lineStatus == LineStatus.Moving || lineStatus == LineStatus.Painting) { Utils.DrawLine(rect.Left, 0, rect.Left, C.ActualHeight, Stroke, LinePattern.Dot, StrokeThickness, Opacity, _linesSel); Utils.DrawLine(rect.Right, 0, rect.Right, C.ActualHeight, Stroke, LinePattern.Dot, StrokeThickness, Opacity, _linesSel); } _linesSel.Stop(); _internalObjectCreated = true; _linesSel.Do(l => l.ZIndex = ZIndexConstants.LineStudies1); }
internal void Render() { if (_linesPath == null) { _linesPath = new Path { StrokeThickness = 1 }; Children.Add(_linesPath); SetZIndex(_linesPath, ZIndexConstants.GridLines); _linesPath.SetBinding(Shape.StrokeProperty, _chartPanel._chartX.CreateOneWayBinding("GridStroke")); } _labels.C = this; _labels.Start(); Rect rcBounds = new Rect(0, 0, ActualWidth, ActualHeight); if (Utils.GetIsInDesignMode(this)) { _min = 0; _max = 1; } if (rcBounds.Height < 2) { return; } //int decimals = _chartPanel._hasVolume ? 0 : _chartPanel._chartX.ScalePrecision; string formatString = _chartPanel.FormatYValueString; bool isVolume = _chartPanel._hasVolume; // && (_chartPanel._chartX.VolumePostfixLetter.Length > 0); double k = rcBounds.Height / LabelCount; double min = _chartPanel.ScalingType == ScalingTypeEnum.Linear || isVolume ? _min : (_min > 0 ? Math.Log10(_min) : 0); double max = _chartPanel.ScalingType == ScalingTypeEnum.Linear || isVolume ? _max : Math.Log10(_max); double startValue = min + (max - min) * (_chartPanel._yOffset / rcBounds.Height); GridStep = (max - min) / LabelCount; _chartPanel.StartPaintingYGridLines(); GeometryGroup gLines = new GeometryGroup(); StringBuilder stringBuilder = new StringBuilder(); double textHeight = _chartPanel._chartX.GetTextHeight("9"); for (int i = 0; i < LabelCount; i++) { double y = rcBounds.Height - (i * k); if (double.IsNaN(y)) { continue; } if (y < 0) { break; } if (i > 0) { gLines.Children.Add(new LineGeometry { StartPoint = new Point(_isLeftAligned ? rcBounds.Width - 10 : 0, y), EndPoint = new Point(_isLeftAligned ? rcBounds.Width : 10, y), }); _chartPanel.PaintYGridLine(y); } stringBuilder.Length = 0; double value = startValue + (GridStep * i); if (_chartPanel.ScalingType == ScalingTypeEnum.Semilog && !isVolume) { value = Math.Pow(10, value); } if (isVolume) { value /= _chartPanel._chartX.VolumeDivisor; } stringBuilder.AppendFormat(formatString, value); if (isVolume && !string.IsNullOrEmpty(_chartPanel._chartX.VolumePostfixLetter)) { stringBuilder.Append(" ").Append(_chartPanel._chartX.VolumePostfixLetter); } if (!string.IsNullOrEmpty(_chartPanel.YAxisPostFix)) { stringBuilder.Append(_chartPanel.YAxisPostFix); } Label tb = _labels.GetPaintObject(); tb.Text = stringBuilder.ToString(); tb.Left = _isLeftAligned ? rcBounds.Width - _chartPanel._chartX.GetTextWidth(stringBuilder.ToString()) - 2 : 2; tb.Top = y - textHeight - 2; } gLines.Children.Add(new LineGeometry { StartPoint = new Point(_isLeftAligned ? rcBounds.Width - 1 : 1, 0), EndPoint = new Point(_isLeftAligned ? rcBounds.Width - 1 : 1, rcBounds.Height), }); _chartPanel.StopPaintingYGridLines(); _painted = true; _labels.Stop(); _linesPath.Data = gLines; }