Visualizing financial data with RadChart for Windows Phone, part of RadControls for Windows Phone, has never been easier. As of the Q3 2011 release, the control adds two of the most popular financial series – Candlestick and Stick (or OHLC as we call it) to its broad range of different visualizations.
In this post I will explain how easy it is to setup a chart that visualizes some financial data. The more interesting topics covered are:
Reading data from a file and creating view models
Setting-up and styling a RadCartesianChart instance
Adding chart interactivity
The data points created by a CandleStickSeries instance are of type OhlcDataPoint, which significant properties are Open, High, Low and Close. So, our view model has to expose some properties that will provide the needed values:
public
class
OhlcModel : ViewModelBase
{
private
double
open;
private
double
high;
private
double
low;
private
double
close;
private
DateTime date;
public
OhlcModel(
params
double
[] values)
{
this
.open = values[0];
this
.high = values[1];
this
.low = values[2];
this
.close = values[3];
}
public
DateTime Date
{
get
{
return
this
.date;
}
set
{
if
(
this
.date == value)
{
return
;
}
this
.date = value;
this
.OnPropertyChanged(
"Date"
);
}
}
public
double
Open
{
get
{
return
this
.open;
}
set
{
if
(
this
.open == value)
{
return
;
}
this
.open = value;
this
.OnPropertyChanged(
"Open"
);
}
}
public
double
High
{
get
{
return
this
.high;
}
set
{
if
(
this
.high == value)
{
return
;
}
this
.high = value;
this
.OnPropertyChanged(
"High"
);
}
}
public
double
Low
{
get
{
return
this
.low;
}
set
{
if
(
this
.low == value)
{
return
;
}
this
.low = value;
this
.OnPropertyChanged(
"Low"
);
}
}
public
double
Close
{
get
{
return
this
.close;
}
set
{
if
(
this
.close == value)
{
return
;
}
this
.close = value;
this
.OnPropertyChanged(
"Close"
);
}
}
}
We also have a Date property, which associates a view model with a particular date. This property will also be used as a “Category” key by the plotting DateTime axis.
Now that we have our view model prototyped, we need to create some real data to pass to the chart. Embedded in the project are three plain text files, which contain some sample financial data. The format of the data is like:
1/4/2010 30.62 31.24 27.66 28.18 81765200 27.09
Let’s see how we can read the data from these files and create our view models:
private
static
void
LoadData(List<OhlcModel> list,
string
fileName)
{
StreamResourceInfo resource = Application.GetResourceStream(
new
Uri(
"ViewModel/"
+ fileName +
".txt"
, UriKind.RelativeOrAbsolute));
using
(StreamReader reader =
new
StreamReader(resource.Stream))
{
string
line =
string
.Empty;
while
(!
string
.IsNullOrEmpty(line = reader.ReadLine()))
{
string
[] values = line.Split(
'\t'
);
double
[] args =
new
double
[values.Length - 1];
// first argument is the Date, start from the second splitted value
for
(
int
i = 1; i < values.Length; i++)
{
args[i - 1] =
double
.Parse(values[i], CultureInfo.InvariantCulture);
}
OhlcModel model =
new
OhlcModel(args);
model.Date = DateTime.Parse(values[0], CultureInfo.InvariantCulture);
list.Add(model);
}
}
}
The method accepts two arguments: the actual list of view models to be populated and the name of the file, containing the data. What we do is to retrieve the core file stream, to read it and to parse each line into a set of values to be passed to a view model instance.
Okay, we are ready with the data, time to setup the chart:
<
telerikChart:RadCartesianChart
Grid.Row
=
"1"
Margin
=
"-8,0,0,0"
x:Name
=
"chart"
Palette
=
"Warm"
>
<
telerikChart:RadCartesianChart.VerticalAxis
>
<
telerikChart:LinearAxis
LineStroke
=
"{StaticResource PhoneSubtleBrush}"
LineThickness
=
"2"
RangeExtendDirection
=
"Positive"
LabelStyle
=
"{StaticResource axisLabelStyle}"
/>
</
telerikChart:RadCartesianChart.VerticalAxis
>
<
telerikChart:RadCartesianChart.HorizontalAxis
>
<
telerikChart:DateTimeCategoricalAxis
LabelFormat
=
"MMM-dd"
LabelFitMode
=
"Rotate"
LabelRotationAngle
=
"325"
LineStroke
=
"{StaticResource PhoneSubtleBrush}"
LineThickness
=
"2"
LabelStyle
=
"{StaticResource axisLabelStyle}"
MajorTickInterval
=
"8"
DateTimeComponent
=
"Date"
/>
</
telerikChart:RadCartesianChart.HorizontalAxis
>
<
telerikChart:CandlestickSeries
OpenBinding
=
"Open"
HighBinding
=
"High"
LowBinding
=
"Low"
CloseBinding
=
"Close"
CategoryBinding
=
"Date"
ItemsSource
=
"{Binding WeeklyData}"
DisplayName
=
"stocks"
>
</
telerikChart:CandlestickSeries
>
</
telerikChart:RadCartesianChart
>
We will need a vertical LinearAxis to plot all the Open-High-Low-Close values properly and we will need a horizontal DateTimeCategoricalAxis to plot our data by its Date property. We will use CandleStickSeries to visualize our data and we need to specify the proper bindings to look-up actual values from.
To emphasize the data we may add grid lines to the chart:
<
telerikChart:RadCartesianChart.Grid
>
<
telerikChart:CartesianChartGrid
MajorLinesVisibility
=
"Y"
MajorYLineDashArray
=
"5, 5"
>
<
telerikChart:CartesianChartGrid.MajorXLineStyle
>
<
Style
TargetType
=
"Line"
>
<
Setter
Property
=
"Stroke"
Value
=
"{StaticResource PhoneSubtleBrush}"
/>
</
Style
>
</
telerikChart:CartesianChartGrid.MajorXLineStyle
>
<
telerikChart:CartesianChartGrid.MajorYLineStyle
>
<
Style
TargetType
=
"Line"
>
<
Setter
Property
=
"Stroke"
Value
=
"{StaticResource PhoneSubtleBrush}"
/>
</
Style
>
</
telerikChart:CartesianChartGrid.MajorYLineStyle
>
</
telerikChart:CartesianChartGrid
>
</
telerikChart:RadCartesianChart.Grid
>
And to make the chart more readable let’s add some interactivity to it:
<
telerikChart:RadCartesianChart.Behaviors
>
<
telerikChart:ChartPanAndZoomBehavior
ZoomMode
=
"Horizontal"
PanMode
=
"Horizontal"
/>
<
telerikChart:ChartTrackBallBehavior
ShowIntersectionPoints
=
"True"
ShowTrackInfo
=
"True"
/>
</
telerikChart:RadCartesianChart.Behaviors
>
We add a ChartPanAndZoomBehavior instance to allow data zooming and panning – only by the horizontal axis. And by adding the ChartTrackBallBehavior instance we allow the users to read the data on a per data point basis by performing a “Hold” gesture over the chart area.
You may also want to display a visual hint at the intersection point of the trackball line and the series:
<
telerikChart:CandlestickSeries.TrackBallTemplate
>
<
DataTemplate
>
<
Grid
>
<
Ellipse
Width
=
"12"
Height
=
"12"
StrokeThickness
=
"2"
Stroke
=
"{StaticResource PhoneSubtleBrush}"
/>
<
Ellipse
Width
=
"8"
Height
=
"8"
StrokeThickness
=
"2"
Stroke
=
"{StaticResource PhoneForegroundBrush}"
HorizontalAlignment
=
"Center"
VerticalAlignment
=
"Center"
/>
</
Grid
>
</
DataTemplate
>
</
telerikChart:CandlestickSeries.TrackBallTemplate
>
By applying initial zoom of 4 along the X-axis of the chart we can display the data in a more readable way (note the trackball intersection point and info part):
Quite easy, right? If we simply replace CandleStickSeries with OhlcSeries we will get another visual representation of the same data:
Well, I hope you will find this post interesting. Please, feel free to drop us your feedback should you have some questions and/or suggestions.
Georgi worked at Progress Telerik to build a product that added the Progress value into the augmented and virtual reality development workflow.