void DrawSpreadChart(Graphics g, Spread[] spreads)
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
DrawCaptial(g);
DrawSubCaptial(g);
DrawYLebal(g);
DrawYAxis(spreads, g);
DrawXLebal(g);
DrawXAxis(spreads, g);
DrawGrid(g);
DrawIndictor(spreads, g);
}
//15 properties can be set for Spread chart
int spread_width = 600;//1.Width of Spread Chart
int spread_hight = 400;//2.Hight of Spread Chart
#region Captial
string caption = "European GSM Week Spreads";//3.Caption of Spread Chart
string fontFamily = "Times New Roman";//4.Font Family of Spread Chart
int captionSize = 8;//5.Caption Size
int captionPxes = 8;
void DrawCaptial(Graphics g)
{
using (Font font = new Font(fontFamily , captionSize , FontStyle.Bold, GraphicsUnit.Point))
{
captionPxes =(int)Math.Ceiling ( font.GetHeight());
Rectangle rect = new Rectangle(0, 0, spread_width,captionPxes );
// Create a StringFormat object with the each line of text, and the block
// of text centered on the page.
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
// Draw the text and the surrounding rectangle.
g.DrawString(caption, font, Brushes.Black , rect, stringFormat);
//g.DrawRectangle(Pens.Black, rect);
}
}
string subCaption = "(<200bps)";//6.Sub-Caption of Spread Chart
int subCaptionSize = 6; //7.Sub-Caption size
int subCpatialPxes = 6;
void DrawSubCaptial(Graphics g)
{
using (Font font = new Font(fontFamily, subCaptionSize, FontStyle.Bold, GraphicsUnit.Point))
{
subCpatialPxes =(int)Math.Ceiling ( font.GetHeight());
Rectangle rect = new Rectangle(0, captionPxes , spread_width ,subCpatialPxes );
// Create a StringFormat object with the each line of text, and the block
// of text centered on the page.
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center ;
// Draw the text and the surrounding rectangle.
g.DrawString(subCaption , font, Brushes.Black, rect, stringFormat);
//g.DrawRectangle(Pens.Red, rect);
}
}
#endregion
#region Y Label
string ylabel = "Asset Class";//8.Label of Y Axis
int yLabelSize = 8;//9.Label font size
int yLabelPxes;
void DrawYLebal(Graphics g)
{
using (Font font = new Font(fontFamily, yLabelSize, FontStyle.Bold , GraphicsUnit.Point))
{
yLabelPxes=(int)Math .Ceiling (font.GetHeight ());
Rectangle rect = new Rectangle(0, captionPxes +subCpatialPxes,yLabelPxes , spread_hight-captionPxes -subCpatialPxes );
StringFormat stringFormat = new StringFormat();
stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
stringFormat.Alignment = StringAlignment.Center ;
stringFormat.LineAlignment = StringAlignment.Center;
g.ResetTransform();
g.DrawString(ylabel , font, Brushes.Black , rect , stringFormat);
//g.DrawRectangle(Pens.Black, rect);
}
}
#endregion
#region Y Axis
int yGradeSize = 6;//10.Font size of Y Axis Grade
double yGradeHight = 10;
int maxYGradePxes = 10;
int gradeLen = 2;//11.Grade Length for X/Y Axis
int endY;
int startY;
int startX;
int yCount;
void DrawYAxis( Spread[] spreads,Graphics g)
{
yCount = spreads.Length;
maxYGradePxes = (int)Math.Ceiling(spreads.Max(x => MeasueLegth(x.AssetClass, yGradeSize, FontStyle.Bold , g).Width));
startY = captionPxes + subCpatialPxes;
startX = yLabelPxes + maxYGradePxes + gradeLen;
endY = spread_hight - GetHightPxes(xLabelSize, FontStyle.Bold) - GetHightPxes(xGradeSize, FontStyle.Bold );
yGradeHight = (endY -startY )*1.0/spreads .Count() ;
g.DrawLine(Pens.Black,
new Point(startX , startY),
new Point(startX , endY));
using (Font font = new Font(fontFamily, yGradeSize , FontStyle.Bold , GraphicsUnit.Point))
{
for (int i = 0; i < spreads.Length; i++)
{
int y = (int)(startY + yGradeHight * i);
Rectangle rect = new Rectangle(yLabelPxes, y, maxYGradePxes, (int)yGradeHight);
// Create a StringFormat object with the each line of text, and the block
// of text centered on the page.
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Far;
stringFormat.LineAlignment = StringAlignment.Center;
// Draw the text and the surrounding rectangle.
g.DrawString(spreads[i].AssetClass, font, Brushes.Black, rect, stringFormat);
//g.DrawRectangle(Pens.Black, rect);
g.DrawLine(Pens.Black,
new Point(yLabelPxes + maxYGradePxes , y),
new Point(yLabelPxes + maxYGradePxes + gradeLen, y));
}
g.DrawLine(Pens.Black,
new Point(yLabelPxes + maxYGradePxes, endY ),
new Point(yLabelPxes + maxYGradePxes + gradeLen, endY ));
}
}
#endregion
#region X Label
string xLabel = "Spreads";//12.Label of X Axis
int xLabelSize = 8;//13.Size of X Axis Label
int xLabelHightPxes = 10;
void DrawXLebal(Graphics g)
{
using (Font font = new Font(fontFamily, xLabelSize , FontStyle.Bold, GraphicsUnit.Point))
{
xLabelHightPxes = (int)Math.Ceiling(font.GetHeight());
Rectangle rect = new Rectangle(yLabelPxes +maxYGradePxes +gradeLen ,
spread_hight -xLabelHightPxes , spread_width-yLabelPxes -maxYGradePxes -gradeLen , xLabelHightPxes );
// Create a StringFormat object with the each line of text, and the block
// of text centered on the page.
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
// Draw the text and the surrounding rectangle.
g.DrawString(xLabel , font, Brushes.Black, rect, stringFormat);
//g.DrawRectangle(Pens.Red, rect);
}
}
#endregion
#region X Axis
int xGradeSize = 6; //14.Size of X Grade
int xInternal = 10; //15.The step length of X Axis
double xgradwith;
int xcount;
int minX;
int maxX;
int endX;
void DrawXAxis(Spread[] spreads, Graphics g)
{
var xs = spreads.SelectMany(x => new double[] { x.StartValue, x.EndValue }).ToArray();
double _minX = xs.Min(), _maxX = xs.Max();
minX = ((int)Math.Floor ( _minX / xInternal)) * xInternal;
maxX = ((int)Math.Ceiling(_maxX / xInternal)) * xInternal;
int margRight = (int)Math.Ceiling(MeasueLegth(maxX.ToString(), xGradeSize, FontStyle.Bold , g).Width / 2);
endX = spread_width - margRight;
xcount = (maxX - minX) / xInternal+1;
xgradwith = (spread_width - margRight - startX)*1.0 / xcount;
g.DrawLine(Pens.Black,
new Point(startX , endY ),
new Point(spread_width -margRight , endY));
using (Font font = new Font(fontFamily, xGradeSize , FontStyle.Bold , GraphicsUnit.Point))
{
for (int i = 0; i <= xcount; i++)
{
string xg = (minX + i * xInternal).ToString();
var xgS = MeasueLegth(xg, xGradeSize, FontStyle.Regular, g) ;
double xv = startX + i * xgradwith;
Rectangle rect = new Rectangle((int)(xv-xgS.Width/2),
endY +gradeLen ,
(int) Math.Ceiling( xgS.Width) ,
(int) Math.Ceiling( xgS .Height));
// Create a StringFormat object with the each line of text, and the block
// of text centered on the page.
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center ;
stringFormat.LineAlignment = StringAlignment.Center;
// Draw the text and the surrounding rectangle.
g.DrawString(xg, font, Brushes.Black, rect, stringFormat);
//g.DrawRectangle(Pens.Black, rect);
g.DrawLine(Pens.Black,
new Point((int)xv , endY ),
new Point((int)xv , endY +gradeLen ));
}
}
}
#endregion
#region Grids
void DrawGrid(Graphics g)
{
int gridMarg =(int) Math.Floor( yGradeHight /3);
for (int r = 0; r <= yCount / 3; r++)
{
int y0 = (int)(startY + 3*r * yGradeHight +gridMarg );
if (r == 0)
y0 = startY ;
int y1 = (int)(startY + 3 * (r + 1) * yGradeHight - gridMarg);
if (y1 > endY)
y1 = endY;
for (int c = 1; c <= xcount; c++)
{
int x =(int)( startX + c * xgradwith);
g.DrawLine(Pens.LightGray , x, y0, x, y1);
}
}
}
#endregion
#region Indictor
int arrow_rect_half_hight = 2; //a halft of the hight of the rectangle of the arrow
int arrow_triangle_add_half_hight = 2;//a half of the triangle ofthe arrow more than arrow_rect_half_hight
int arrow_triagle_width = 8;//the width of the triangle ofthe arrow
void DrawIndictor(Spread[] spreads, Graphics g)
{
double unit = (endX - startX) / (maxX - minX);
for (int i = 0; i < spreads.Length; i++)
{
Spread s = spreads[i];
int y = (int)(startY + (i + 0.5) * yGradeHight);
int x0 = (int)(startX + (Math.Min(s.StartValue, s.EndValue) - minX) * unit);
int x1 = (int)(startX + (Math.Max(s.StartValue, s.EndValue) - minX) * unit);
Point[] ps;
if (x1 - x0 < arrow_triagle_width)
ps = new Point[] {
new Point(x0,y-arrow_rect_half_hight ),
new Point(x1,y-arrow_rect_half_hight ),
new Point(x1,y+arrow_rect_half_hight ),
new Point (x0,y+arrow_rect_half_hight ),
new Point(x0,y-arrow_rect_half_hight )};
else if (x1 - x0 == arrow_triagle_width)
{
ps = new Point[] {
new Point(x0,y-arrow_rect_half_hight-arrow_triangle_add_half_hight ),
new Point(x1,y ),
new Point (x0,y+arrow_rect_half_hight+arrow_triangle_add_half_hight ),
new Point(x0,y-arrow_rect_half_hight-arrow_triangle_add_half_hight )};
}
else if (s.EndValue > s.StartValue)
{
ps = new Point[] {
new Point(x0, y-arrow_rect_half_hight ),
new Point(x1-arrow_triagle_width , y-arrow_rect_half_hight),
new Point(x1-arrow_triagle_width , y-arrow_rect_half_hight-arrow_triangle_add_half_hight),
new Point(x1, y) ,
new Point(x1-arrow_triagle_width , y+arrow_rect_half_hight+arrow_triangle_add_half_hight),
new Point(x1-arrow_triagle_width , y+arrow_rect_half_hight),
new Point(x0, y+arrow_rect_half_hight ),
new Point(x0, y-arrow_rect_half_hight ),};
}
else
{
ps = new Point[] {
new Point(x1, y-arrow_rect_half_hight ),
new Point(x0+arrow_triagle_width , y-arrow_rect_half_hight),
new Point(x0+arrow_triagle_width , y-arrow_rect_half_hight-arrow_triangle_add_half_hight),
new Point(x0, y) ,
new Point(x0+arrow_triagle_width , y+arrow_rect_half_hight+arrow_triangle_add_half_hight),
new Point(x0+arrow_triagle_width , y+arrow_rect_half_hight),
new Point(x1, y+arrow_rect_half_hight ),
new Point(x1, y-arrow_rect_half_hight ),};
}
if (s.StartValue < s.EndValue)
g.FillPolygon(Brushes.Red, ps);
else
g.FillPolygon(Brushes.Green, ps);
}
}
#endregion
#region Helpers
int GetHightPxes(int size, FontStyle style)
{
using (Font font = new Font(fontFamily, size ,style, GraphicsUnit.Point))
{
return (int)Math.Ceiling(font.GetHeight());
}
}
SizeF MeasueLegth(string txt, int size, FontStyle style, Graphics g)
{
using (Font font = new Font(fontFamily, size ,style, GraphicsUnit.Point))
{
return g.MeasureString (txt ,font );
}
}
#endregion