Skip to content

Commit

Permalink
Add IpfConnection (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
stdcion authored Nov 3, 2023
1 parent 5c9cb48 commit 4662888
Show file tree
Hide file tree
Showing 23 changed files with 701 additions and 186 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,18 @@ ready to answer any questions and help with the transition.

#### Sample Mapping

| # | Sample | Old Version | New Version |
|:--:|:----------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------|
| 1 | How to subscribe to `Quote`, `Trade`, `TradeETH`, `Order`, `SpreadOrder`, `AnalyticOrder`, `TimeAndSale` events | [dxf_events_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_events_sample) | [DxFeed.Graal.Net.Samples.DxFeedConnect](samples/DxFeedConnect) |
| 2 | How to subscribe to `Candle` event | [dxf_candle_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_candle_sample) | [DxFeed.Graal.Net.Samples.CandleSample](samples/CandleSample) |
| 3 | How to receive IPF data from URL or file | [dxf_instrument_profile_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_instrument_profile_sample) | [DxFeed.Graal.Net.Samples.DXFeedIpfConnect](samples/DXFeedIpfConnect) |
| 4 | How to subscribe to IPF live updates | [dxf_instrument_profile_live_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_instrument_profile_live_sample) | *Q4’2023*, please see [TBD](#future-development) section |
| 5 | How to subscribe to `Order`, `SpreadOrder`, `Candle`, `TimeAndSale`, `Greeks`, `Series` snapshots | [dxf_snapshot_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_snapshot_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 6 | How to subscribe to depth of market | [dxf_price_level_book_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_price_level_book_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 7 | How to receive snapshots of `TimeAndSale`, `Candle`, `Series`, `Greeks` events on a given time interval without live subscription | [dxf_simple_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_simple_data_retrieving_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 8 | How to subscribe to order snapshot with incremental updates | [dxf_inc_order_snapshot_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_inc_order_snapshot_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 9 | How to retrieve `Candle` data from the candle web service | [dxf_candle_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_candle_data_retrieving_sample) | *Q4’2024*, please see [TBD](#future-development) section |
| 10 | How to retrieve `TimeAndSale` data from the candle web service | [dxf_tns_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_tns_data_retrieving_sample) | *Q4’2024*, please see [TBD](#future-development) section |
| # | Sample | Old Version | New Version |
|:--:|:----------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------|
| 1 | How to subscribe to `Quote`, `Trade`, `TradeETH`, `Order`, `SpreadOrder`, `AnalyticOrder`, `TimeAndSale` events | [dxf_events_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_events_sample) | [DxFeed.Graal.Net.Samples.DxFeedConnect](samples/DxFeedConnect) |
| 2 | How to subscribe to `Candle` event | [dxf_candle_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_candle_sample) | [DxFeed.Graal.Net.Samples.CandleSample](samples/CandleSample) |
| 3 | How to receive IPF data from URL or file | [dxf_instrument_profile_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_instrument_profile_sample) | [DxFeed.Graal.Net.Samples.DxFeedIpfConnect](samples/DxFeedIpfConnect) |
| 4 | How to subscribe to IPF live updates | [dxf_instrument_profile_live_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_instrument_profile_live_sample) | [DxFeed.Graal.Net.Samples.DxFeedLiveIpfSample](samples/DxFeedLiveIpfSample) |
| 5 | How to subscribe to `Order`, `SpreadOrder`, `Candle`, `TimeAndSale`, `Greeks`, `Series` snapshots | [dxf_snapshot_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_snapshot_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 6 | How to subscribe to depth of market | [dxf_price_level_book_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_price_level_book_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 7 | How to receive snapshots of `TimeAndSale`, `Candle`, `Series`, `Greeks` events on a given time interval without live subscription | [dxf_simple_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_simple_data_retrieving_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 8 | How to subscribe to order snapshot with incremental updates | [dxf_inc_order_snapshot_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_inc_order_snapshot_sample) | *Q2’2024*, please see [TBD](#future-development) section |
| 9 | How to retrieve `Candle` data from the candle web service | [dxf_candle_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_candle_data_retrieving_sample) | *Q4’2024*, please see [TBD](#future-development) section |
| 10 | How to retrieve `TimeAndSale` data from the candle web service | [dxf_tns_data_retrieving_sample](https://github.com/dxFeed/dxfeed-net-api/tree/master/samples/dxf_tns_data_retrieving_sample) | *Q4’2024*, please see [TBD](#future-development) section |

### Implementation Details

Expand Down Expand Up @@ -495,7 +495,7 @@ sudo /usr/bin/xattr -r -d com.apple.quarantine <directory_with_tools>
represents basic profile information about a market instrument
([Java API sample](https://github.com/devexperts/QD/blob/master/dxfeed-samples/src/main/java/com/dxfeed/sample/ipf/DXFeedIpfConnect.java))

- [ ] [InstrumentProfileCollector](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/ipf/live/InstrumentProfileCollector.html)
- [x] [InstrumentProfileCollector](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/ipf/live/InstrumentProfileCollector.html)
collects instrument profile updates and provides the live instrument profiles list
([Java API sample](https://github.com/devexperts/QD/blob/master/dxfeed-samples/src/main/java/com/dxfeed/sample/ipf/DXFeedLiveIpfSample.java))

Expand Down
3 changes: 3 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## Version 0.6.0
* Feature: Add IpfConnection

## Version 0.5.0

## What's Changed
Expand Down
9 changes: 8 additions & 1 deletion dxfeed-graal-net-api.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DxFeedSample", "samples\DxF
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CandleSample", "samples\CandleSample\CandleSample.csproj", "{CECAB17A-9DBE-4A4E-8556-5747AB170714}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DXFeedIpfConnect", "samples\DXFeedIpfConnect\DXFeedIpfConnect.csproj", "{62206DAF-999F-437A-AC18-1217ED14EB52}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DxFeedIpfConnect", "samples\DxFeedIpfConnect\DxFeedIpfConnect.csproj", "{62206DAF-999F-437A-AC18-1217ED14EB52}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DxFeedLiveIpfSample", "samples\DxFeedLiveIpfSample\DxFeedLiveIpfSample.csproj", "{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -76,6 +78,10 @@ Global
{62206DAF-999F-437A-AC18-1217ED14EB52}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62206DAF-999F-437A-AC18-1217ED14EB52}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62206DAF-999F-437A-AC18-1217ED14EB52}.Release|Any CPU.Build.0 = Release|Any CPU
{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{73597E04-D8A8-4991-A759-7F886CBE2A8F} = {C4490D74-2970-4A1B-8178-A724A06B140A}
Expand All @@ -87,5 +93,6 @@ Global
{ECD5E041-0FBF-475E-82A6-DE6384EF25A0} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{CECAB17A-9DBE-4A4E-8556-5747AB170714} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{62206DAF-999F-437A-AC18-1217ED14EB52} = {C4490D74-2970-4A1B-8178-A724A06B140A}
{C2F0FF7C-4675-4D5F-AE90-0E8DA33A1EB8} = {C4490D74-2970-4A1B-8178-A724A06B140A}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>../../artifacts/Debug/Samples/DXFeedIpfConnect/</OutputPath>
<OutputPath>../../artifacts/Debug/Samples/DxFeedIpfConnect/</OutputPath>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>../../artifacts/Release/Samples/DXFeedIpfConnect/</OutputPath>
<OutputPath>../../artifacts/Release/Samples/DxFeedIpfConnect/</OutputPath>
</PropertyGroup>

<ItemGroup>
Expand Down
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions samples/DxFeedLiveIpfSample/DxFeedLiveIpfSample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>DxFeed.Graal.Net.Samples</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>../../artifacts/Debug/Samples/DxFeedLiveIpfSample/</OutputPath>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>../../artifacts/Release/Samples/DxFeedLiveIpfSample/</OutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\DxFeed.Graal.Net\DxFeed.Graal.Net.csproj" />
</ItemGroup>
</Project>
65 changes: 65 additions & 0 deletions samples/DxFeedLiveIpfSample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// <copyright file="Program.cs" company="Devexperts LLC">
// Copyright © 2022 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.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using DxFeed.Graal.Net.Ipf;
using DxFeed.Graal.Net.Ipf.Live;

namespace DxFeed.Graal.Net.Samples;

internal abstract class Program
{
private static readonly string DXFEED_IPF_URL = "https://demo:[email protected]/ipf";

public static async Task Main(string[] args)
{
if (args.Length > 1) {
Console.WriteLine("usage: DXFeedLiveIpfSample [<ipf-url>]");
Console.WriteLine("where: <ipf-url> is URL for the instruments profiles, default: " + DXFEED_IPF_URL);
return;
}

var url = (args.Length > 0) ? args[0] : DXFEED_IPF_URL;

var collector = new InstrumentProfileCollector();
var connection = InstrumentProfileConnection.CreateConnection(url, collector);
// Update period can be used to re-read IPF files, not needed for services supporting IPF "live-update"
connection.SetUpdatePeriod(60_000L);
connection.Start();

// Data model to keep all instrument profiles mapped by their ticker symbol
var profiles = new ConcurrentDictionary<string, InstrumentProfile>();

// It is possible to add listener after connection is started - updates will not be missed in this case
collector.AddUpdateListener(instruments =>
{
Console.WriteLine("\nInstrument Profiles:");
// We can observe REMOVED elements - need to add necessary filtering
// See javadoc for InstrumentProfileCollector for more details

// (1) We can either process instrument profile updates manually
instruments.ForEach(profile =>
{
if (InstrumentProfileType.REMOVED.Name.Equals(profile.GetType().Name, StringComparison.Ordinal)) {
// Profile was removed - remove it from our data model
profiles.Remove(profile.Symbol, out _);
} else {
// Profile was updated - collector only notifies us if profile was changed
profiles.TryAdd(profile.Symbol, profile);
}
});
Console.WriteLine("Total number of profiles (1): " + profiles.Count);
Console.WriteLine("Last modified: " + DateTimeOffset.FromUnixTimeMilliseconds(collector.GetLastUpdateTime()));
});


await Task.Delay(Timeout.Infinite);
}
}
63 changes: 63 additions & 0 deletions src/DxFeed.Graal.Net/Ipf/Live/InstrumentProfileCollector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// <copyright file="InstrumentProfileCollector.cs" company="Devexperts LLC">
// Copyright © 2022 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.Collections.Generic;
using DxFeed.Graal.Net.Native.Ipf;

namespace DxFeed.Graal.Net.Ipf.Live;

/// <summary>
/// Collects instrument profile updates and provides the live list of instrument profiles.
/// This class contains a map that keeps a unique instrument profile per symbol.
/// This class is intended to be used with InstrumentProfileConnection as a repository
/// that keeps profiles of all known instruments.
/// As set of instrument profiles stored in this collector can be accessed with view method.
/// A snapshot plus a live stream of updates can be accessed with addUpdateListener method.
/// Removal of instrument profile is represented by an InstrumentProfile instance
/// with a type equal to InstrumentProfileType.REMOVED.
/// </summary>
public class InstrumentProfileCollector
{
private readonly InstrumentProfileCollectorHandle handle = InstrumentProfileCollectorHandle.Create();

/// <summary>
/// Gets last modification time (in milliseconds) of instrument profiles or zero if it is unknown.
/// Note, that while the time is represented in milliseconds, the actual granularity of time here is a second.
/// </summary>
/// <returns>Last modification time (in milliseconds) of instrument profiles or zero if it is unknown.</returns>
public long GetLastUpdateTime() =>
handle.GetLastUpdateTime();

/// <summary>
/// Gets a concurrent view of the set of instrument profiles.
/// Note, that removal of instrument profile is represented by an <see cref="InstrumentProfile"/> instance with a
/// <see cref="InstrumentProfileType"/> equal to
/// <c>InstrumentProfileType.REMOVED</c>
/// Normally, this view exposes only non-removed profiles. However, if iteration is concurrent with removal,
/// then a removed instrument profile (with a removed type) can be exposed by this view.
/// </summary>
/// <returns>A concurrent view of the set of instrument profiles.</returns>
public IEnumerable<InstrumentProfile> View() =>
handle.View();

/// <summary>
/// Adds listener that is notified about any updates in the set of instrument profiles.
/// If a set of instrument profiles is not empty, then this listener will be immediately notified.
/// </summary>
/// <param name="listener">The profile update listener.</param>
public void AddUpdateListener(InstrumentProfileUpdateListener listener) =>
handle.AddUpdateListener(listener);

/// <summary>
/// Removes listener that is notified about any updates in the set of instrument profiles.
/// </summary>
/// <param name="listener">The profile update listener.</param>
public void RemoveUpdateListener(InstrumentProfileUpdateListener listener) =>
handle.RemoveUpdateListener(listener);

internal InstrumentProfileCollectorHandle GetHandle() =>
handle;
}
Loading

0 comments on commit 4662888

Please sign in to comment.