void PnlPrice_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(LayoutColors.ColorChartBack);
if (chartBars == 0) return;
// Searching the min and the max price and volume
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];
}
double pricePixel = (maxPrice - minPrice) / (YBottom - YTop);
if (isVolumeShown)
minPrice -= pricePixel * 30;
else if (isPositionLotsShown)
minPrice -= pricePixel * 10;
maxPrice += pricePixel * verticalScale;
minPrice -= pricePixel * verticalScale;
// Grid
int countLabels = (int)Math.Max((YBottom - YTop) / 30, 1);
double deltaPoint = (Data.InstrProperties.Digits == 5 || Data.InstrProperties.Digits == 3) ? Data.InstrProperties.Point * 100 : Data.InstrProperties.Point * 10;
double deltaLabel = Math.Max(Math.Round((maxPrice - minPrice) / countLabels, Data.InstrProperties.Point < 0.001 ? 3 : 1), deltaPoint);
minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - deltaPoint;
countLabels = (int)Math.Ceiling((maxPrice - minPrice) / deltaLabel);
maxPrice = minPrice + countLabels * deltaLabel;
YScale = (YBottom - YTop) / (countLabels * deltaLabel);
YVolScale = maxVolume > 0 ? 40.0f / maxVolume : 0f; // 40 - the highest volume line
// Price labels
for (double label = minPrice; label <= maxPrice + Data.InstrProperties.Point; label += deltaLabel)
{
int iLabelY = (int)Math.Round(YBottom - (label - minPrice) * YScale);
g.DrawString(label.ToString(Data.FF), Font, brushFore, XRight, iLabelY - Font.Height / 2 - 1);
if (isGridShown || label == minPrice)
g.DrawLine(penGrid, spcLeft, iLabelY, XRight, iLabelY);
else
g.DrawLine(penGrid, XRight - 5, iLabelY, XRight, iLabelY);
}
// Date labels
for (int iVertLineBar = lastBar; iVertLineBar > firstBar; iVertLineBar -= (int)Math.Round((szDate.Width + 10.0) / barPixels + 1))
{
int iXVertLine = (iVertLineBar - firstBar) * barPixels + spcLeft + barPixels / 2 - 1;
if (isGridShown)
g.DrawLine(penGrid, iXVertLine, YTop, iXVertLine, YBottom + 2);
string date = String.Format("{0} {1}", Data.Time[iVertLineBar].ToString(Data.DFS), Data.Time[iVertLineBar].ToString("HH:mm"));
g.DrawString(date, font, brushFore, iXVertLine - szDate.Width / 2, YBottomText);
}
// Cross
if (isCrossShown && mouseX > XLeft - 1 && mouseX < XRight + 1)
{
Point point;
Rectangle rec;
int crossBar;
crossBar = (mouseX - spcLeft) / barPixels;
crossBar = Math.Max(0, crossBar);
crossBar = Math.Min(chartBars - 1, crossBar);
crossBar += firstBar;
crossBar = Math.Min(Data.Bars - 1, crossBar);
// Vertical positions
point = new Point(mouseX - szDateL.Width / 2, YBottomText);
rec = new Rectangle(point, szDateL);
// Vertical line
if (isMouseInPriceChart && mouseY > YTop - 1 && mouseY < YBottom + 1)
{
g.DrawLine(penCross, mouseX, YTop, mouseX, mouseY - 10);
g.DrawLine(penCross, mouseX, mouseY + 10, mouseX, YBottomText);
}
else if (isMouseInPriceChart || isMouseInIndicatorChart)
{
g.DrawLine(penCross, mouseX, YTop, mouseX, YBottomText);
}
// Date Window
if (isMouseInPriceChart || isMouseInIndicatorChart)
{
g.FillRectangle(brushLabelBkgrd, rec);
g.DrawRectangle(penCross, rec);
string sDate = Data.Time[crossBar].ToString(Data.DF) + " " + Data.Time[crossBar].ToString("HH:mm");
g.DrawString(sDate, font, brushLabelFore, point);
}
if (isMouseInPriceChart && mouseY > YTop - 1 && mouseY < YBottom + 1)
{
//Horizontal positions
point = new Point(XRight, mouseY - szPrice.Height / 2);
rec = new Rectangle(point, szPrice);
// Horizontal line
g.DrawLine(penCross, XLeft, mouseY, mouseX - 10, mouseY);
g.DrawLine(penCross, mouseX + 10, mouseY, XRight, mouseY);
// Price Window
g.FillRectangle(brushLabelBkgrd, rec);
g.DrawRectangle(penCross, rec);
string sPrice = ((YBottom - mouseY) / YScale + minPrice).ToString(Data.FF);
g.DrawString(sPrice, font, brushLabelFore, point);
}
}
// Draws Volume, Lots and Bars
for (int bar = firstBar; bar <= lastBar; bar++)
{
int x = (bar - firstBar) * barPixels + spcLeft;
int yOpen = (int)Math.Round(YBottom - (Data.Open[bar] - minPrice) * YScale);
int yHigh = (int)Math.Round(YBottom - (Data.High[bar] - minPrice) * YScale);
int yLow = (int)Math.Round(YBottom - (Data.Low[bar] - minPrice) * YScale);
int yClose = (int)Math.Round(YBottom - (Data.Close[bar] - minPrice) * YScale);
int yVolume = (int)Math.Round(YBottom - Data.Volume[bar] * YVolScale);
// Draw the volume
if (isVolumeShown && yVolume != YBottom)
g.DrawLine(penVolume, x + barPixels / 2 - 1, yVolume, x + barPixels / 2 - 1, YBottom);
// Draw position lots
if (isPositionLotsShown && Backtester.IsPos(bar))
{
int iPosHight = (int)Math.Round(Math.Max(Backtester.SummaryLots(bar) * 2, 2));
int iPosY = YBottom - iPosHight + 1;
if (Backtester.SummaryDir(bar) == PosDirection.Long)
{ // Long
Rectangle rect = new Rectangle(x - 1, iPosY, barPixels + 1, iPosHight);
LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorLongTrade1, colorLongTrade2, 0f);
rect = new Rectangle(x, iPosY, barPixels - 1, iPosHight);
g.FillRectangle(lgBrush, rect);
}
else if (Backtester.SummaryDir(bar) == PosDirection.Short)
{ // Short
Rectangle rect = new Rectangle(x - 1, iPosY, barPixels + 1, iPosHight);
LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorShortTrade1, colorShortTrade2, 0f);
rect = new Rectangle(x, iPosY, barPixels - 1, iPosHight);
g.FillRectangle(lgBrush, rect);
}
else
{ // Closed
Rectangle rect = new Rectangle(x - 1, 2, barPixels + 1, 2);
LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorClosedTrade1, colorClosedTrade2, 0f);
rect = new Rectangle(x, YBottom - 1, barPixels - 1, 2);
g.FillRectangle(lgBrush, rect);
}
}
// Draw the bar
if (isCandleChart)
{
if (barPixels < 25)
g.DrawLine(penBarBorder, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh);
else
g.DrawLine(penBarThick, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh);
if (barPixels == 2)
g.DrawLine(penBarBorder, x, yClose, x + 1, yClose);
else
{
if (yClose < yOpen)
{ // White bar
Rectangle rect = new Rectangle(x, yClose, barPixels - 2, yOpen - yClose);
LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorBarWhite1, colorBarWhite2, 5f);
g.FillRectangle(lgBrush, rect);
g.DrawRectangle(penBarBorder, x, yClose, barPixels - 2, yOpen - yClose);
}
else if (yClose > yOpen)
{ // Black bar
Rectangle rect = new Rectangle(x, yOpen, barPixels - 2, yClose - yOpen);
LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorBarBlack1, colorBarBlack2, 5f);
g.FillRectangle(lgBrush, rect);
g.DrawRectangle(penBarBorder, rect);
}
else
{ // Cross
if (barPixels < 25)
g.DrawLine(penBarBorder, x, yClose, x + barPixels - 2, yClose);
else
g.DrawLine(penBarThick, x, yClose, x + barPixels - 2, yClose);
}
}
}
else
{
if (barPixels == 2)
{
g.DrawLine(penBarBorder, x, yClose, x + 1, yClose);
g.DrawLine(penBarBorder, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh);
}
else if (barPixels <= 16)
{
g.DrawLine(penBarBorder, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh);
if (yClose != yOpen)
{
g.DrawLine(penBarBorder, x, yOpen, x + barPixels / 2 - 1, yOpen);
g.DrawLine(penBarBorder, x + barPixels / 2 - 1, yClose, x + barPixels - 2, yClose);
}
else
{
g.DrawLine(penBarBorder, x, yClose, x + barPixels - 2, yClose);
}
}
else
{
g.DrawLine(penBarThick, x + barPixels / 2 - 1, yLow + 2, x + barPixels / 2 - 1, yHigh - 1);
if (yClose != yOpen)
{
g.DrawLine(penBarThick, x + 1, yOpen, x + barPixels / 2 - 1, yOpen);
g.DrawLine(penBarThick, x + barPixels / 2, yClose, x + barPixels - 2, yClose);
}
else
{
g.DrawLine(penBarThick, x, yClose, x + barPixels - 2, yClose);
}
}
}
}
// Drawing the indicators in the chart
g.SetClip(new RectangleF(0, YTop, XRight, YBottom - YTop));
for (int slot = 0; slot < Data.Strategy.Slots && isIndicatorsShown; slot++)
{
if (Data.Strategy.Slot[slot].SeparatedChart || repeatedIndicator[slot]) continue;
int cloudUp = 0; // For Ichimoku and similar
int cloudDown = 0; // For Ichimoku and similar
bool isIndicatorValueAtClose = true;
int indicatorValueShift = 1;
foreach (ListParam listParam in Data.Strategy.Slot[slot].IndParam.ListParam)
if (listParam.Caption == "Base price" && listParam.Text == "Open")
{
isIndicatorValueAtClose = false;
indicatorValueShift = 0;
}
for (int comp = 0; comp < Data.Strategy.Slot[slot].Component.Length; comp++)
{
Pen pen = new Pen(Data.Strategy.Slot[slot].Component[comp].ChartColor);
Pen penTC = new Pen(Data.Strategy.Slot[slot].Component[comp].ChartColor);
penTC.DashStyle = DashStyle.Dash;
penTC.DashPattern = new float[] { 2, 1 };
if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Line)
{ // Line
if (isTrueChartsShown)
{ // True Charts
Point[] point = new Point[lastBar - firstBar + 1];
for (int bar = firstBar; bar <= lastBar; bar++)
{
double value = Data.Strategy.Slot[slot].Component[comp].Value[bar];
int x = spcLeft + (bar - firstBar) * barPixels + indicatorValueShift * (barPixels - 2);
int y = (int)Math.Round(YBottom - (value - minPrice) * YScale);
if (value == 0)
point[bar - firstBar] = point[Math.Max(bar - firstBar - 1, 0)];
else
point[bar - firstBar] = new Point(x, y);
}
for (int bar = firstBar; bar <= lastBar; bar++)
{ // All bars except the last one
int i = bar - firstBar;
// The indicator value point
g.DrawLine(pen, point[i].X - 1, point[i].Y, point[i].X + 1, point[i].Y);
g.DrawLine(pen, point[i].X, point[i].Y - 1, point[i].X, point[i].Y + 1);
if (bar == firstBar && isIndicatorValueAtClose)
{ // First bar
double value = Data.Strategy.Slot[slot].Component[comp].Value[bar - 1];
int x = spcLeft + (bar - firstBar) * barPixels;
int y = (int)Math.Round(YBottom - (value - minPrice) * YScale);
int deltaY = Math.Abs(y - point[i].Y);
if (barPixels > 3)
{ // Horizontal part
if (deltaY == 0)
g.DrawLine(pen, x + 1, y, x + barPixels - 5, y);
else if (deltaY < 3)
g.DrawLine(pen, x + 1, y, x + barPixels - 4, y);
else
g.DrawLine(pen, x + 1, y, x + barPixels - 2, y);
}
if (deltaY > 4)
{ // Vertical part
if (point[i].Y > y)
g.DrawLine(penTC, x + barPixels - 2, y + 2, x + barPixels - 2, point[i].Y - 2);
else
g.DrawLine(penTC, x + barPixels - 2, y - 2, x + barPixels - 2, point[i].Y + 2);
}
}
if (bar < lastBar)
{
int deltaY = Math.Abs(point[i + 1].Y - point[i].Y);
if (barPixels > 3)
{ // Horizontal part
if (deltaY == 0)
g.DrawLine(pen, point[i].X + 3, point[i].Y, point[i + 1].X - 3, point[i].Y);
else if (deltaY < 3)
g.DrawLine(pen, point[i].X + 3, point[i].Y, point[i + 1].X - 2, point[i].Y);
else
g.DrawLine(pen, point[i].X + 3, point[i].Y, point[i + 1].X, point[i].Y);
}
if (deltaY > 4)
{ // Vertical part
if (point[i + 1].Y > point[i].Y)
g.DrawLine(penTC, point[i + 1].X, point[i].Y + 2, point[i + 1].X, point[i + 1].Y - 2);
else
g.DrawLine(penTC, point[i + 1].X, point[i].Y - 2, point[i + 1].X, point[i + 1].Y + 2);
}
}
if (bar == lastBar && !isIndicatorValueAtClose && barPixels > 3)
{ // Last bar
g.DrawLine(pen, point[i].X + 3, point[i].Y, point[i].X + barPixels - 2, point[i].Y);
}
}
}
else
{ // Regular Charts
Point[] aPoint = new Point[lastBar - firstBar + 1];
for (int bar = firstBar; bar <= lastBar; bar++)
{
double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
int x = spcLeft + (bar - firstBar) * barPixels + barPixels / 2 - 1;
int y = (int)Math.Round(YBottom - (dValue - minPrice) * YScale);
if (dValue == 0)
aPoint[bar - firstBar] = aPoint[Math.Max(bar - firstBar - 1, 0)];
else
aPoint[bar - firstBar] = new Point(x, y);
}
g.DrawLines(pen, aPoint);
}
}
else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Dot)
{ // Dots
for (int bar = firstBar; bar <= lastBar; bar++)
{
double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
int x = (bar - firstBar) * barPixels + barPixels / 2 - 1 + spcLeft;
int y = (int)Math.Round(YBottom - (dValue - minPrice) * YScale);
if (barPixels == 2)
g.FillRectangle(pen.Brush, x, y, 1, 1);
else
{
g.DrawLine(pen, x - 1, y, x + 1, y);
g.DrawLine(pen, x, y - 1, x, y + 1);
}
}
}
else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Level)
{ // Level
for (int bar = firstBar; bar <= lastBar; bar++)
{
double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
int x = (bar - firstBar) * barPixels + spcLeft;
int y = (int)Math.Round(YBottom - (dValue - minPrice) * YScale);
g.DrawLine(pen, x, y, x + barPixels - 1, y);
}
}
else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudUp)
{
cloudUp = comp;
}
else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudDown)
{
cloudDown = comp;
}
}
// Clouds
if (cloudUp > 0 && cloudDown > 0)
{
PointF[] apntUp = new PointF[lastBar - firstBar + 1];
PointF[] apntDown = new PointF[lastBar - firstBar + 1];
for (int bar = firstBar; bar <= lastBar; bar++)
{
double dValueUp = Data.Strategy.Slot[slot].Component[cloudUp].Value[bar];
double dValueDown = Data.Strategy.Slot[slot].Component[cloudDown].Value[bar];
apntUp[bar - firstBar].X = (bar - firstBar) * barPixels + barPixels / 2 - 1 + spcLeft;
apntUp[bar - firstBar].Y = (int)Math.Round(YBottom - (dValueUp - minPrice) * YScale);
apntDown[bar - firstBar].X = (bar - firstBar) * barPixels + barPixels / 2 - 1 + spcLeft;
apntDown[bar - firstBar].Y = (int)Math.Round(YBottom - (dValueDown - minPrice) * YScale);
}
GraphicsPath pathUp = new GraphicsPath();
pathUp.AddLine(new PointF(apntUp[0].X, 0), apntUp[0]);
pathUp.AddLines(apntUp);
pathUp.AddLine(apntUp[lastBar - firstBar], new PointF(apntUp[lastBar - firstBar].X, 0));
pathUp.AddLine(new PointF(apntUp[lastBar - firstBar].X, 0), new PointF(apntUp[0].X, 0));
GraphicsPath pathDown = new GraphicsPath();
pathDown.AddLine(new PointF(apntDown[0].X, 0), apntDown[0]);
pathDown.AddLines(apntDown);
pathDown.AddLine(apntDown[lastBar - firstBar], new PointF(apntDown[lastBar - firstBar].X, 0));
pathDown.AddLine(new PointF(apntDown[lastBar - firstBar].X, 0), new PointF(apntDown[0].X, 0));
Color colorUp = Color.FromArgb(50, Data.Strategy.Slot[slot].Component[cloudUp].ChartColor);
Color colorDown = Color.FromArgb(50, Data.Strategy.Slot[slot].Component[cloudDown].ChartColor);
Pen penUp = new Pen(Data.Strategy.Slot[slot].Component[cloudUp].ChartColor);
Pen penDown = new Pen(Data.Strategy.Slot[slot].Component[cloudDown].ChartColor);
penUp.DashStyle = DashStyle.Dash;
penDown.DashStyle = DashStyle.Dash;
Brush brushUp = new SolidBrush(colorUp);
Brush brushDown = new SolidBrush(colorDown);
System.Drawing.Region regionUp = new Region(pathUp);
regionUp.Exclude(pathDown);
g.FillRegion(brushDown, regionUp);
System.Drawing.Region regionDown = new Region(pathDown);
regionDown.Exclude(pathUp);
g.FillRegion(brushUp, regionDown);
g.DrawLines(penUp, apntUp);
g.DrawLines(penDown, apntDown);
}
}
g.ResetClip();
// Draws position price, deals and Ambiguous note
for (int bar = firstBar; bar <= lastBar; bar++)
{
int x = (bar - firstBar) * barPixels + spcLeft;
int yHigh = (int)Math.Round(YBottom - (Data.High[bar] - minPrice) * YScale);
// Draw the corrected position price
for (int iPos = 0; iPos < Backtester.Positions(bar) && isPositionPriceShown; iPos++)
{
int yPrice = (int)Math.Round(YBottom - (Backtester.SummaryPrice(bar) - minPrice) * YScale);
if (yPrice >= YBottom || yPrice <= YTop) continue;
if (Backtester.SummaryDir(bar) == PosDirection.Long)
{ // Long
g.DrawLine(penTradeLong, x, yPrice, x + barPixels - 2, yPrice);
}
else if (Backtester.SummaryDir(bar) == PosDirection.Short)
{ // Short
g.DrawLine(penTradeShort, x, yPrice, x + barPixels - 2, yPrice);
}
else if (Backtester.SummaryDir(bar) == PosDirection.Closed)
{ // Closed
g.DrawLine(penTradeClose, x, yPrice, x + barPixels - 2, yPrice);
}
}
//// Draw Permanent SL and TP
//for (int iPos = 0; iPos < Backtester.Positions(bar) && isPositionPriceShown; iPos++)
//{
// int yAbsSL = (int)Math.Round(YBottom - (Backtester.SummaryAbsoluteSL(bar) - minPrice) * YScale);
// int yAbsTP = (int)Math.Round(YBottom - (Backtester.SummaryAbsoluteTP(bar) - minPrice) * YScale);
// if (yAbsTP < YBottom && yAbsTP > YTop)
// g.DrawLine(penTradeLong, x, yAbsTP, x + barPixels - 2, yAbsTP);
// if (yAbsSL < YBottom && yAbsSL > YTop)
// g.DrawLine(penTradeShort, x, yAbsSL, x + barPixels - 2, yAbsSL);
//}
// Draw the deals
for (int iPos = 0; iPos < Backtester.Positions(bar) && isOrdersShown; iPos++)
{
if (Backtester.PosTransaction(bar, iPos) == Transaction.Transfer) continue;
int yDeal = (int)Math.Round(YBottom - (Backtester.PosOrdPrice(bar, iPos) - minPrice) * YScale);
if (Backtester.PosDir(bar, iPos) == PosDirection.Long ||
Backtester.PosDir(bar, iPos) == PosDirection.Short)
{
if (Backtester.OrdFromNumb(Backtester.PosOrdNumb(bar, iPos)).OrdDir == OrderDirection.Buy)
{ // Buy
Pen pen = new Pen(brushTradeLong, 2);
if (barPixels < 8)
{
g.DrawLine(pen, x, yDeal, x + barPixels - 1, yDeal);
}
else if (barPixels == 8)
{
g.DrawLine(pen, x, yDeal, x + 4, yDeal);
pen.EndCap = LineCap.DiamondAnchor;
g.DrawLine(pen, x + 2, yDeal, x + 5, yDeal - 3);
}
else if (barPixels > 8)
{
int d = barPixels / 2 - 1;
int x1 = x + d;
int x2 = x + barPixels - 2;
g.DrawLine(pen, x, yDeal, x1, yDeal);
g.DrawLine(pen, x1, yDeal, x2, yDeal - d);
g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1);
g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2);
}
}
else
{ // Sell
Pen pen = new Pen(brushTradeShort, 2);
if (barPixels < 8)
{
g.DrawLine(pen, x, yDeal, x + barPixels - 1, yDeal);
}
else if (barPixels == 8)
{
g.DrawLine(pen, x, yDeal + 1, x + 4, yDeal + 1);
pen.EndCap = LineCap.DiamondAnchor;
g.DrawLine(pen, x + 2, yDeal, x + 5, yDeal + 3);
}
else if (barPixels > 8)
{
int d = barPixels / 2 - 1;
int x1 = x + d;
int x2 = x + barPixels - 2;
g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1);
g.DrawLine(pen, x1, yDeal, x2, yDeal + d);
g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d);
g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1);
}
}
}
else if (Backtester.PosDir(bar, iPos) == PosDirection.Closed)
{ // Close
Pen pen = new Pen(brushTradeClose, 2);
if (barPixels < 8)
{
g.DrawLine(pen, x, yDeal, x + barPixels - 1, yDeal);
}
else if (barPixels == 8)
{
g.DrawLine(pen, x, yDeal, x + 7, yDeal);
g.DrawLine(pen, x + 5, yDeal - 2, x + 5, yDeal + 2);
}
else if (barPixels > 8)
{
int d = barPixels / 2 - 1;
int x1 = x + d;
int x2 = x + barPixels - 3;
g.DrawLine(pen, x, yDeal, x1, yDeal);
g.DrawLine(pen, x1, yDeal + d / 2, x2, yDeal - d / 2);
g.DrawLine(pen, x1, yDeal - d / 2, x2, yDeal + d / 2);
}
}
}
// Ambiguous note
if (isAmbiguousBarsShown && Backtester.BackTestEval(bar) == "Ambiguous")
g.DrawString("!", Font, brushSignalRed, x + barPixels / 2 - 4, yHigh - 20);
}
// Chart title
g.DrawString(chartTitle, font, brushFore, spcLeft, 0);
return;
}