/// <summary> /// Updates the journal data from StatsBuffer /// </summary> public void UpdateJournalData() { _journalData = new string[_shownBars, _columns]; _positionIcons = new Image[_shownBars]; for (int bar = _firstBar; bar < _firstBar + _shownBars; bar++) { int row = bar - _firstBar; int col = 0; bool isPos = StatsBuffer.IsPos(bar); bool inMoney = Configs.AccountInMoney; _journalData[row, col++] = (bar + 1).ToString(CultureInfo.InvariantCulture); _journalData[row, col++] = Data.Time[bar].ToString(Data.DF); _journalData[row, col++] = Data.Time[bar].ToString("HH:mm"); _journalData[row, col++] = Data.Open[bar].ToString(Data.FF); _journalData[row, col++] = Data.High[bar].ToString(Data.FF); _journalData[row, col++] = Data.Low[bar].ToString(Data.FF); _journalData[row, col++] = Data.Close[bar].ToString(Data.FF); _journalData[row, col++] = Data.Volume[bar].ToString(CultureInfo.InvariantCulture); _journalData[row, col++] = isPos ? Language.T(StatsBuffer.SummaryTrans(bar).ToString()) : ""; _journalData[row, col++] = isPos ? Language.T(StatsBuffer.SummaryDir(bar).ToString()) : ""; _journalData[row, col++] = isPos ? GetPositionAmmountString(bar) : ""; _journalData[row, col++] = isPos ? StatsBuffer.SummaryPrice(bar).ToString(Data.FF) : ""; _journalData[row, col++] = isPos ? GetPositionProfitString(bar) : ""; _journalData[row, col++] = isPos ? GetPositionFloatingPLString(bar) : ""; _journalData[row, col++] = inMoney ? StatsBuffer.MoneyBalance(bar).ToString("F2") : StatsBuffer.Balance(bar).ToString(CultureInfo.InvariantCulture); _journalData[row, col++] = inMoney ? StatsBuffer.MoneyEquity(bar).ToString("F2") : StatsBuffer.Equity(bar).ToString(CultureInfo.InvariantCulture); _journalData[row, col++] = StatsBuffer.SummaryRequiredMargin(bar).ToString("F2"); _journalData[row, col++] = StatsBuffer.SummaryFreeMargin(bar).ToString("F2"); _journalData[row, col] = Language.T(StatsBuffer.BackTestEvalToString(bar)); _positionIcons[row] = isPos ? Position.PositionIconImage(StatsBuffer.SummaryPositionIcon(bar)) : Resources.pos_square; } }
/// <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; } } } }