/// <summary> /// Public constructor /// </summary> public IndicatorComp() { compName = "Not defined"; dataType = IndComponentType.NotDefined; chartType = IndChartType.NoChart; chartColor = Color.Red; firstBar = 0; previous = 0; isDynInfo = true; values = new double[] { }; posPriceDependence = PositionPriceDependence.None; }
/// <summary> /// Public constructor /// </summary> public IndicatorComp() { compName = "Not defined"; dataType = IndComponentType.NotDefined; chartType = IndChartType.NoChart; chartColor = Color.Red; firstBar = 0; previous = 0; isDynInfo = true; values = new double[] { }; posPriceDependence = PositionPriceDependence.None; }
/// <summary> /// Prepare the parameters /// </summary> public void SetUpChart() { // Panel caption stringCaptionText = Language.T("Indicator Chart"); fontCaptionText = new Font(Font.FontFamily, 9); captionHeight = Math.Max(fontCaptionText.Height, 18); captionWidth = this.ClientSize.Width; brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); rectfCaption = new RectangleF(0, 0, captionWidth, captionHeight); stringFormatCaption = new StringFormat(); stringFormatCaption.Alignment |= StringAlignment.Center; stringFormatCaption.LineAlignment |= StringAlignment.Center; stringFormatCaption.Trimming |= StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags |= StringFormatFlags.NoWrap; if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) { return; } clSzWidth = this.ClientSize.Width; clSzHeight = this.ClientSize.Height; xLeft = space; xRight = clSzWidth - space; yTop = (int)captionHeight + space; yBottom = clSzHeight - scrollBar.Height - space; yPrcBottom = yBottom; // Price chart y inds = 0; // Count of separated indicators indHeight = 0; // Height of Ind charts aiIndSlot = new int[12]; penFore = new Pen(LayoutColors.ColorChartFore); penVolume = new Pen(LayoutColors.ColorVolume); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); for (int slot = Data.Strategy.Slots - 1; slot >= 0; slot--) { if (Data.Strategy.Slot[slot].SeparatedChart) { aiIndSlot[inds++] = slot; } } if (inds > 0) { indHeight = (yBottom - yTop) / (2 + inds); yPrcBottom = yBottom - inds * indHeight; } maxPrice = double.MinValue; minPrice = double.MaxValue; maxVolume = int.MinValue; for (int bar = firstBar; bar <= lastBar; bar++) { if (Data.High[bar] > maxPrice) { maxPrice = Data.High[bar]; } if (Data.Low[bar] < minPrice) { minPrice = Data.Low[bar]; } if (Data.Volume[bar] > maxVolume) { maxVolume = Data.Volume[bar]; } } minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point * 10; maxPrice = Math.Round(maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point * 10; scaleY = (yPrcBottom - yTop) / (maxPrice - minPrice); scaleYVol = maxVolume > 0 ? ((yPrcBottom - yTop) / 8d) / maxVolume : 0d; // Volume, Lots and Price x = new int[chartBars]; yOpen = new int[chartBars]; yHigh = new int[chartBars]; yLow = new int[chartBars]; yClose = new int[chartBars]; yVolume = new int[chartBars]; rectPosition = new Rectangle[chartBars]; brushPosition = new Brush[chartBars]; int index = 0; for (int bar = firstBar; bar <= lastBar; bar++) { x[index] = (bar - firstBar) * barPixels + xLeft; yOpen[index] = (int)(yPrcBottom - (Data.Open[bar] - minPrice) * scaleY); yHigh[index] = (int)(yPrcBottom - (Data.High[bar] - minPrice) * scaleY); yLow[index] = (int)(yPrcBottom - (Data.Low[bar] - minPrice) * scaleY); yClose[index] = (int)(yPrcBottom - (Data.Close[bar] - minPrice) * scaleY); yVolume[index] = (int)(yPrcBottom - Data.Volume[bar] * scaleYVol); // Draw position lots if (Backtester.IsPos(bar)) { int iPosHight = (int)(Math.Max(Backtester.SummaryLots(bar) * 2, 2)); int iPosY = yPrcBottom - iPosHight; if (Backtester.SummaryDir(bar) == PosDirection.Long) { // Long rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); } else if (Backtester.SummaryDir(bar) == PosDirection.Short) { // Short rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); } else { // Close position rectPosition[index] = new Rectangle(x[index], iPosY - 2, 1, 2); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); } } else { // There is no position rectPosition[index] = Rectangle.Empty; brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart slots = Data.Strategy.Slots; bIsSeparatedChart = new bool[slots]; iComponentLenght = new int[slots]; chartType = new IndChartType[slots][]; chartLine = new Point[slots][][]; chartDot = new Rectangle[slots][][]; chartLevel = new Rectangle[slots][][]; chartValue = new double[slots][][]; chartPen = new Pen[slots][][]; chartBrush = new Brush[slots][]; for (int iSlot = 0; iSlot < slots; iSlot++) { bIsSeparatedChart[iSlot] = Data.Strategy.Slot[iSlot].SeparatedChart; int iLenght = Data.Strategy.Slot[iSlot].Component.Length; iComponentLenght[iSlot] = iLenght; chartType[iSlot] = new IndChartType[iLenght]; chartLine[iSlot] = new Point[iLenght][]; chartDot[iSlot] = new Rectangle[iLenght][]; chartLevel[iSlot] = new Rectangle[iLenght][]; chartValue[iSlot] = new double[iLenght][]; chartPen[iSlot] = new Pen[iLenght][]; chartBrush[iSlot] = new Brush[iLenght]; } for (int slot = 0; slot < slots; slot++) { if (bIsSeparatedChart[slot]) { continue; } for (int comp = 0; comp < iComponentLenght[slot]; comp++) { chartType[slot][comp] = Data.Strategy.Slot[slot].Component[comp].ChartType; if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Line || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudUp || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudDown) { // Line chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLine[slot][comp] = new Point[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); if (dValue == 0) { chartLine[slot][comp][bar - firstBar] = chartLine[slot][comp][Math.Max(bar - firstBar - 1, 0)]; } else { chartLine[slot][comp][bar - firstBar] = new Point(ix, iy); } } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Dot) { // Dots chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartDot[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartDot[slot][comp][bar - firstBar] = new Rectangle(ix, iy, 1, 1); } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Level) { // Level chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLevel[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartLevel[slot][comp][bar - firstBar] = new Rectangle(ix, iy, barPixels, 1); } } } } // Separate indicators yIndTop = new int[inds]; yIndBottom = new int[inds]; dMaxValue = new double[inds]; dMinValue = new double[inds]; dScale = new double[inds]; for (int ind = 0; ind < inds; ind++) { yIndTop[ind] = yBottom - (ind + 1) * indHeight + 1; yIndBottom[ind] = yBottom - ind * indHeight - 1; dMaxValue[ind] = double.MinValue; dMinValue[ind] = double.MaxValue; int iSlot = aiIndSlot[ind]; double dValue; for (int iComp = 0; iComp < iComponentLenght[iSlot]; iComp++) { if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType != IndChartType.NoChart) { for (bar = Math.Max(firstBar, Data.Strategy.Slot[iSlot].Component[iComp].FirstBar); bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; if (dValue > dMaxValue[ind]) { dMaxValue[ind] = dValue; } if (dValue < dMinValue[ind]) { dMinValue[ind] = dValue; } } } } dMaxValue[ind] = Math.Max(dMaxValue[ind], Data.Strategy.Slot[iSlot].MaxValue); dMinValue[ind] = Math.Min(dMinValue[ind], Data.Strategy.Slot[iSlot].MinValue); foreach (double dSpecVal in Data.Strategy.Slot[iSlot].SpecValue) { if (dSpecVal == 0) { dMaxValue[ind] = Math.Max(dMaxValue[ind], 0); dMinValue[ind] = Math.Min(dMinValue[ind], 0); } } dScale[ind] = (yIndBottom[ind] - yIndTop[ind] - 2) / (Math.Max(dMaxValue[ind] - dMinValue[ind], 0.0001f)); // Indicator chart for (int iComp = 0; iComp < Data.Strategy.Slot[iSlot].Component.Length; iComp++) { chartType[iSlot][iComp] = Data.Strategy.Slot[iSlot].Component[iComp].ChartType; if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Line) { // Line chartBrush[iSlot][iComp] = new SolidBrush(Data.Strategy.Slot[iSlot].Component[iComp].ChartColor); chartLine[iSlot][iComp] = new Point[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yIndBottom[ind] - 1 - (dValue - dMinValue[ind]) * dScale[ind]); chartLine[iSlot][iComp][bar - firstBar] = new Point(ix, iy); } } else if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Histogram) { // Histogram chartValue[iSlot][iComp] = new double[lastBar - firstBar + 1]; chartPen[iSlot][iComp] = new Pen[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; chartValue[iSlot][iComp][bar - firstBar] = dValue; if (dValue > Data.Strategy.Slot[iSlot].Component[iComp].Value[bar - 1]) { chartPen[iSlot][iComp][bar - firstBar] = penGreen; } else { chartPen[iSlot][iComp][bar - firstBar] = penRed; } } } } } }
/// <summary> /// Prepare the parameters /// </summary> private void SetUpPaintData() { // Panel caption _captionText = Language.T("Indicator Chart"); _captionFont = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_captionFont.Height, 18); _captionWidth = ClientSize.Width; _captionBrush = new SolidBrush(LayoutColors.ColorCaptionText); _captionRectangle = new RectangleF(0, 0, _captionWidth, _captionHeight); _captionStringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; if (!Data.IsData || !Data.IsResult || Data.Bars <= StatsBuffer.FirstBar) return; _xLeft = Space; _xRight = ClientSize.Width - Space; _yTop = (int) _captionHeight + Space; _yBottom = ClientSize.Height - _scrollBar.Height - Space; _yPriceBottom = _yBottom; _separateIndicatorsCount = 0; _separateIndicatorsChartHeight = 0; _indicatorSlots = new int[Configs.MaxEntryFilters + Configs.MaxExitFilters + 2]; _penFore = new Pen(LayoutColors.ColorChartFore); _penVolume = new Pen(LayoutColors.ColorVolume); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); for (int slot = StatsBuffer.Strategy.Slots - 1; slot >= 0; slot--) if (StatsBuffer.Strategy.Slot[slot].SeparatedChart) _indicatorSlots[_separateIndicatorsCount++] = slot; if (_separateIndicatorsCount > 0) { _separateIndicatorsChartHeight = (_yBottom - _yTop)/(2 + _separateIndicatorsCount); _yPriceBottom = _yBottom - _separateIndicatorsCount*_separateIndicatorsChartHeight; } _maxPrice = double.MinValue; _minPrice = double.MaxValue; _maxVolume = int.MinValue; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { if (Data.High[bar] > _maxPrice) _maxPrice = Data.High[bar]; if (Data.Low[bar] < _minPrice) _minPrice = Data.Low[bar]; if (Data.Volume[bar] > _maxVolume) _maxVolume = Data.Volume[bar]; } _minPrice = Math.Round(_minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point*10; _maxPrice = Math.Round(_maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point*10; _scaleY = (_yPriceBottom - _yTop)/(_maxPrice - _minPrice); _scaleYVol = _maxVolume > 0 ? ((_yPriceBottom - _yTop)/8d)/_maxVolume : 0d; // Volume, Lots and Price _x = new int[_chartBars]; _yOpen = new int[_chartBars]; _yHigh = new int[_chartBars]; _yLow = new int[_chartBars]; _yClose = new int[_chartBars]; _yVolume = new int[_chartBars]; _rectPosition = new Rectangle[_chartBars]; _brushPosition = new Brush[_chartBars]; int index = 0; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { _x[index] = (bar - _chartFirstBar)*_chartBarWidth + _xLeft; _yOpen[index] = (int) (_yPriceBottom - (Data.Open[bar] - _minPrice)*_scaleY); _yHigh[index] = (int) (_yPriceBottom - (Data.High[bar] - _minPrice)*_scaleY); _yLow[index] = (int) (_yPriceBottom - (Data.Low[bar] - _minPrice)*_scaleY); _yClose[index] = (int) (_yPriceBottom - (Data.Close[bar] - _minPrice)*_scaleY); _yVolume[index] = (int) (_yPriceBottom - Data.Volume[bar]*_scaleYVol); // Draw position lots if (StatsBuffer.IsPos(bar)) { var posHight = (int) (Math.Max(StatsBuffer.SummaryLots(bar)*2, 2)); int yPos = _yPriceBottom - posHight; switch (StatsBuffer.SummaryDir(bar)) { case PosDirection.Long: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); break; case PosDirection.Short: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); break; case PosDirection.Closed: _rectPosition[index] = new Rectangle(_x[index], yPos - 2, 1, 2); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); break; } } else { // There is no position _rectPosition[index] = Rectangle.Empty; _brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart int slots = StatsBuffer.Strategy.Slots; _isSeparatedChart = new bool[slots]; _componentLenght = new int[slots]; _chartType = new IndChartType[slots][]; _chartLine = new Point[slots][][]; _chartDot = new Rectangle[slots][][]; _chartLevel = new Rectangle[slots][][]; _chartValue = new double[slots][][]; _chartPen = new Pen[slots][][]; _chartBrush = new Brush[slots][]; for (int slot = 0; slot < slots; slot++) { _isSeparatedChart[slot] = StatsBuffer.Strategy.Slot[slot].SeparatedChart; int count = StatsBuffer.Strategy.Slot[slot].Component.Length; _componentLenght[slot] = count; _chartType[slot] = new IndChartType[count]; _chartLine[slot] = new Point[count][]; _chartDot[slot] = new Rectangle[count][]; _chartLevel[slot] = new Rectangle[count][]; _chartValue[slot] = new double[count][]; _chartPen[slot] = new Pen[count][]; _chartBrush[slot] = new Brush[count]; } for (int slot = 0; slot < slots; slot++) { if (_isSeparatedChart[slot]) continue; for (int comp = 0; comp < _componentLenght[slot]; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType) { case IndChartType.Line: case IndChartType.CloudUp: case IndChartType.CloudDown: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar)*_chartBarWidth + _xLeft; var y = (int) (_yPriceBottom - (value - _minPrice)*_scaleY); if (Math.Abs(value - 0) < 0.0001) _chartLine[slot][comp][bar - _chartFirstBar] = _chartLine[slot][comp][Math.Max(bar - _chartFirstBar - 1, 0)]; else _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } break; case IndChartType.Dot: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartDot[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar)*_chartBarWidth + _xLeft; var y = (int) (_yPriceBottom - (value - _minPrice)*_scaleY); _chartDot[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, 1, 1); } break; case IndChartType.Level: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLevel[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar)*_chartBarWidth + _xLeft; var y = (int) (_yPriceBottom - (value - _minPrice)*_scaleY); _chartLevel[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, _chartBarWidth, 1); } break; } } } // Separate indicators _yIndTop = new int[_separateIndicatorsCount]; _yIndBottom = new int[_separateIndicatorsCount]; _maxValues = new double[_separateIndicatorsCount]; _minValues = new double[_separateIndicatorsCount]; _scales = new double[_separateIndicatorsCount]; for (int ind = 0; ind < _separateIndicatorsCount; ind++) { _yIndTop[ind] = _yBottom - (ind + 1)*_separateIndicatorsChartHeight + 1; _yIndBottom[ind] = _yBottom - ind*_separateIndicatorsChartHeight - 1; _maxValues[ind] = double.MinValue; _minValues[ind] = double.MaxValue; int slot = _indicatorSlots[ind]; for (int comp = 0; comp < _componentLenght[slot]; comp++) if (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType != IndChartType.NoChart) for ( int bar = Math.Max(_chartFirstBar, StatsBuffer.Strategy.Slot[slot].Component[comp].FirstBar); bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; if (value > _maxValues[ind]) _maxValues[ind] = value; if (value < _minValues[ind]) _minValues[ind] = value; } _maxValues[ind] = Math.Max(_maxValues[ind], StatsBuffer.Strategy.Slot[slot].MaxValue); _minValues[ind] = Math.Min(_minValues[ind], StatsBuffer.Strategy.Slot[slot].MinValue); foreach (double specialValue in StatsBuffer.Strategy.Slot[slot].SpecValue) if (Math.Abs(specialValue - 0) < 0.0001) { _maxValues[ind] = Math.Max(_maxValues[ind], 0); _minValues[ind] = Math.Min(_minValues[ind], 0); } _scales[ind] = (_yIndBottom[ind] - _yIndTop[ind] - 2)/ (Math.Max(_maxValues[ind] - _minValues[ind], 0.0001f)); // Indicator chart for (int comp = 0; comp < StatsBuffer.Strategy.Slot[slot].Component.Length; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (_chartType[slot][comp]) { case IndChartType.Line: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar)*_chartBarWidth + _xLeft; var y = (int) (_yIndBottom[ind] - 1 - (value - _minValues[ind])*_scales[ind]); _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } break; case IndChartType.Histogram: _chartValue[slot][comp] = new double[_chartLastBar - _chartFirstBar + 1]; _chartPen[slot][comp] = new Pen[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; _chartValue[slot][comp][bar - _chartFirstBar] = value; if (value > StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar - 1]) _chartPen[slot][comp][bar - _chartFirstBar] = _penGreen; else _chartPen[slot][comp][bar - _chartFirstBar] = _penRed; } break; } } } }
/// <summary> /// Prepare the parameters /// </summary> public void SetUpChart() { // Panel caption stringCaptionText = Language.T("Indicator Chart"); fontCaptionText = new Font(Font.FontFamily, 9); captionHeight = Math.Max(fontCaptionText.Height, 18); captionWidth = this.ClientSize.Width; brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); rectfCaption = new RectangleF(0, 0, captionWidth, captionHeight); stringFormatCaption = new StringFormat(); stringFormatCaption.Alignment |= StringAlignment.Center; stringFormatCaption.LineAlignment |= StringAlignment.Center; stringFormatCaption.Trimming |= StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags |= StringFormatFlags.NoWrap; if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) return; clSzWidth = this.ClientSize.Width; clSzHeight = this.ClientSize.Height; xLeft = space; xRight = clSzWidth - space; yTop = (int)captionHeight + space; yBottom = clSzHeight - scrollBar.Height - space; yPrcBottom = yBottom; // Price chart y inds = 0; // Count of separated indicators indHeight = 0; // Height of Ind charts aiIndSlot = new int[12]; penFore = new Pen(LayoutColors.ColorChartFore); penVolume = new Pen(LayoutColors.ColorVolume); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); for (int slot = Data.Strategy.Slots - 1; slot >= 0; slot--) if (Data.Strategy.Slot[slot].SeparatedChart) aiIndSlot[inds++] = slot; if (inds > 0) { indHeight = (yBottom - yTop) / (2 + inds); yPrcBottom = yBottom - inds * indHeight; } maxPrice = double.MinValue; minPrice = double.MaxValue; maxVolume = int.MinValue; for (int bar = firstBar; bar <= lastBar; bar++) { if (Data.High[bar] > maxPrice ) maxPrice = Data.High[bar]; if (Data.Low[bar] < minPrice ) minPrice = Data.Low[bar]; if (Data.Volume[bar] > maxVolume) maxVolume = Data.Volume[bar]; } minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point * 10; maxPrice = Math.Round(maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point * 10; scaleY = (yPrcBottom - yTop) / (maxPrice - minPrice); scaleYVol = maxVolume > 0 ? ((yPrcBottom - yTop) / 8d) / maxVolume : 0d; // Volume, Lots and Price x = new int[chartBars]; yOpen = new int[chartBars]; yHigh = new int[chartBars]; yLow = new int[chartBars]; yClose = new int[chartBars]; yVolume = new int[chartBars]; rectPosition = new Rectangle[chartBars]; brushPosition = new Brush[chartBars]; int index = 0; for (int bar = firstBar; bar <= lastBar; bar++) { x[index] = (bar - firstBar) * barPixels + xLeft; yOpen[index] = (int)(yPrcBottom - (Data.Open[bar] - minPrice) * scaleY); yHigh[index] = (int)(yPrcBottom - (Data.High[bar] - minPrice) * scaleY); yLow[index] = (int)(yPrcBottom - (Data.Low[bar] - minPrice) * scaleY); yClose[index] = (int)(yPrcBottom - (Data.Close[bar] - minPrice) * scaleY); yVolume[index] = (int)(yPrcBottom - Data.Volume[bar] * scaleYVol); // Draw position lots if (Backtester.IsPos(bar)) { int iPosHight = (int)(Math.Max(Backtester.SummaryLots(bar) * 2, 2)); int iPosY = yPrcBottom - iPosHight; if (Backtester.SummaryDir(bar) == PosDirection.Long) { // Long rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); } else if (Backtester.SummaryDir(bar) == PosDirection.Short) { // Short rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); } else { // Close position rectPosition[index] = new Rectangle(x[index], iPosY - 2, 1, 2); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); } } else { // There is no position rectPosition[index] = Rectangle.Empty; brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart slots = Data.Strategy.Slots; bIsSeparatedChart = new bool[slots]; iComponentLenght = new int[slots]; chartType = new IndChartType[slots][]; chartLine = new Point[slots][][]; chartDot = new Rectangle[slots][][]; chartLevel = new Rectangle[slots][][]; chartValue = new double[slots][][]; chartPen = new Pen[slots][][]; chartBrush = new Brush[slots][]; for (int iSlot = 0; iSlot < slots; iSlot++) { bIsSeparatedChart[iSlot] = Data.Strategy.Slot[iSlot].SeparatedChart; int iLenght = Data.Strategy.Slot[iSlot].Component.Length; iComponentLenght[iSlot] = iLenght; chartType[iSlot] = new IndChartType[iLenght]; chartLine[iSlot] = new Point[iLenght][]; chartDot[iSlot] = new Rectangle[iLenght][]; chartLevel[iSlot] = new Rectangle[iLenght][]; chartValue[iSlot] = new double[iLenght][]; chartPen[iSlot] = new Pen[iLenght][]; chartBrush[iSlot] = new Brush[iLenght]; } for (int slot = 0; slot < slots; slot++) { if (bIsSeparatedChart[slot]) continue; for (int comp = 0; comp < iComponentLenght[slot]; comp++) { chartType[slot][comp] = Data.Strategy.Slot[slot].Component[comp].ChartType; if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Line || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudUp || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudDown ) { // Line chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLine[slot][comp] = new Point[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); if(dValue == 0) chartLine[slot][comp][bar - firstBar] = chartLine[slot][comp][Math.Max(bar - firstBar - 1, 0)]; else chartLine[slot][comp][bar - firstBar] = new Point(ix, iy); } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Dot) { // Dots chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartDot[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartDot[slot][comp][bar-firstBar] = new Rectangle(ix, iy, 1, 1); } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Level) { // Level chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLevel[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartLevel[slot][comp][bar - firstBar] = new Rectangle(ix, iy, barPixels, 1); } } } } // Separate indicators yIndTop = new int[inds]; yIndBottom = new int[inds]; dMaxValue = new double[inds]; dMinValue = new double[inds]; dScale = new double[inds]; for (int ind = 0; ind < inds; ind++) { yIndTop[ind] = yBottom - (ind + 1) * indHeight + 1; yIndBottom[ind] = yBottom - ind * indHeight - 1; dMaxValue[ind] = double.MinValue; dMinValue[ind] = double.MaxValue; int iSlot = aiIndSlot[ind]; double dValue; for (int iComp = 0; iComp < iComponentLenght[iSlot]; iComp++) if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType != IndChartType.NoChart) for (bar = Math.Max(firstBar, Data.Strategy.Slot[iSlot].Component[iComp].FirstBar); bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; if (dValue > dMaxValue[ind]) dMaxValue[ind] = dValue; if (dValue < dMinValue[ind]) dMinValue[ind] = dValue; } dMaxValue[ind] = Math.Max(dMaxValue[ind], Data.Strategy.Slot[iSlot].MaxValue); dMinValue[ind] = Math.Min(dMinValue[ind], Data.Strategy.Slot[iSlot].MinValue); foreach (double dSpecVal in Data.Strategy.Slot[iSlot].SpecValue) if (dSpecVal == 0) { dMaxValue[ind] = Math.Max(dMaxValue[ind], 0); dMinValue[ind] = Math.Min(dMinValue[ind], 0); } dScale[ind] = (yIndBottom[ind] - yIndTop[ind] - 2) / (Math.Max(dMaxValue[ind] - dMinValue[ind], 0.0001f)); // Indicator chart for (int iComp = 0; iComp < Data.Strategy.Slot[iSlot].Component.Length; iComp++) { chartType[iSlot][iComp] = Data.Strategy.Slot[iSlot].Component[iComp].ChartType; if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Line) { // Line chartBrush[iSlot][iComp] = new SolidBrush(Data.Strategy.Slot[iSlot].Component[iComp].ChartColor); chartLine[iSlot][iComp] = new Point[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yIndBottom[ind] - 1 - (dValue - dMinValue[ind]) * dScale[ind]); chartLine[iSlot][iComp][bar - firstBar] = new Point(ix, iy); } } else if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Histogram) { // Histogram chartValue[iSlot][iComp] = new double[lastBar - firstBar + 1]; chartPen[iSlot][iComp] = new Pen[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; chartValue[iSlot][iComp][bar - firstBar] = dValue; if (dValue > Data.Strategy.Slot[iSlot].Component[iComp].Value[bar - 1]) chartPen[iSlot][iComp][bar - firstBar] = penGreen; else chartPen[iSlot][iComp][bar - firstBar] = penRed; } } } } }
/// <summary> /// Prepare the parameters /// </summary> private void SetUpPaintData() { // Panel caption _captionText = Language.T("Indicator Chart"); _captionFont = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_captionFont.Height, 18); _captionWidth = ClientSize.Width; _captionBrush = new SolidBrush(LayoutColors.ColorCaptionText); _captionRectangle = new RectangleF(0, 0, _captionWidth, _captionHeight); _captionStringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; if (!Data.IsData || !Data.IsResult || Data.Bars <= StatsBuffer.FirstBar) { return; } _xLeft = Space; _xRight = ClientSize.Width - Space; _yTop = (int)_captionHeight + Space; _yBottom = ClientSize.Height - _scrollBar.Height - Space; _yPriceBottom = _yBottom; _separateIndicatorsCount = 0; _separateIndicatorsChartHeight = 0; _indicatorSlots = new int[Configs.MaxEntryFilters + Configs.MaxExitFilters + 2]; _penFore = new Pen(LayoutColors.ColorChartFore); _penVolume = new Pen(LayoutColors.ColorVolume); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); for (int slot = StatsBuffer.Strategy.Slots - 1; slot >= 0; slot--) { if (StatsBuffer.Strategy.Slot[slot].SeparatedChart) { _indicatorSlots[_separateIndicatorsCount++] = slot; } } if (_separateIndicatorsCount > 0) { _separateIndicatorsChartHeight = (_yBottom - _yTop) / (2 + _separateIndicatorsCount); _yPriceBottom = _yBottom - _separateIndicatorsCount * _separateIndicatorsChartHeight; } _maxPrice = double.MinValue; _minPrice = double.MaxValue; _maxVolume = int.MinValue; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { if (Data.High[bar] > _maxPrice) { _maxPrice = Data.High[bar]; } if (Data.Low[bar] < _minPrice) { _minPrice = Data.Low[bar]; } if (Data.Volume[bar] > _maxVolume) { _maxVolume = Data.Volume[bar]; } } _minPrice = Math.Round(_minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point * 10; _maxPrice = Math.Round(_maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point * 10; _scaleY = (_yPriceBottom - _yTop) / (_maxPrice - _minPrice); _scaleYVol = _maxVolume > 0 ? ((_yPriceBottom - _yTop) / 8d) / _maxVolume : 0d; // Volume, Lots and Price _x = new int[_chartBars]; _yOpen = new int[_chartBars]; _yHigh = new int[_chartBars]; _yLow = new int[_chartBars]; _yClose = new int[_chartBars]; _yVolume = new int[_chartBars]; _rectPosition = new Rectangle[_chartBars]; _brushPosition = new Brush[_chartBars]; int index = 0; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { _x[index] = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; _yOpen[index] = (int)(_yPriceBottom - (Data.Open[bar] - _minPrice) * _scaleY); _yHigh[index] = (int)(_yPriceBottom - (Data.High[bar] - _minPrice) * _scaleY); _yLow[index] = (int)(_yPriceBottom - (Data.Low[bar] - _minPrice) * _scaleY); _yClose[index] = (int)(_yPriceBottom - (Data.Close[bar] - _minPrice) * _scaleY); _yVolume[index] = (int)(_yPriceBottom - Data.Volume[bar] * _scaleYVol); // Draw position lots if (StatsBuffer.IsPos(bar)) { var posHight = (int)(Math.Max(StatsBuffer.SummaryLots(bar) * 2, 2)); int yPos = _yPriceBottom - posHight; switch (StatsBuffer.SummaryDir(bar)) { case PosDirection.Long: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); break; case PosDirection.Short: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); break; case PosDirection.Closed: _rectPosition[index] = new Rectangle(_x[index], yPos - 2, 1, 2); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); break; } } else { // There is no position _rectPosition[index] = Rectangle.Empty; _brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart int slots = StatsBuffer.Strategy.Slots; _isSeparatedChart = new bool[slots]; _componentLenght = new int[slots]; _chartType = new IndChartType[slots][]; _chartLine = new Point[slots][][]; _chartDot = new Rectangle[slots][][]; _chartLevel = new Rectangle[slots][][]; _chartValue = new double[slots][][]; _chartPen = new Pen[slots][][]; _chartBrush = new Brush[slots][]; for (int slot = 0; slot < slots; slot++) { _isSeparatedChart[slot] = StatsBuffer.Strategy.Slot[slot].SeparatedChart; int count = StatsBuffer.Strategy.Slot[slot].Component.Length; _componentLenght[slot] = count; _chartType[slot] = new IndChartType[count]; _chartLine[slot] = new Point[count][]; _chartDot[slot] = new Rectangle[count][]; _chartLevel[slot] = new Rectangle[count][]; _chartValue[slot] = new double[count][]; _chartPen[slot] = new Pen[count][]; _chartBrush[slot] = new Brush[count]; } for (int slot = 0; slot < slots; slot++) { if (_isSeparatedChart[slot]) { continue; } for (int comp = 0; comp < _componentLenght[slot]; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType) { case IndChartType.Line: case IndChartType.CloudUp: case IndChartType.CloudDown: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); if (Math.Abs(value - 0) < 0.0001) { _chartLine[slot][comp][bar - _chartFirstBar] = _chartLine[slot][comp][Math.Max(bar - _chartFirstBar - 1, 0)]; } else { _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } } break; case IndChartType.Dot: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartDot[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); _chartDot[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, 1, 1); } break; case IndChartType.Level: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLevel[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); _chartLevel[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, _chartBarWidth, 1); } break; } } } // Separate indicators _yIndTop = new int[_separateIndicatorsCount]; _yIndBottom = new int[_separateIndicatorsCount]; _maxValues = new double[_separateIndicatorsCount]; _minValues = new double[_separateIndicatorsCount]; _scales = new double[_separateIndicatorsCount]; for (int ind = 0; ind < _separateIndicatorsCount; ind++) { _yIndTop[ind] = _yBottom - (ind + 1) * _separateIndicatorsChartHeight + 1; _yIndBottom[ind] = _yBottom - ind * _separateIndicatorsChartHeight - 1; _maxValues[ind] = double.MinValue; _minValues[ind] = double.MaxValue; int slot = _indicatorSlots[ind]; for (int comp = 0; comp < _componentLenght[slot]; comp++) { if (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType != IndChartType.NoChart) { for ( int bar = Math.Max(_chartFirstBar, StatsBuffer.Strategy.Slot[slot].Component[comp].FirstBar); bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; if (value > _maxValues[ind]) { _maxValues[ind] = value; } if (value < _minValues[ind]) { _minValues[ind] = value; } } } } _maxValues[ind] = Math.Max(_maxValues[ind], StatsBuffer.Strategy.Slot[slot].MaxValue); _minValues[ind] = Math.Min(_minValues[ind], StatsBuffer.Strategy.Slot[slot].MinValue); foreach (double specialValue in StatsBuffer.Strategy.Slot[slot].SpecValue) { if (Math.Abs(specialValue - 0) < 0.0001) { _maxValues[ind] = Math.Max(_maxValues[ind], 0); _minValues[ind] = Math.Min(_minValues[ind], 0); } } _scales[ind] = (_yIndBottom[ind] - _yIndTop[ind] - 2) / (Math.Max(_maxValues[ind] - _minValues[ind], 0.0001f)); // Indicator chart for (int comp = 0; comp < StatsBuffer.Strategy.Slot[slot].Component.Length; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (_chartType[slot][comp]) { case IndChartType.Line: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yIndBottom[ind] - 1 - (value - _minValues[ind]) * _scales[ind]); _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } break; case IndChartType.Histogram: _chartValue[slot][comp] = new double[_chartLastBar - _chartFirstBar + 1]; _chartPen[slot][comp] = new Pen[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; _chartValue[slot][comp][bar - _chartFirstBar] = value; if (value > StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar - 1]) { _chartPen[slot][comp][bar - _chartFirstBar] = _penGreen; } else { _chartPen[slot][comp][bar - _chartFirstBar] = _penRed; } } break; } } } }