Telerik blogs

Download the demo

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 view model

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.

Reading the data

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.

Setting-up the chart

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.

Download the demo


Georgi Atanasov 164x164
About the Author

Georgi Atanasov

Georgi worked at Progress Telerik to build a product that added the Progress value into the augmented and virtual reality development workflow.

 

Comments

Comments are disabled in preview mode.