void PnlFloatingPL_Paint(object sender, PaintEventArgs e)
{
if (!isFloatingPLShown) return;
Panel pnl = (Panel)sender;
Graphics g = e.Graphics;
int topSpace = font.Height / 2 + 2;
int bottmSpace = font.Height / 2;
int maxValue = 10;
int minValue = -10;
int value;
g.Clear(LayoutColors.ColorChartBack);
if (chartBars == 0) return;
for (int bar = Math.Max(firstBar, Data.FirstBar); bar <= lastBar; bar++)
{
if (!Backtester.IsPos(bar)) continue;
value = Configs.AccountInMoney ? (int)Math.Round(Backtester.MoneyProfitLoss(bar) + Backtester.MoneyFloatingPL(bar)) :
Backtester.ProfitLoss(bar) + Backtester.FloatingPL(bar);
if (value > maxValue) maxValue = value;
if (value < minValue) minValue = value;
}
minValue = 10 * (int)Math.Floor(minValue / 10.0);
maxValue = 10 * (int)Math.Ceiling(maxValue / 10.0);
double scale = (pnl.ClientSize.Height - topSpace - bottmSpace) / ((double)Math.Max(maxValue - minValue, 1));
// Grid
int XGridRight = pnl.ClientSize.Width - spcRight + 2;
int label = 0;
int labelYZero = (int)Math.Round(pnl.ClientSize.Height - bottmSpace - (label - minValue) * scale);
if (label >= minValue && label <= maxValue)
{
g.DrawString(label.ToString(), Font, brushFore, XRight, labelYZero - Font.Height / 2 - 1);
g.DrawLine(penGridSolid, spcLeft, labelYZero, XGridRight, labelYZero);
}
label = minValue;
int labelYMin = (int)Math.Round(pnl.ClientSize.Height - bottmSpace - (label - minValue) * scale);
if (Math.Abs(labelYZero - labelYMin) >= Font.Height)
{
g.DrawString(label.ToString(), Font, brushFore, XRight, labelYMin - Font.Height / 2 - 1);
if (isGridShown)
g.DrawLine(penGrid, spcLeft, labelYMin, XGridRight, labelYMin);
else
g.DrawLine(penGrid, XGridRight - 5, labelYMin, XGridRight, labelYMin);
}
label = maxValue;
int labelYMax = (int)Math.Round(pnl.ClientSize.Height - bottmSpace - (label - minValue) * scale);
if (Math.Abs(labelYZero - labelYMax) >= Font.Height)
{
g.DrawString(label.ToString(), Font, brushFore, XRight, labelYMax - Font.Height / 2 - 1);
if (isGridShown)
g.DrawLine(penGrid, spcLeft, labelYMax, XGridRight, labelYMax);
else
g.DrawLine(penGrid, XGridRight - 5, labelYMax, XGridRight, labelYMax);
}
// Vertical line
if (isGridShown)
{
string date = Data.Time[firstBar].ToString("dd.MM") + " " + Data.Time[firstBar].ToString("HH:mm");
int isDataWidth = (int)g.MeasureString(date, Font).Width;
for (int vertLineBar = lastBar; vertLineBar > firstBar; vertLineBar -= (int)Math.Round((isDataWidth + 10.0) / barPixels + 1))
{
int XVertLine = (vertLineBar - firstBar) * barPixels + barPixels / 2 - 1 + spcLeft;
g.DrawLine(penGrid, XVertLine, topSpace, XVertLine, pnl.ClientSize.Height - bottmSpace);
}
}
// Chart
Rectangle rect;
LinearGradientBrush lgBrush;
int y0 = (int)Math.Round(pnl.ClientSize.Height - 5 + minValue * scale);
for (int bar = firstBar; bar <= lastBar; bar++)
{
if (!Backtester.IsPos(bar)) continue;
value = Configs.AccountInMoney ? (int)Math.Round(Backtester.MoneyProfitLoss(bar) + Backtester.MoneyFloatingPL(bar)) :
Backtester.ProfitLoss(bar) + Backtester.FloatingPL(bar);
int x = (bar - firstBar) * barPixels + spcLeft;
int y = (int)Math.Round(pnl.ClientSize.Height - 7 - (value - minValue) * scale);
if (y == y0) continue;
if (Backtester.SummaryDir(bar) == PosDirection.Long)
{
if (y > y0)
{
rect = new Rectangle(x - 1, y0, barPixels + 1, y - y0);
lgBrush = new LinearGradientBrush(rect, colorLongTrade1, colorLongTrade2, 0f);
rect = new Rectangle(x, y0, barPixels - 1, y - y0);
}
else if (y < y0)
{
rect = new Rectangle(x - 1, y, barPixels + 1, y0 - y);
lgBrush = new LinearGradientBrush(rect, colorLongTrade1, colorLongTrade2, 0f);
rect = new Rectangle(x, y, barPixels - 1, y0 - y);
}
else
continue;
g.FillRectangle(lgBrush, rect);
}
else if (Backtester.SummaryDir(bar) == PosDirection.Short)
{
if (y > y0)
{
rect = new Rectangle(x - 1, y0, barPixels + 1, y - y0);
lgBrush = new LinearGradientBrush(rect, colorShortTrade1, colorShortTrade2, 0f);
rect = new Rectangle(x, y0, barPixels - 1, y - y0);
}
else if (y < y0)
{
rect = new Rectangle(x - 1, y, barPixels + 1, y0 - y);
lgBrush = new LinearGradientBrush(rect, colorShortTrade1, colorShortTrade2, 0f);
rect = new Rectangle(x, y, barPixels - 1, y0 - y);
}
else
continue;
g.FillRectangle(lgBrush, rect);
}
else
{
if (y > y0)
{
rect = new Rectangle(x - 1, y0, barPixels + 1, y - y0);
lgBrush = new LinearGradientBrush(rect, colorClosedTrade1, colorClosedTrade2, 0f);
rect = new Rectangle(x, y0, barPixels - 1, y - y0);
}
else if (y < y0)
{
rect = new Rectangle(x - 1, y, barPixels + 1, y0 - y);
lgBrush = new LinearGradientBrush(rect, colorClosedTrade1, colorClosedTrade2, 0f);
rect = new Rectangle(x, y, barPixels - 1, y0 - y);
}
else
continue;
g.FillRectangle(lgBrush, rect);
}
}
// Vertical cross line
if (isCrossShown && mouseX > XLeft - 1 && mouseX < XRight + 1)
g.DrawLine(penCross, mouseX, 0, mouseX, pnl.ClientSize.Height);
// Chart title
string sTitle = Language.T("Floating P/L") + " [" + (Configs.AccountInMoney ? Configs.AccountCurrency + "]" : Language.T("pips") + "]");
Size szTitle = g.MeasureString(sTitle, Font).ToSize();
g.FillRectangle(brushBack, new Rectangle(spcLeft, 0, szTitle.Width, szTitle.Height));
g.DrawString(sTitle, Font, brushFore, spcLeft, 0);
return;
}