Skip to content

Commit

Permalink
[MDAPI-67] [.NET] Integrate IndexedEventTxModel
Browse files Browse the repository at this point in the history
- implement models
  • Loading branch information
Konstantin Ivaschenko committed Jul 24, 2024
1 parent 32f6103 commit e4e8e7b
Show file tree
Hide file tree
Showing 30 changed files with 1,959 additions and 546 deletions.
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ dotnet_diagnostic.CA1861.severity = none
dotnet_diagnostic.CA1846.severity = none
# CA1845 : Use span-based 'string.Concat' and 'AsSpan' instead of 'Substring'
dotnet_diagnostic.CA1845.severity = none
dotnet_diagnostic.cs0693.severity=none
dotnet_diagnostic.CA1000.severity=none
##########################################
# Formatting Rules
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules
Expand Down
7 changes: 7 additions & 0 deletions dxfeed-graal-net-api.sln
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CandleDataResponseReader",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketDepthModelSample", "samples\MarketDepthModelSample\MarketDepthModelSample.csproj", "{930B1039-B76C-42C5-AD0F-9FA1A1FC9D84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CandleChartSample", "samples\CandleChartSample\CandleChartSample.csproj", "{B74E8A86-1AB7-4B36-AED3-292CDD95BF90}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -118,6 +120,10 @@ Global
{930B1039-B76C-42C5-AD0F-9FA1A1FC9D84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{930B1039-B76C-42C5-AD0F-9FA1A1FC9D84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{930B1039-B76C-42C5-AD0F-9FA1A1FC9D84}.Release|Any CPU.Build.0 = Release|Any CPU
{B74E8A86-1AB7-4B36-AED3-292CDD95BF90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B74E8A86-1AB7-4B36-AED3-292CDD95BF90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B74E8A86-1AB7-4B36-AED3-292CDD95BF90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B74E8A86-1AB7-4B36-AED3-292CDD95BF90}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{73597E04-D8A8-4991-A759-7F886CBE2A8F} = {C4490D74-2970-4A1B-8178-A724A06B140A}
Expand All @@ -136,5 +142,6 @@ Global
{B9088D14-10F6-4D88-876D-062B9F6494AB} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{2567935E-FEFB-470A-BF17-7A883735C4BF} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{930B1039-B76C-42C5-AD0F-9FA1A1FC9D84} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{B74E8A86-1AB7-4B36-AED3-292CDD95BF90} = {C4490D74-2970-4A1B-8178-A724A06B140A}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions dxfeed-graal-net-api.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=multiplexor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dkey/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ddxfeed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ohlc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=OPASPS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=opol/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Osub/@EntryIndexedValue">True</s:Boolean>
Expand Down
10 changes: 10 additions & 0 deletions samples/CandleChartSample/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="CandleChartSample.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
23 changes: 23 additions & 0 deletions samples/CandleChartSample/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

namespace CandleChartSample;

public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
}

base.OnFrameworkInitializationCompleted();
}
}
26 changes: 26 additions & 0 deletions samples/CandleChartSample/CandleChartSample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.10"/>
<PackageReference Include="Avalonia.Desktop" Version="11.0.10"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.10"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.10"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.10"/>
<PackageReference Include="ScottPlot.Avalonia" Version="5.0.36"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\DxFeed.Graal.Net\DxFeed.Graal.Net.csproj"/>
</ItemGroup>

</Project>
44 changes: 44 additions & 0 deletions samples/CandleChartSample/CandleExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <copyright file="CandleExtension.cs" company="Devexperts LLC">
// Copyright © 2024 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// </copyright>

using System;
using DxFeed.Graal.Net.Events.Candles;
using ScottPlot;

namespace CandleChartSample;

public static class CandleExtension
{
public static OHLC ToOHLC(this Candle candle)
{
var open = GetValueWithPriority(candle.Open, candle.High, candle.Low, candle.Close);
var high = GetValueWithPriority(candle.High, candle.Open, candle.Low, candle.Close);
var low = GetValueWithPriority(candle.Low, candle.Close, candle.Open, candle.High);
var close = GetValueWithPriority(candle.Close, candle.Low, candle.Open, candle.High);

return new OHLC
{
Open = open,
High = high,
Low = low,
Close = close,
DateTime = DateTimeOffset.FromUnixTimeMilliseconds(candle.Time).DateTime.ToLocalTime(),
TimeSpan = TimeSpan.FromMilliseconds(candle.CandleSymbol!.Period!.PeriodIntervalMillis)
};
}

private static double GetValueWithPriority(params double[] values)
{
foreach (var value in values)
{
if (!double.IsNaN(value))
{
return value;
}
}
return double.NaN;
}
}
111 changes: 111 additions & 0 deletions samples/CandleChartSample/CandleList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// <copyright file="CandleList.cs" company="Devexperts LLC">
// Copyright © 2024 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using DxFeed.Graal.Net.Events;
using DxFeed.Graal.Net.Events.Candles;
using ScottPlot;

namespace CandleChartSample;

public class CandleList : List<OHLC>
{
public void Update(IEnumerable<Candle> candles, bool isSnapshot)
{
var sortedCandles = candles.OrderBy(c => c.Index);

if (isSnapshot)
{
UpdateSnapshot(sortedCandles);
}
else
{
UpdateIncremental(sortedCandles);
}
}

private void UpdateSnapshot(IEnumerable<Candle> candles)
{
Clear();
foreach (var candle in candles)
{
if (!ShouldRemove(candle))
{
Add(candle.ToOHLC());
}
}
}

private void UpdateIncremental(IEnumerable<Candle> candles)
{
foreach (var candle in candles)
{
if (ShouldRemove(candle))
{
RemoveCandle(candle);
continue;
}

var ohlc = candle.ToOHLC();
var lastOhlc = LastOrDefault();
switch (DateTime.Compare(ohlc.DateTime, lastOhlc.DateTime))
{
case < 0:
InsertOrUpdate(ohlc);
break;
case 0:
AddOrUpdateLast(ohlc);
break;
case > 0:
Add(ohlc);
break;
}
}
}

private void AddOrUpdateLast(OHLC ohlc)
{
if (IsEmpty())
{
Add(ohlc);
}
else
{
this[Count - 1] = ohlc;
}
}

private void InsertOrUpdate(OHLC ohlc)
{
var index = FindIndex(o => DateTime.Compare(ohlc.DateTime, o.DateTime) <= 0);
if (index >= 0 && this[index].DateTime.Equals(ohlc.DateTime))
{
this[index] = ohlc;
}
else
{
Insert(index >= 0 ? index : 0, ohlc);
}
}

private void RemoveCandle(Candle candle) =>
RemoveAll(ohlc => candle.ToOHLC().DateTime.Equals(ohlc.DateTime));

private bool IsEmpty() =>
Count == 0;

private OHLC LastOrDefault() =>
IsEmpty() ? new OHLC() : this[Count - 1];

private static bool ShouldRemove(Candle candle) =>
EventFlags.IsRemove(candle) ||
(double.IsNaN(candle.Open) &&
double.IsNaN(candle.High) &&
double.IsNaN(candle.Low) &&
double.IsNaN(candle.Close));
}
45 changes: 45 additions & 0 deletions samples/CandleChartSample/MainWindow.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:scottPlot="clr-namespace:ScottPlot.Avalonia;assembly=ScottPlot.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="CandleChartSample.MainWindow"
WindowStartupLocation="CenterScreen"
Title="CandleChartSample">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" HorizontalAlignment="Left" Margin="10" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Symbol" Margin="5" FontSize="12" VerticalAlignment="Center" />
<TextBox x:Name="SymbolTextBox"
Grid.Column="1"
Text="AAPL{=d}"
FontSize="12"
Width="180"
Margin="5"
KeyDown="OnKeyDown"
LostFocus="OnLostFocus" />
<TextBlock Grid.Column="2" Text="From Time" Margin="5" FontSize="12" VerticalAlignment="Center" />
<TextBox x:Name="FromTimeTextBox"
Grid.Column="3"
FontSize="12"
Width="180"
Margin="5"
KeyDown="OnKeyDown"
LostFocus="OnLostFocus" />
</Grid>
<Grid Grid.Row="1" Grid.Column="0">
<scottPlot:AvaPlot Name="AvaPlot" />
</Grid>
</Grid>

</Window>
Loading

0 comments on commit e4e8e7b

Please sign in to comment.