SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components
SciChart WPF ships with hundreds of WPF Chart Examples which you can browse, play with, view the source-code and even export each WPF Chart Example to a stand-alone Visual Studio solution. All of this is possible with the new and improved SciChart WPF Examples Suite, which ships as part of the SciChart WPF SDK.
Demonstrates how to the AggregationFilter, part of the Filters API in SciChart WPF v5.
Given a data-source of trading ticks or quotes, we aggregate into bars (Time bars, Range bars, Volume bars, Tick Bars and Renko Bars).
Each bar type is created by a different filter type, and we use the extension methods DataSeries.AggregateByTime, DataSeries.AggregateByCount, DataSeries.AggregateByVolume, DataSeries.AggregateByRange and DataSeries.AggregateByRenko. This creates a filter around the original tick data. Any changes to the tick data are reflected in the resulting bars on the chart.
Documentation Links
– FastCandlestickRenderableSeries Type
– What is the Filters API
– The DiscontinuousDateTimeAxis
– Renko, Volume, Tick and Range Bars
The C#/WPF source code for the WPF Chart Gaps (Nulls) in Series example is included below (Scroll down!).
Did you know you can also view the source code from one of the following sources as well?
<UserControl x:Class="SciChart.Examples.Examples.SeeFeaturedApplication.AggregationFilters.AggregationFiltersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ext="http://schemas.abtsoftware.co.uk/scichart/exampleExternals"
xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SciChart.Examples.Examples.SeeFeaturedApplication.AggregationFilters"
d:DataContext="{d:DesignInstance local:AggregationFiltersViewModel, IsDesignTimeCreatable=True}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SciChart.Examples.ExternalDependencies;component/Resources/Styles/MergedResources.xaml"/>
<ResourceDictionary Source="/SciChart.Examples.ExternalDependencies;component/Resources/Styles/ToolbarButtonsCommon.xaml"/>
</ResourceDictionary.MergedDictionaries>
<s:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<s:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<ext:IsSameObjectsMultiConverter x:Key="IsSameSeriesMultiConverter"/>
<ext:EnumValueToStringConverter x:Key="SelectedEnumValueConverter"/>
<Style x:Key="DataItemTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding Stroke, Converter={StaticResource ColorToBrushConverter}}"/>
<Setter Property="MinWidth" Value="80"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="Margin" Value="0,0,20,0"/>
</Style>
<!-- DataTemplate for the SeriesInfo which are exposed on the RolloverModifier -->
<DataTemplate x:Key="ChartDataTemplate" DataType="s:SeriesInfo">
<TextBlock Style="{StaticResource DataItemTextBlockStyle}">
<Run Text="{Binding SeriesName, StringFormat=\{0\}:}"/>
<Run Text="{Binding Value, StringFormat=\{0:0.000\}}"/>
</TextBlock>
</DataTemplate>
<!-- Style for the 50-period Moving Average -->
<Style x:Key="Ma50SeriesStyle" TargetType="s:FastLineRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax"/>
<Setter Property="Stroke" Value="#FFE13219"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#AAE13219"
Stroke="White"
StrokeThickness="2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for 200 period Moving Average -->
<Style x:Key="Ma200SeriesStyle" TargetType="s:FastLineRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax"/>
<Setter Property="Stroke" Value="#FFFFA500"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#AAFFA500"
Stroke="White"
StrokeThickness="2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for Candlestick chart -->
<Style x:Key="PriceSeriesStyle" TargetType="s:FastCandlestickRenderableSeries">
<Setter Property="StrokeUp" Value="#FF52CC54"/>
<Setter Property="StrokeDown" Value="#FFE26565"/>
<Setter Property="FillUp" Value="#7052CC54"/>
<Setter Property="FillDown" Value ="#70E26565"/>
<Setter Property="AntiAliasing" Value="False"/>
<Setter Property="ResamplingMode" Value="MinMax"/>
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#FF52CC54"
Stroke="White"
StrokeThickness="2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Define the Toolbar -->
<Border Panel.ZIndex="9999"
Background="#232426"
BorderBrush="#323539"
BorderThickness="0,0,2,0">
<WrapPanel HorizontalAlignment="Left" Orientation="Vertical">
<ToggleButton Content="Zoom"
HorizontalAlignment="Left"
Command="{Binding SetRubberBandModifierCommand}"
IsChecked="{Binding IsRubberBandZoomSelected, Mode=OneWay}"
Style="{StaticResource ZoomButtonStyle}"
ToolTipService.ToolTip="Toggle Rubber-Band Zoom"/>
<ext:FlyoutMenuToggleButton Content="Pan"
HorizontalAlignment="Left"
Command="{Binding SetZoomPanModifierCommand}"
IsChecked="{Binding IsZoomPanSelected, Mode=OneWay}"
Style="{StaticResource PanToggleButtonStyle}"
ToolTipService.ToolTip="Toggle Zoom-Pan">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock Text="Direction"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:XyDirection}}}"
SelectedItem="{Binding Source={x:Reference Name=ZoomPanMod}, Path=XyDirection, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<ext:FlyoutSeparator/>
<Button Content="Zoom Extents"
HorizontalAlignment="Left"
Command="{Binding Source={x:Reference Name=PriceChart}, Path=AnimateZoomExtentsCommand}"
Style="{StaticResource ZoomExtentsButtonStyle}"
ToolTipService.ToolTip="Zoom to Extents"/>
<ext:FlyoutMenuButton Content="Wheel"
HorizontalAlignment="Left"
Style="{StaticResource MouseWheelButtonStyle}"
ToolTipService.ToolTip="MouseWheel">
<ext:FlyoutMenuButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock Text="Action Type"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ActionType}}}"
SelectedItem="{Binding ActionType, Source={x:Reference Name=MouseWheelZoomMod}, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Direction"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:XyDirection}}}"
SelectedItem="{Binding XyDirection, Source={x:Reference Name=MouseWheelZoomMod}, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
</StackPanel>
</ext:FlyoutMenuButton.PopupContent>
</ext:FlyoutMenuButton>
<!-- Rollover modifier -->
<ext:FlyoutMenuToggleButton HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
Command="{Binding SetRolloverModifierCommand}"
Content="ROLL"
FontSize="10"
IsChecked="{Binding IsRolloverSelected, Mode=OneWay}"
Padding="0"
Style="{StaticResource FlyoutMenuToggleButtonStyle}"
ToolTipService.ToolTip="Rollover">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock FontSize="12" Text="Rollover mode"/>
<ComboBox FontSize="12"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:SourceMode}}}"
SelectedItem="{Binding SourceMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock FontSize="12" Text="Show tooltip mode"/>
<ComboBox FontSize="12"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ShowTooltipOptions}}}"
SelectedItem="{Binding ShowTooltipMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<CheckBox Margin="3"
VerticalAlignment="Center"
Content="Show axis label"
FontSize="12"
IsChecked="{Binding ShowAxisLabels, Mode=TwoWay}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<!-- Cursor modifier -->
<ext:FlyoutMenuToggleButton HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
Command="{Binding SetCursorModifierCommand}"
Content="CUR"
IsChecked="{Binding IsCursorSelected, Mode=OneWay}"
Padding="0"
Style="{StaticResource CursorButtonStyle}">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<StackPanel.Resources>
<ext:SnappingModeToVisibilityConverter x:Key="SnappingModeToVisibilityConverter"/>
</StackPanel.Resources>
<TextBlock Text="Cursor mode"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:SourceMode}}}"
SelectedItem="{Binding SourceMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Show tooltip mode"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ShowTooltipOptions}}}"
SelectedItem="{Binding ShowTooltipMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Snapping mode"/>
<ComboBox x:Name="snappingModeCmbx"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:CursorSnappingMode}}}"
SelectedItem="{Binding Source={x:Reference Name=CursorMod}, Path=SnappingMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<StackPanel Orientation="Vertical" Visibility="{Binding SelectedItem, Source={x:Reference Name=snappingModeCmbx}, Mode=OneWay, Converter={StaticResource SnappingModeToVisibilityConverter}}">
<TextBlock Text="Snap to"/>
<ComboBox FontSize="12"
ItemsSource="{Binding AllSeriesNames, Mode=OneWay}"
SelectedItem="{Binding SelectedSeriesToSnap, Mode=TwoWay}"/>
<ext:FlyoutSeparator/>
</StackPanel>
<CheckBox Margin="3"
VerticalAlignment="Center"
Content="Show axis label"
IsChecked="{Binding ShowAxisLabels, Mode=TwoWay}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<ext:FlyoutSeparator/>
<ext:FlyoutMenuButton x:Name="traderDataExample"
HorizontalAlignment="Left"
Content="Data"
FontSize="11"
Padding="0"
Style="{StaticResource FlyoutMenuButtonStyle}"
ToolTipService.ToolTip="Data">
<ext:FlyoutMenuButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock FontSize="12" Text="Aggregation Price Chart:"/>
<ComboBox Margin="2" x:Name="AggregationPriceCharts"
FontSize="12"
ItemsSource="{Binding AllAggregationPriceCharts}"
SelectedItem="{Binding SelectedAggregationPriceChart, Mode=TwoWay}"/>
<ext:FlyoutSeparator/>
<StackPanel>
<TextBlock FontSize="12" Text="Count:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllCounts}"
SelectedItem="{Binding SelectedCount, Mode=TwoWay}"/>
<StackPanel.Style>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAggregationPriceChart}" Value="Count">
<Setter Property="FrameworkElement.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<StackPanel>
<TextBlock FontSize="12" Text="Time Frame (min):"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllTimeFrames}"
SelectedItem="{Binding SelectedTimeFrame, Mode=TwoWay}"/>
<StackPanel.Style>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAggregationPriceChart}" Value="Time">
<Setter Property="FrameworkElement.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<StackPanel>
<TextBlock FontSize="12" Text="Volume:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllVolumes}"
SelectedItem="{Binding SelectedVolume, Mode=TwoWay}"/>
<StackPanel.Style>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAggregationPriceChart}" Value="Volume">
<Setter Property="FrameworkElement.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<StackPanel>
<TextBlock FontSize="12" Text="Range:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllRanges}"
SelectedItem="{Binding SelectedRange, Mode=TwoWay}"/>
<StackPanel.Style>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAggregationPriceChart}" Value="Range">
<Setter Property="FrameworkElement.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<StackPanel>
<TextBlock FontSize="12" Text="Brick size:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllBrickSizes}"
SelectedItem="{Binding SelectedBrickSize, Mode=TwoWay}"/>
<StackPanel.Style>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAggregationPriceChart}" Value="Renko">
<Setter Property="FrameworkElement.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
</StackPanel>
</ext:FlyoutMenuButton.PopupContent>
</ext:FlyoutMenuButton>
</WrapPanel>
</Border>
<Grid Grid.Column="1" Background="#333">
<s:SciChartSurface x:Name="PriceChart">
<s:SciChartSurface.RenderableSeries>
<s:FastCandlestickRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastCandlestickRenderableSeries>
<s:FastLineRenderableSeries DataSeries="{Binding Sma50Series}" Style="{StaticResource Ma50SeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastLineRenderableSeries>
<s:FastLineRenderableSeries DataSeries="{Binding Sma200Series}" Style="{StaticResource Ma200SeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastLineRenderableSeries>
</s:SciChartSurface.RenderableSeries>
<!-- Create X Axis. Optional bands give a cool look and feel for minimal performance impact -->
<s:SciChartSurface.XAxis>
<s:CategoryDateTimeAxis DrawMajorBands="True" GrowBy="0.0, 0.1"/>
</s:SciChartSurface.XAxis>
<!-- Create Y Axis -->
<s:SciChartSurface.YAxis>
<s:NumericAxis AutoRange="Always" GrowBy="0.1, 0.1"/>
</s:SciChartSurface.YAxis>
<!-- Create and enable ChartModifiers through bindings -->
<s:SciChartSurface.ChartModifier>
<s:ModifierGroup>
<s:RolloverModifier x:Name="RolloverMod"
IsEnabled="{Binding IsRolloverSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
ShowAxisLabels="{Binding ShowAxisLabels}"
ShowTooltipOn="{Binding ShowTooltipMode}"
SourceMode="{Binding SourceMode}"/>
<s:CursorModifier x:Name="CursorMod"
IsEnabled="{Binding IsCursorSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
ShowAxisLabels="{Binding ShowAxisLabels}"
ShowTooltip="True"
ShowTooltipOn="{Binding ShowTooltipMode}"
SourceMode="{Binding SourceMode}"/>
<s:MouseWheelZoomModifier x:Name="MouseWheelZoomMod"
ReceiveHandledEvents="True"
XyDirection="XYDirection"
ActionType="Zoom"/>
<s:RubberBandXyZoomModifier IsEnabled="{Binding IsRubberBandZoomSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
IsXAxisOnly="True"/>
<s:ZoomPanModifier x:Name="ZoomPanMod"
ClipModeX="None"
IsEnabled="{Binding IsZoomPanSelected, Mode=OneWay}"
ReceiveHandledEvents="True"/>
<s:ZoomExtentsModifier ExecuteOn="MouseDoubleClick"/>
</s:ModifierGroup>
</s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
<ItemsControl Margin="20"
IsHitTestVisible="False"
VerticalAlignment="Top"
DataContext="{Binding Source={x:Reference Name=PriceChart}, Path=ChartModifier}"
ItemTemplate="{StaticResource ChartDataTemplate}"
ItemsSource="{Binding Path=[RolloverModifier].SeriesData.SeriesInfo, Mode=OneWay}"
Visibility="{Binding Path=[RolloverModifier].IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Grid>
</UserControl>
// *************************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2022. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// AggregationFiltersView.xaml.cs is part of the SCICHART® Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART® examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
// *************************************************************************************
namespace SciChart.Examples.Examples.SeeFeaturedApplication.AggregationFilters
{
public partial class AggregationFiltersView
{
public AggregationFiltersView()
{
InitializeComponent();
}
}
}
// *************************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2022. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// AggregationFiltersViewModel.cs is part of the SCICHART® Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART® examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
// *************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Common.Helpers;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Model.Filters;
using SciChart.Core.Extensions;
using SciChart.Examples.ExternalDependencies.Common;
using SciChart.Examples.ExternalDependencies.Data;
namespace SciChart.Examples.Examples.SeeFeaturedApplication.AggregationFilters
{
public class AggregationFiltersViewModel : BaseViewModel
{
private readonly List<Tick> _ticks;
private readonly IOhlcDataSeries<DateTime, double> _priceData = new OhlcDataSeries<DateTime, double>();
private IOhlcDataSeries<DateTime, double> _priceSeries;
private IXyDataSeries<DateTime, double> _sma200Series;
private IXyDataSeries<DateTime, double> _sma50Series;
private AggregationPriceChart _selectedAggregationPriceChart;
private ModifierType _chartZoomModifier;
private ModifierType _chartSeriesModifier;
private ShowTooltipOptions _showTooltipMode;
private SourceMode _sourceMode;
private bool _showAxisLabels;
private string _selectedSeriesToSnap;
private int _selectedCount;
private int _selectedTimeFrame;
private int _selectedVolume;
private double _selectedRange;
private double _selectedBrickSize;
public AggregationFiltersViewModel()
{
_ticks = DataManager.Instance.GetTicks().ToList();
_priceData.Append(_ticks.Select(x => x.DateTime), _ticks.Select(x => x.Open), _ticks.Select(x => x.High), _ticks.Select(x => x.Low), _ticks.Select(x => x.Close));
SetZoomPanModifierCommand = new ActionCommand(() => ChartZoomModifier = IsZoomPanSelected ? ModifierType.Null : ModifierType.ZoomPan);
SetRubberBandModifierCommand = new ActionCommand(() => ChartZoomModifier = IsRubberBandZoomSelected ? ModifierType.Null : ModifierType.RubberBandZoom);
SetCursorModifierCommand = new ActionCommand(() => ChartSeriesModifier = IsCursorSelected ? ModifierType.Null : ModifierType.CrosshairsCursor);
SetRolloverModifierCommand = new ActionCommand(() => ChartSeriesModifier = IsRolloverSelected ? ModifierType.Null : ModifierType.Rollover);
SetDefaults();
InitializeChartSurface();
}
public ActionCommand SetZoomPanModifierCommand { get; }
public ActionCommand SetRubberBandModifierCommand { get; }
public ActionCommand SetCursorModifierCommand { get; }
public ActionCommand SetRolloverModifierCommand { get; }
public bool IsZoomPanSelected => ChartZoomModifier == ModifierType.ZoomPan;
public bool IsRubberBandZoomSelected => ChartZoomModifier == ModifierType.RubberBandZoom;
public bool IsCursorSelected => ChartSeriesModifier == ModifierType.CrosshairsCursor;
public bool IsRolloverSelected => ChartSeriesModifier == ModifierType.Rollover;
public IEnumerable<AggregationPriceChart> AllAggregationPriceCharts { get; } = new[]
{
AggregationPriceChart.Count,
AggregationPriceChart.Time,
AggregationPriceChart.Volume,
AggregationPriceChart.Range,
AggregationPriceChart.Renko
};
public IEnumerable<int> AllCounts { get; } = new[] { 1000, 2000, 3000 };
public IEnumerable<int> AllTimeFrames { get; } = new[] { 5, 15, 30 };
public IEnumerable<int> AllVolumes { get; } = new[] { 1000, 2000, 3000 };
public IEnumerable<double> AllRanges { get; } = new[] { 0.5, 1.0, 1.5 };
public IEnumerable<double> AllBrickSizes { get; } = new[] { 0.5, 1.0, 1.5 };
public IEnumerable<string> AllSeriesNames { get; } = new[] { "PriceData", "200 SMA", "50 SMA" };
public IOhlcDataSeries<DateTime, double> PriceSeries
{
get => _priceSeries;
set
{
_priceSeries = value;
_priceSeries.SeriesName = "PriceData";
OnPropertyChanged(nameof(PriceSeries));
}
}
public IXyDataSeries<DateTime, double> Sma200Series
{
get => _sma200Series;
set
{
_sma200Series = value;
_sma200Series.SeriesName = "200 SMA";
OnPropertyChanged(nameof(Sma200Series));
}
}
public IXyDataSeries<DateTime, double> Sma50Series
{
get => _sma50Series;
set
{
_sma50Series = value;
_sma50Series.SeriesName = "50 SMA";
OnPropertyChanged(nameof(Sma50Series));
}
}
public string SelectedSeriesToSnap
{
get => _selectedSeriesToSnap;
set
{
_selectedSeriesToSnap = value;
OnPropertyChanged(nameof(SelectedSeriesToSnap));
}
}
private void InitializeChartSurface()
{
UpdatePriceChart(_selectedAggregationPriceChart);
ChartZoomModifier = ModifierType.RubberBandZoom;
ChartSeriesModifier = ModifierType.Rollover;
}
private void SetDefaults()
{
_selectedSeriesToSnap = "PriceData";
_selectedAggregationPriceChart = AggregationPriceChart.Count;
_selectedCount = 1000;
_selectedTimeFrame = 5;
_selectedVolume = 1000;
_selectedRange = 0.5;
_selectedBrickSize = 0.5;
}
public ModifierType ChartSeriesModifier
{
get => _chartSeriesModifier;
set
{
_chartSeriesModifier = value;
OnPropertyChanged(nameof(ChartSeriesModifier));
OnPropertyChanged(nameof(IsRolloverSelected));
OnPropertyChanged(nameof(IsCursorSelected));
}
}
public ModifierType ChartZoomModifier
{
get => _chartZoomModifier;
set
{
_chartZoomModifier = value;
OnPropertyChanged(nameof(ChartZoomModifier));
OnPropertyChanged(nameof(IsZoomPanSelected));
OnPropertyChanged(nameof(IsRubberBandZoomSelected));
}
}
public ShowTooltipOptions ShowTooltipMode
{
get => _showTooltipMode;
set
{
_showTooltipMode = value;
OnPropertyChanged(nameof(ShowTooltipMode));
}
}
public SourceMode SourceMode
{
get => _sourceMode;
set
{
_sourceMode = value;
OnPropertyChanged(nameof(SourceMode));
}
}
public bool ShowAxisLabels
{
get => _showAxisLabels;
set
{
_showAxisLabels = value;
OnPropertyChanged(nameof(ShowAxisLabels));
}
}
public AggregationPriceChart SelectedAggregationPriceChart
{
get => _selectedAggregationPriceChart;
set
{
_selectedAggregationPriceChart = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedAggregationPriceChart));
}
}
public int SelectedCount
{
get => _selectedCount;
set
{
_selectedCount = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedCount));
}
}
public int SelectedTimeFrame
{
get => _selectedTimeFrame;
set
{
_selectedTimeFrame = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedTimeFrame));
}
}
public int SelectedVolume
{
get => _selectedVolume;
set
{
_selectedVolume = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedVolume));
}
}
public double SelectedRange
{
get => _selectedRange;
set
{
_selectedRange = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedRange));
}
}
public double SelectedBrickSize
{
get => _selectedBrickSize;
set
{
_selectedBrickSize = value;
UpdatePriceChart(_selectedAggregationPriceChart);
OnPropertyChanged(nameof(SelectedBrickSize));
}
}
private void UpdatePriceChart(AggregationPriceChart barStyle)
{
switch (barStyle)
{
case AggregationPriceChart.Count:
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.AggregateByCount(_selectedCount);
break;
case AggregationPriceChart.Time:
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.AggregateByTime(TimeSpan.FromMinutes(_selectedTimeFrame));
break;
case AggregationPriceChart.Volume:
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.AggregateByVolume(i =>_ticks[i].Volume.ToDouble(), _selectedVolume);
break;
case AggregationPriceChart.Range:
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.AggregateByRange(_selectedRange);
break;
case AggregationPriceChart.Renko:
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.AggregateByRenko(_selectedBrickSize);
break;
}
// Create a series for the 200 period SMA which will be plotted as a line chart
Sma200Series = (IXyDataSeries<DateTime, double>)PriceSeries.ToMovingAverage(200);
// Create a series for the 50 period SMA which will be plotted as a line chart
Sma50Series = (IXyDataSeries<DateTime, double>)((IXyDataSeries<DateTime, double>)PriceSeries.ToMovingAverage(50)).Scale(1.001);
_priceSeries.InvalidateParentSurface(RangeMode.ZoomToFit);
}
}
}