Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / WPF

How to create stock charts using the Silverlight Toolkit

Rate me:
Please Sign up or sign in to vote.
4.70/5 (15 votes)
16 Feb 2009CPOL2 min read 141.6K   2.7K   65   23
An article on how to create a Candlestick stock chart using the Silverlight Toolkit.

Image 1

Introduction

The Silverlight Toolkit is a collection of Silverlight controls, components, and utilities made available outside the normal Silverlight release cycle. It adds new functionality quickly for designers and developers, and provides the community an efficient way to help shape product development by contributing ideas and bug reports. It includes full source code, Unit Tests, samples, and documentation for 12 new controls covering charting, styling, layout, and user input.

The Silverlight Toolkit gives us an incredibly powerful charting control for Silverlight! The one type of chart that is still relatively difficult to create using this toolkit is stock charts (OHLC or Candlestick).

A candlestick chart is a style of bar-chart used primarily to describe price movements of an equity over time.

It is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. It is most often used in technical analysis of equity and currency price patterns. They appear superficially similar to error bars, but are unrelated.

Luckily the Silverlight Toolkit is also very customizable. This article will show a method of extending the Silverlight Toolkit to allow for the creation of stock charts.

The Basics

ClassDiagram.jpg

Each chart can contain multiple series. The Silverlight Toolkit has some common series:

  • BarSeries
  • BubbleSeries
  • ColumnSeries
  • LineSeries
  • PieSeries
  • ScatterSeries

We will be creating our own CandlestickSeries by deriving from DataPointSingleSeriesWithAxes:

C#
public sealed partial class CandlestickSeries : DataPointSingleSeriesWithAxes 
{ 
    // ... 
}

DataPointSingleSeriesWithAxes is a dynamic series with axes, and only one legend item and style for all data points.

Each series contains multiple data points:

C#
public sealed partial classCandlestickDataPoint : DataPoint 
{
    // ... 
}

DataPoint represents a control that displays a data point.

Now that we have the basics (a chart has a series, and each series has data points), let's dig deeper to see how it works…

CandlestickDataPoint

Image 3

The CandlestickDataPoint will be responsible for rendering the candlestick. Each candlestick has a shadow and body. Here is the default control template for the CandlestickDataPoint:

XML
<ControlTemplate TargetType="charting:CandlestickDataPoint">
   <Border x:Name="Root" Opacity="0" 
      BorderBrush="{x:Null}" BorderThickness="0" 
      RenderTransformOrigin="0.5,0.5">
   <!-- Removed the VSM stuff for brevity -->
   <Grid>
      <Grid x:Name="PART_Shadow">
         <Rectangle Fill="Black" Width="1" />
      </Grid>
      <Grid x:Name="PART_Body" 
               Background="{TemplateBinding Background}" 
               Margin="0,5,0,5">
         <Rectangle Fill="{TemplateBinding Background}" />
         <Rectangle>
            <Rectangle.Fill>
               <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                  <GradientStop Color="#64686868" />
                  <GradientStop Color="#FF4D4C4C" Offset="0.996" />
               </LinearGradientBrush>
            </Rectangle.Fill>
         </Rectangle>
        <Rectangle RenderTransformOrigin="0.5,0.5" 
                Margin="19,19,17,17" Opacity="0.245">
           <Rectangle.Fill>
              <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                 <GradientStop Color="#FF919191" />
                 <GradientStop Color="#FFFFFFFF" Offset="1" />
              </LinearGradientBrush>
           </Rectangle.Fill>
           <Rectangle.RenderTransform>
              <TransformGroup>
                 <ScaleTransform />
                 <SkewTransform />
                 <RotateTransform />
                 <TranslateTransform X="0.5" Y="0.5" />
              </TransformGroup>
           </Rectangle.RenderTransform>
        </Rectangle>
        <Rectangle x:Name="MouseOverHighlight" Opacity="0" 
                 Fill="#FF9B1C1C" Stroke="#FF000000" />
        <Rectangle x:Name="SelectionHighlight" 
                 Opacity="0" Fill="#3EF0F0F0" />
     </Grid>
   </Grid>
   </Border>
</ControlTemplate>

Each CandlestickDataPoint also has the following DPs (these are needed for the calculation of the body size):

  • Open
  • Close
  • High
  • Low

The only “tricky” thing about the CandlestickDataPoint is how it sizes the body. CandlestickDataPoint has a method called UpdateBody() which will resize the body.

CandlestickSeries

To make the CandlestickSeries “work”, we need to override CreateDataPoint, PrepareDataPoint, and UpdateDataPoint.

C#
protected override DataPoint CreateDataPoint()
{
   return new CandlestickDataPoint();
}

CreateDataPoint adds an object to the series host by creating a corresponding data point for it.

C#
protected override void PrepareDataPoint(DataPoint dataPoint, object dataContext)
{
   base.PrepareDataPoint(dataPoint, dataContext);
   CandlestickDataPoint candlestickDataPoint = (CandlestickDataPoint)dataPoint;
   candlestickDataPoint.SetBinding(CandlestickDataPoint.OpenProperty, OpenValueBinding);
   candlestickDataPoint.SetBinding(CandlestickDataPoint.CloseProperty, CloseValueBinding);
   candlestickDataPoint.SetBinding(CandlestickDataPoint.HighProperty, HighValueBinding);
   candlestickDataPoint.SetBinding(CandlestickDataPoint.LowProperty, LowValueBinding);
}

PrepareDataPoint prepares a data point by extracting and binding it to a data context object.

C#
protected override void UpdateDataPoint(DataPoint dataPoint)
{
   CandlestickDataPoint candlestickDataPoint = (CandlestickDataPoint)dataPoint;
   double PlotAreaHeight = 
      ActualDependentRangeAxis.GetPlotAreaCoordinate(
      ActualDependentRangeAxis.Range.Maximum);
   double dataPointX = 
      ActualIndependentRangeAxis.GetPlotAreaCoordinate(
      ValueHelper.ToComparable(dataPoint.ActualIndependentValue));
   double highPointY = 
      ActualDependentRangeAxis.GetPlotAreaCoordinate(
      ValueHelper.ToDouble(candlestickDataPoint.High));
   double lowPointY = 
      ActualDependentRangeAxis.GetPlotAreaCoordinate(
      ValueHelper.ToDouble(candlestickDataPoint.Low));
   double openPointY = 
      ActualDependentRangeAxis.GetPlotAreaCoordinate(
      ValueHelper.ToDouble(candlestickDataPoint.Open));
   double closePointY = 
      ActualDependentRangeAxis.GetPlotAreaCoordinate(
      ValueHelper.ToDouble(candlestickDataPoint.Close));
  
   candlestickDataPoint.UpdateBody(ActualDependentRangeAxis);

   if (ValueHelper.CanGraph(dataPointX))
   {
      dataPoint.Height = Math.Abs(highPointY - lowPointY);
      dataPoint.Width = 5.0;
      if (dataPoint.ActualWidth == 0.0 || dataPoint.ActualHeight == 0.0)
         dataPoint.UpdateLayout();

      Canvas.SetLeft(dataPoint,
         Math.Round(dataPointX - (dataPoint.ActualWidth / 2)));
      Canvas.SetTop(dataPoint,
         Math.Round(PlotAreaHeight - highPointY));
   }
}

UpdateDataPoint updates the visual representation of a single data point in the plot area.

And that is it…

CandlestickChart.jpg

XML
<charting:Chart Title="Typical Use">
   <charting:Chart.Series>
      <charting:CandlestickSeries
         Title="MSFT"
         ItemsSource="{Binding Microsoft, Source={StaticResource FinancialData}}"
         IndependentValueBinding="{Binding Date}"
         DependentValueBinding="{Binding High}"
         OpenValueBinding="{Binding Open}"
         CloseValueBinding="{Binding Close}"
         LowValueBinding="{Binding Low}"
         HighValueBinding="{Binding High}"/>
   </charting:Chart.Series>
</charting:Chart>

Please also visit my blog for more information...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionProblems importiing with VS2013 Pin
Member 1148162125-Feb-15 23:40
Member 1148162125-Feb-15 23:40 
QuestionForked for WPF 4.0 Pin
jogibear998829-Apr-14 11:56
jogibear998829-Apr-14 11:56 
QuestionI wish it worked with WPF :( Pin
Xavier John17-Sep-11 9:56
Xavier John17-Sep-11 9:56 
QuestionHow can I find the source code of this article? Pin
Member 250407611-Jan-11 2:40
professionalMember 250407611-Jan-11 2:40 
AnswerRe: How can I find the source code of this article? Pin
thavvarao9-Sep-11 6:06
thavvarao9-Sep-11 6:06 
GeneralMy vote of 5 Pin
Henrique Clausing30-Nov-10 0:12
Henrique Clausing30-Nov-10 0:12 
GeneralCustomizing style template Pin
Jon Burchel13-Nov-10 18:11
Jon Burchel13-Nov-10 18:11 
GeneralRe: Customizing style template Pin
Jon Burchel13-Nov-10 19:26
Jon Burchel13-Nov-10 19:26 
QuestionDataPointStyle Property Pin
Member 18713621-Aug-10 20:26
Member 18713621-Aug-10 20:26 
AnswerRe: DataPointStyle Property Pin
Member 187136210-Aug-10 1:37
Member 187136210-Aug-10 1:37 
GeneralRe: DataPointStyle Property Pin
Member 187136213-Aug-10 1:28
Member 187136213-Aug-10 1:28 
QuestionWPF Toolkit equivalent? Pin
tbgox24-May-10 9:31
tbgox24-May-10 9:31 
AnswerRe: WPF Toolkit equivalent? [modified] Pin
JowenMei17-Jun-10 22:40
JowenMei17-Jun-10 22:40 
Generalabout my new "how to create stock chart" Pin
chuncn14-May-10 20:05
chuncn14-May-10 20:05 
Dear Rudi Grobler:
I need you help.
I study your "how to create stock chart" in codeproject.Then I use and Transform it:
First,I Remove non-trading day
Second,I add zoom ,drag with using mouse and keyboard
etc.

The picture 's url by my doing is
http://images.cnblogs.com/cnblogs_com/chuncn/234695/o_2.png

But I meet a question:
I add many candlestick's points about 3000,then the zoom and drag 's speed and effect become slowly(instant stop).
I think the reason is that your "how to create stock chart" base on silverlight2.Now silverlight4 's performance had

increased,please you teach me convert sl2's "how to create stock chart" to sl4's "how to create stock chart".Thanks you!
wang,shenzhen,china
msn:dszj2005@hotmail.com
email:eboy_83@126.com
2010/05/15
thank you!

GeneralRe: about my new "how to create stock chart" Pin
Member 18713622-Aug-10 19:00
Member 18713622-Aug-10 19:00 
GeneralPlease give an opinion on developing an open source market charting and trade simulation program Pin
John Pretorius30-Apr-10 2:06
professionalJohn Pretorius30-Apr-10 2:06 
GeneralHelp me setting point by point instead of provide the observablecollection Pin
Camilo Vergara M.1-Jun-09 4:52
Camilo Vergara M.1-Jun-09 4:52 
GeneralOHLC Pin
Cengiz Ilerler27-Mar-09 19:00
Cengiz Ilerler27-Mar-09 19:00 
GeneralCan't compile the project Pin
Tawani Anyangwe20-Feb-09 2:18
Tawani Anyangwe20-Feb-09 2:18 
GeneralRe: Can't compile the project Pin
rudigrobler23-Feb-09 19:17
rudigrobler23-Feb-09 19:17 
GeneralRe: Can't compile the project Pin
thavvarao9-Sep-11 6:04
thavvarao9-Sep-11 6:04 
GeneralVery nice ... Pin
Colin Eberhardt16-Feb-09 23:19
Colin Eberhardt16-Feb-09 23:19 
GeneralRe: Very nice ... Pin
rudigrobler16-Feb-09 23:27
rudigrobler16-Feb-09 23:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.