dxFeed / dxfeed-graal-net-api

For .NET developers, this library offers easy access to dxFeed market data. Built upon the GraalVM Native Image and our flagship dxFeed Java API, it provides a seamless experience for .NET-based applications
Mozilla Public License 2.0
11 stars 6 forks source link
api dxfeed market-data
light

This package provides access to dxFeed market data. The library is built as a language-specific wrapper over the dxFeed Graal Native library, which was compiled with GraalVM Native Image and dxFeed Java API (our flagman API).

:information_source: If you already use dxFeed .NET API, please see the Overview section.

Build CodeQL Platform NET Release Nuget License

Table of Contents

Overview

Reasons for the New .NET API Repository

The old version of dxFeed .NET API is built as a thin wrapper over dxFeed C API, which has several architectural restrictions that prevent us from providing a state-of-the-art technological solution.

Benefits of the New Version

Milestones

Feature development has already stopped for the old version of dxFeed .NET API.

The old version will be considered deprecated, and at the end of 2024, we plan to end the service. If you’re already our customer and have difficulty with a future transition, please contact us via our customer portal.

Migration

To help you rewrite the existing API calls, we’ve prepared samples demonstrating how to work with the new API and how several functionalities are implemented. More examples will follow. The table below shows the sample mapping between the old and new versions.

Our support team on our customer portal is ready to answer any questions and help with the transition.

Sample Mapping

# Sample Old Version New Version
1 How to get Instrument Profiles dxf_ipf_connect_sample IpfSample
2 How to get live updates for Instrument Profiles dxf_instrument_profile_live_sample IpfLiveSample
3 How to subscribe to Order, SpreadOrder, Candle, TimeAndSale, Greeks, Series snapshots dxf_snapshot_sample Q4’2024, please see TBD section
4 How to subscribe to depth of market dxf_price_level_book_sample PriceLevelBookSample
5 How to receive snapshots of TimeAndSale, Candle, Series, Greeks events on a given time interval without live subscription dxf_simple_data_retrieving_sample FetchDailyCandlesSample
6 How to subscribe to order snapshot with incremental updates dxf_inc_order_snapshot_sample IncOrderSnapshotSample
7 How to retrieve Candle data from the candle web service dxf_candle_data_retrieving_sample CandleDataSample
8 How to retrieve TimeAndSale data from the candle web service dxf_tns_data_retrieving_sample CandleDataSample

Implementation Details

We use GraalVM Native Image technology and specially written code that wraps Java methods into native ones to get dynamically linked libraries for different platforms (Linux, macOS, and Windows) based on the latest Java API package.

Then, the resulting dynamic link library (dxFeed Graal-native) is used through C ABI (application binary interface), and we write programming interfaces that describe our business model (similar to Java API).

As a result, we get a full-featured, similar performance as with Java API. Regardless of the language, writing the final application logic using API calls will be very similar (only the syntax will be amended, "best practices", specific language restrictions).

Below is a scheme of this process:

light

Architectural Restrictions and Other Limitations of the Old Version

# Limitation How It’s Solved in the New Version
1 Windows support only Windows-x64, Linux-x64, macOS-x64, macOS-arm64 support by .NET
2 Single-threaded architecture limiting throughput Based on the Java API, each subscription object (DXFeedSubscription) can run on its own thread
3 User code in event callbacks (for example, OnQuote) is executed in the socket read thread, which can significantly reduce throughput Socket processing threads and callback threads are separated
4 In event callbacks, one market event type and one data portion always arrive (excluding snapshot subscription), which increases the load on the CPU with a large amount of incoming data Event callbacks can receive different market event types, and more than one by batch
5 It’s impossible to subscribe to data without getting regionals (if it is available for the market event) or only for a certain regional subscription.AddSymbols("AAPL"); - composite
subscription.AddSymbols("AAPL&Q"); - regional
6 It’s impossible to subscribe to Order event (excluding snapshot subscription) without getting: all sources, Order by Quote (including regionals), Order by MarketMaker subscription.AddSymbols(new IndexedEventSubscriptionSymbol("AAPL", OrderSource.NTV)); - [Order.Source]() determines which data is being subscribed to
7 Data is mixed up when creating two subscriptions (regular and time series) for the same market event type. Both regular and time series data go to both subscriptions Each subscription instance receives only the data requested
8 Each subsequent request for the same symbol set in a subscription instance overwrites the existing one in another subscription instance Subscription instances and the data they receive are independent of each other
9 Removing a symbol from one subscription instance caused it to be removed from all others Subscription instances and the data they receive are independent of each other
10 Incorrect behavior when reading from a file (if a market event in the file hasn’t been subscribed to). Reading from a file always occurs at maximum speed. The supported format is binary only endpoint.Connect(@"file:tape.txt[format=text]"); - processing a text file with at it's "real" speed by timestamps
endpoint.Connect(@"file:tape.bin[format=binary,speed=max]"); - processing a binary file with max speed

Documentation

Find useful information in our self-service dxFeed Knowledge Base or .NET API documentation:

Requirements

Windows

Only x64 versions are supported.

OS Version Architectures
Windows 8, 8.1 x64
Windows 10 Version 1607+ x64
Windows 11 Version 22000+ x64
Windows Server 2012+ x64
Windows Server Core 2012+ x64
Nano Server Version 1809+ x64

Requirements

Linux

Only x64 versions are supported.

Requirements

Libc compatibility

Libpthread compatibility

A symlink on libpthread.so, libpthread.so.0, or libcoreclr.so must exist.

macOS

OS Version Architectures
macOS 10.15+ x64
macOS 11+ Arm64

Is supported in the Rosetta 2 x64 emulator.

Requirements

Installation

Add the following package source to your NuGet.Config file.

For Linux and macOS:

The NuGet.Config file is usually located at ~/.config/NuGet/NuGet.Config.

For Windows:

The NuGet.Config file is usually located at %appdata%\NuGet\NuGet.Config.

An example of what this file might look like:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <packageSources>
        <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3"/>
        <add key="dxFeed" value="https://dxfeed.jfrog.io/artifactory/api/nuget/v3/nuget-open" protocolVersion="3"/>
    </packageSources>
</configuration>

Then add the DxFeed.Graal.Net package to your project using the NuGet package manager.

Using Visual Studio:

  1. Open your solution in Visual Studio.
  2. Right-click on the project in Solution Explorer and select Manage NuGet Packages.
  3. Switch to the Browse tab, select the dxFeed source, and search for DxFeed.Graal.Net.
  4. Click Install to add the package to your project.

Using JetBrains Rider:

  1. Open your solution in JetBrains Rider.
  2. Right-click on the project in the Solution and select Manage NuGet Packages.
  3. Switch to the Packages tab, select the dxFeed source, and search for DxFeed.Graal.Net.
  4. Right-click on the package and select Install to add the package to your project.

If you are using .NET Framework and building for platform target AnyCPU, be sure to uncheck Prefer 32-bit in Properties->Buildfor the project. We only support 64-bit builds.

Using VSCode:

  1. Create a new project: dotnet new console --framework net6.0 --use-program-main
  2. Add the DxFeed.Graal.Net package to your project: dotnet add package DxFeed.Graal.Net
  3. Copy and paste the following code into the Program.cs file:
using DxFeed.Graal.Net.Api;
using DxFeed.Graal.Net.Events.Market;

namespace sandbox;

internal abstract class Program
{
    public static async Task Main(string[] args)
    {
        var address = "demo.dxfeed.com:7300";
        var symbol = "AAPL";
        var sub = DXEndpoint.GetInstance().Connect(address).GetFeed().CreateSubscription(typeof(Quote));
        sub.AddEventListener(events =>
        {
            foreach (var quote in events)
            {
                Console.WriteLine(quote);
            }
        });
        sub.AddSymbols(symbol);
        await Task.Delay(Timeout.Infinite);
    }
}
  1. Run project: dotnet run
  2. Add C# support to VSCode by following the instructions here
  3. You can now open this directory in VSCode

Usage

How to connect to QD endpoint

using System;
using DxFeed.Graal.Net.Api;
using DxFeed.Graal.Net.Events.Market;

// For token-based authorization, use the following address format:
// "demo.dxfeed.com:7300[login=entitle:token]"
using var endpoint = DXEndpoint.Create().Connect("demo.dxfeed.com:7300");
using var subscription = endpoint.GetFeed().CreateSubscription(typeof(Quote));
subscription.AddEventListener(events =>
{
    foreach (var e in events)
    {
        Console.WriteLine(e);
    }
});
subscription.AddSymbols("AAPL");
Console.ReadKey();
Output
``` I 231130 141419.914 [main] QD - Using QDS-3.325+file-UNKNOWN, (C) Devexperts I 231130 141419.925 [main] QD - Using scheme com.dxfeed.api.impl.DXFeedScheme slfwemJduh1J7ibvy9oo8DABTNhNALFQfw0KmE40CMI I 231130 141419.934 [main] MARS - Started time synchronization tracker using multicast 239.192.51.45:5145 with SFmog I 231130 141419.937 [main] MARS - Started JVM self-monitoring I 231130 141419.938 [main] QD - qdnet with collectors [Ticker, Stream, History] I 231130 141419.950 [main] ClientSocket-Distributor - Starting ClientSocketConnector to demo.dxfeed.com:7300 I 231130 141419.950 [demo.dxfeed.com:7300-Reader] ClientSocketConnector - Resolving IPs for demo.dxfeed.com I 231130 141419.951 [demo.dxfeed.com:7300-Reader] ClientSocketConnector - Connecting to 208.93.103.170:7300 I 231130 141420.099 [demo.dxfeed.com:7300-Reader] ClientSocketConnector - Connected to 208.93.103.170:7300 D 231130 141420.246 [demo.dxfeed.com:7300-Reader] QD - Distributor received protocol descriptor multiplexor@fFLro [type=qtp, version=QDS-3.319, opt=hs, mars.root=mdd.demo-amazon.multiplexor-demo1] sending [TICKER, STREAM, HISTORY, DATA] from 208.93.103.170 Quote{AAPL, eventTime=0, time=20231130-135604.000+03:00, timeNanoPart=0, sequence=0, bidTime=20231130-135548+03:00, bidExchange=Q, bidPrice=189.43, bidSize=3, askTime=20231130-135604+03:00, askExchange=Q, askPrice=189.49, askSize=1} ```

How to connect to dxLink

using System;
using DxFeed.Graal.Net;
using DxFeed.Graal.Net.Api;
using DxFeed.Graal.Net.Events.Market;

// Enable experimental feature.
SystemProperty.SetProperty("dxfeed.experimental.dxlink.enable", "true");
// Set scheme for dxLink.
SystemProperty.SetProperty("scheme", "ext:opt:sysprops,resource:dxlink.xml");

// For token-based authorization, use the following address format:
// "dxlink:wss://demo.dxfeed.com/dxlink-ws[login=dxlink:token]"
using var endpoint = DXEndpoint.Create().Connect("dxlink:wss://demo.dxfeed.com/dxlink-ws");
using var subscription = endpoint.GetFeed().CreateSubscription(typeof(Quote));
subscription.AddEventListener(events =>
{
    foreach (var e in events)
    {
        Console.WriteLine(e);
    }
});
subscription.AddSymbols("AAPL");
Console.ReadKey();
Output
``` I 231130 141308.314 [main] QD - Using QDS-3.325+file-UNKNOWN, (C) Devexperts I 231130 141308.326 [main] QD - Using scheme com.dxfeed.api.impl.DXFeedScheme slfwemJduh1J7ibvy9oo8DABTNhNALFQfw0KmE40CMI I 231130 141308.351 [main] MARS - Started time synchronization tracker using multicast 239.192.51.45:5145 with DgKtZ I 231130 141308.358 [main] MARS - Started JVM self-monitoring I 231130 141308.359 [main] QD - qdnet with collectors [Ticker, Stream, History] I 231130 141308.384 [main] DxLinkClientWebSocket-Distributor - Starting DxLinkClientWebSocketConnector to wss://demo.dxfeed.com/dxlink-ws SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. I 231130 141308.392 [wss://demo.dxfeed.com/dxlink-ws-Writer] DxLinkClientWebSocket-Distributor - Connecting to wss://demo.dxfeed.com/dxlink-ws I 231130 141308.938 [wss://demo.dxfeed.com/dxlink-ws-Writer] DxLinkClientWebSocket-Distributor - Connected to wss://demo.dxfeed.com/dxlink-ws D 231130 141310.105 [oioEventLoopGroup-2-1] QD - Distributor received protocol descriptor [type=dxlink, version=0.1-0.18-20231017-133150, keepaliveTimeout=120, acceptKeepaliveTimeout=5] sending [] from wss://demo.dxfeed.com/dxlink-ws D 231130 141310.106 [oioEventLoopGroup-2-1] QD - Distributor received protocol descriptor [type=dxlink, version=0.1-0.18-20231017-133150, keepaliveTimeout=120, acceptKeepaliveTimeout=5, authentication=] sending [] from wss://demo.dxfeed.com/dxlink-ws Quote{AAPL, eventTime=0, time=20231130-135604.000+03:00, timeNanoPart=0, sequence=0, bidTime=20231130-135548+03:00, bidExchange=Q, bidPrice=189.43, bidSize=3, askTime=20231130-135604+03:00, askExchange=Q, askPrice=189.49, askSize=1} ```

To familiarize with the dxLink protocol, please click here.

Tools

Tools is a collection of utilities that allow you to subscribe to various market events for the specified symbols. The tools can be downloaded from Release (including self-contained versions, that do not require .NET installation):

To run tools on macOS, it may be necessary to unquarantine them:

sudo /usr/bin/xattr -r -d com.apple.quarantine <directory_with_tools>

Samples

API

Candle

Console

File

IPF

Model

Schedule

UI

Current State

Endpoint Roles

Event Types

Subscription Symbols

Subscriptions & Models

IPF & Schedule