Skip to content

Commit

Permalink
[MDAPI-96] [.NET] Retrieve latest events from feed
Browse files Browse the repository at this point in the history
  • Loading branch information
Konstantin Ivaschenko committed Oct 22, 2024
1 parent f191683 commit a5a5859
Show file tree
Hide file tree
Showing 24 changed files with 531 additions and 198 deletions.
2 changes: 2 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* [MDAPI-96] [.NET] Retrieve latest events from feed

## Version 2.5.2

* [MDAPI-165] [.NET] DxFeed.Graal.Net.Schedules.GetNextSession does not return null if no session exists
Expand Down
82 changes: 81 additions & 1 deletion src/DxFeed.Graal.Net/Api/DXFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DxFeed.Graal.Net.Api.Osub;
using DxFeed.Graal.Net.Events;
using DxFeed.Graal.Net.Native.Feed;
using DxFeed.Graal.Net.Utils;
Expand Down Expand Up @@ -78,10 +79,89 @@ public DXFeedSubscription CreateSubscription(params Type[] eventTypes)
public DXFeedSubscription CreateSubscription(IEnumerable<Type> eventTypes) =>
CreateSubscription(eventTypes.ToArray());

/// <summary>
/// Returns the last event for the specified event instance.
/// This method works only for event types that implement <see cref="ILastingEvent"/> marker interface.
/// This method <b>does not</b> make any remote calls to the uplink data provider.
/// It just retrieves last received event from the local cache of this feed.
/// The events are stored in the cache only if there is some
/// attached <see cref="DXFeedSubscription"/> that is subscribed to the corresponding symbol and event type.
/// <see cref="WildcardSymbol.All"/> subscription does not count for that purpose.
///
/// <p>Use <see cref="GetLastEventAsync{T}"/> method
/// if an event needs to be requested in the absence of subscription.</p>
///
/// <p>This method fills in the values for the last event into the <c>event</c> argument.
/// If the last event is not available for any reason (no subscription, no connection to uplink, etc).
/// then the event object is not changed.
/// This method always returns the same <c>event</c> instance that is passed to it as an argument.</p>
///
/// <p>This method provides no way to distinguish a case when there is no subscription from the case when
/// there is a subscription, but the event data have not arrived yet. It is recommended to use
/// <see cref="GetLasEventIfSubscribed{TE}"/> method
/// instead of this <c>GetLastEvent</c> method to fail-fast in case when the subscription was supposed to be
/// set by the logic of the code, since <see cref="GetLasEventIfSubscribed{TE}"/>
/// method returns null when there is no subscription.</p>
///
/// <p>Note, that this method does not work when <see cref="DXEndpoint"/> was created with
/// <see cref="DXEndpoint.Role.StreamFeed"/> role (never fills in the event).</p>
///
/// </summary>
/// <param name="e">The event.</param>
/// <typeparam name="TE">The type of event.</typeparam>
/// <returns>The same event.</returns>
public TE GetLastEvent<TE>(TE e)
where TE : ILastingEvent =>
_feedNative.GetLastEvent(e);

/// <summary>
/// Returns the last events for the specified list of event instances.
/// This is a bulk version of <see cref="GetLastEvent{TE}"/> method.
///
/// <p>Note, that this method does not work when <see cref="DXEndpoint"/> was created with
/// <see cref="DXEndpoint.Role.StreamFeed"/> role (never fills in the event).</p>
///
/// </summary>
/// <param name="events">The collection of events.</param>
/// <typeparam name="TE">The type of event.</typeparam>
/// <returns>The same collection of events.</returns>
public IList<TE> GetLastEvents<TE>(IList<TE> events)
where TE : ILastingEvent =>
_feedNative.GetLastEvents(events);

/// <summary>
/// Returns the last event for the specified event type and symbol if there is a subscription for it.
/// This method works only for event types that implement <see cref="ILastingEvent"/> marker interface.
/// This method <b>does not</b> make any remote calls to the uplink data provider.
/// It just retrieves last received event from the local cache of this feed.
/// The events are stored in the cache only if there is some
/// attached <see cref="DXFeedSubscription"/> that is subscribed to the corresponding event type and symbol.
/// The subscription can also be permanently defined using <see cref="DXEndpoint"/> properties.
/// <see cref="WildcardSymbol.All"/> subscription does not count for that purpose.
/// If there is no subscription, then this method returns null.
///
/// <p>If there is a subscription, but the event has not arrived from the uplink data provider,
/// this method returns an non-initialized event object: its <see cref="GetLastEvent{TE}"/>
/// property is set to the requested symbol, but all the other properties have their default values.</p>
///
/// <p>Use <see cref="GetLastEventAsync{T}"/> method
/// if an event needs to be requested in the absence of subscription.</p>
///
/// <p>Note, that this method does not work when <see cref="DXEndpoint"/> was created with
/// <see cref="DXEndpoint.Role.StreamFeed"/> role (never fills in the event).</p>
///
/// </summary>
/// <param name="symbol">The symbol.</param>
/// <typeparam name="TE">The event type.</typeparam>
/// <returns>The event or null if there is no subscription for the specified event type and symbol.</returns>
public TE? GetLasEventIfSubscribed<TE>(object symbol)
where TE : ILastingEvent =>
_feedNative.GetLastEventIfSubscribed<TE>(symbol);

/// <summary>
/// Requests the last event for the specified event type and symbol.
/// This method works only for event types that implement <see cref="ILastingEvent"/> marker interface.
/// This method requests the data from the the uplink data provider,
/// This method requests the data from the uplink data provider,
/// creates new event of the specified event type,
/// and <see cref="Task{TResult}.Result"/> the resulting task with this event.
/// </summary>
Expand Down
40 changes: 25 additions & 15 deletions src/DxFeed.Graal.Net/Native/Events/Candles/CandleMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="CandleMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand All @@ -17,25 +17,16 @@ public override unsafe IEventType FromNative(EventTypeNative* eventType) =>
public override unsafe EventTypeNative* ToNative(IEventType eventType) =>
(EventTypeNative*)Convert((Candle)eventType);

public override unsafe IEventType FillFromNative(EventTypeNative* nativeEventType, IEventType eventType) =>
Fill((CandleNative*)nativeEventType, (Candle)eventType);

public override unsafe void Release(EventTypeNative* eventType) =>
ReleaseEventType(eventType);

protected override unsafe Candle Convert(CandleNative* eventType)
{
var candle = CreateEventType(eventType);
candle.EventFlags = eventType->EventFlags;
candle.Index = eventType->Index;
candle.Count = eventType->Count;
candle.Open = eventType->Open;
candle.High = eventType->High;
candle.Low = eventType->Low;
candle.Close = eventType->Close;
candle.Volume = eventType->Volume;
candle.VWAP = eventType->VWAP;
candle.BidVolume = eventType->BidVolume;
candle.AskVolume = eventType->AskVolume;
candle.ImpVolatility = eventType->ImpVolatility;
candle.OpenInterest = eventType->OpenInterest;
var candle = new Candle();
Fill(eventType, candle);
return candle;
}

Expand All @@ -61,4 +52,23 @@ protected override unsafe Candle Convert(CandleNative* eventType)
};
return ptr;
}

private static unsafe Candle Fill(CandleNative* eventType, Candle candle)
{
AssignEventType((EventTypeNative*)eventType, candle);
candle.EventFlags = eventType->EventFlags;
candle.Index = eventType->Index;
candle.Count = eventType->Count;
candle.Open = eventType->Open;
candle.High = eventType->High;
candle.Low = eventType->Low;
candle.Close = eventType->Close;
candle.Volume = eventType->Volume;
candle.VWAP = eventType->VWAP;
candle.BidVolume = eventType->BidVolume;
candle.AskVolume = eventType->AskVolume;
candle.ImpVolatility = eventType->ImpVolatility;
candle.OpenInterest = eventType->OpenInterest;
return candle;
}
}
5 changes: 4 additions & 1 deletion src/DxFeed.Graal.Net/Native/Events/EventMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="EventMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand Down Expand Up @@ -80,6 +80,9 @@ public static unsafe ICollection<IEventType> FromNative(EventTypeNative** eventT
public static unsafe IEventType FromNative(EventTypeNative* eventTypeNative) =>
GetEventMapperByEventCode(eventTypeNative->EventCode).FromNative(eventTypeNative);

public static unsafe IEventType FillFromNative(EventTypeNative* eventTypeNative, IEventType eventType) =>
GetEventMapperByEventCode(eventTypeNative->EventCode).FillFromNative(eventTypeNative, eventType);

public static unsafe EventTypeNative* ToNative(IEventType eventType) =>
GetEventMapperByEventCode(eventType).ToNative(eventType);

Expand Down
23 changes: 10 additions & 13 deletions src/DxFeed.Graal.Net/Native/Events/EventTypeMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="EventTypeMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand Down Expand Up @@ -28,6 +28,9 @@ internal abstract class EventTypeMapper<TEventType, TEventTypeNative> : IEventMa
/// <inheritdoc/>
public abstract unsafe EventTypeNative* ToNative(IEventType eventType);

/// <inheritdoc/>
public abstract unsafe IEventType FillFromNative(EventTypeNative* nativeEventType, IEventType eventType);

/// <inheritdoc/>
public abstract unsafe void Release(EventTypeNative* eventType);

Expand All @@ -50,18 +53,12 @@ protected static EventTypeNative CreateEventType(TEventType eventType) =>
protected static EventTypeNative CreateEventType(EventCodeNative eventCode, TEventType eventType) =>
new() { EventCode = eventCode, EventSymbol = eventType.EventSymbol, EventTime = eventType.EventTime, };

/// <inheritdoc cref="CreateEventType(EventTypeNative*)"/>
protected static unsafe TEventType CreateEventType(TEventTypeNative* eventType) =>
CreateEventType((EventTypeNative*)eventType);

/// <summary>
/// Creates the specified TEventType from <see cref="EventTypeNative"/>.
/// Populates only the fields contained in <see cref="IEventType"/>.
/// </summary>
/// <param name="eventType">The <see cref="EventTypeNative"/>.</param>
/// <returns>The created TEventType.</returns>
protected static unsafe TEventType CreateEventType(EventTypeNative* eventType) =>
new() { EventSymbol = eventType->EventSymbol, EventTime = eventType->EventTime, };
protected static unsafe TEventType AssignEventType(EventTypeNative* eventTypeNative, TEventType eventType)
{
eventType.EventSymbol = eventTypeNative->EventSymbol;
eventType.EventTime = eventTypeNative->EventTime;
return eventType;
}

/// <summary>
/// Allocates an unmanaged pointer with type and size TEventTypeNative.
Expand Down
10 changes: 9 additions & 1 deletion src/DxFeed.Graal.Net/Native/Events/IEventMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="IEventMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand Down Expand Up @@ -35,6 +35,14 @@ internal interface IEventMapper
/// </returns>
unsafe EventTypeNative* ToNative(IEventType eventType);

/// <summary>
/// Populates an existing managed event type instance with data from a native event type.
/// </summary>
/// <param name="nativeEventType">An unsafe pointer to a native <see cref="EventTypeNative"/> instance.</param>
/// <param name="eventType">The managed <see cref="IEventType"/> instance to populate.</param>
/// <returns>The populated <see cref="IEventType"/> instance.</returns>
public unsafe IEventType FillFromNative(EventTypeNative* nativeEventType, IEventType eventType);

/// <summary>
/// Releases all associated resources.
/// This method released unmanaged memory allocated by <see cref="ToNative"/>.
Expand Down
24 changes: 17 additions & 7 deletions src/DxFeed.Graal.Net/Native/Events/Market/AnalyticOrderMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="AnalyticOrderMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand All @@ -19,17 +19,16 @@ public override unsafe IEventType FromNative(EventTypeNative* eventType) =>
public override unsafe EventTypeNative* ToNative(IEventType eventType) =>
(EventTypeNative*)Convert((AnalyticOrder)eventType);

public override unsafe IEventType FillFromNative(EventTypeNative* nativeEventType, IEventType eventType) =>
Fill((AnalyticOrderNative*)nativeEventType, (AnalyticOrder)eventType);

public override unsafe void Release(EventTypeNative* eventType) =>
OrderMapper.Release(eventType);

protected override unsafe AnalyticOrder Convert(AnalyticOrderNative* eventType)
{
var analyticOrder = CreateOrderBase((OrderBaseNative*)eventType);
analyticOrder.MarketMaker = eventType->Order.MarketMaker;
analyticOrder.IcebergPeakSize = eventType->IcebergPeakSize;
analyticOrder.IcebergHiddenSize = eventType->IcebergHiddenSize;
analyticOrder.IcebergExecutedSize = eventType->IcebergExecutedSize;
analyticOrder.IcebergFlags = eventType->IcebergFlags;
var analyticOrder = new AnalyticOrder();
Fill(eventType, analyticOrder);
return analyticOrder;
}

Expand All @@ -46,4 +45,15 @@ protected override unsafe AnalyticOrder Convert(AnalyticOrderNative* eventType)
};
return ptr;
}

private static unsafe AnalyticOrder Fill(AnalyticOrderNative* eventType, AnalyticOrder analyticOrder)
{
AssignOrderBase((OrderBaseNative*)eventType, analyticOrder);
analyticOrder.MarketMaker = eventType->Order.MarketMaker;
analyticOrder.IcebergPeakSize = eventType->IcebergPeakSize;
analyticOrder.IcebergHiddenSize = eventType->IcebergHiddenSize;
analyticOrder.IcebergExecutedSize = eventType->IcebergExecutedSize;
analyticOrder.IcebergFlags = eventType->IcebergFlags;
return analyticOrder;
}
}
44 changes: 27 additions & 17 deletions src/DxFeed.Graal.Net/Native/Events/Market/OptionSaleMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="OptionSaleMapper.cs" company="Devexperts LLC">
// Copyright © 2022 Devexperts LLC. All rights reserved.
// 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>
Expand All @@ -17,6 +17,9 @@ public override unsafe IEventType FromNative(EventTypeNative* eventType) =>
public override unsafe EventTypeNative* ToNative(IEventType eventType) =>
(EventTypeNative*)Convert((OptionSale)eventType);

public override unsafe IEventType FillFromNative(EventTypeNative* nativeEventType, IEventType eventType) =>
Fill((OptionSaleNative*)nativeEventType, (OptionSale)eventType);

public override unsafe void Release(EventTypeNative* eventType)
{
if (eventType == (EventTypeNative*)0)
Expand All @@ -32,22 +35,8 @@ public override unsafe void Release(EventTypeNative* eventType)

protected override unsafe OptionSale Convert(OptionSaleNative* eventType)
{
var optionSale = CreateEventType(eventType);
optionSale.EventFlags = eventType->EventFlags;
optionSale.Index = eventType->Index;
optionSale.TimeSequence = eventType->TimeSequence;
optionSale.TimeNanoPart = eventType->TimeNanoPart;
optionSale.ExchangeCode = eventType->ExchangeCode;
optionSale.Price = eventType->Price;
optionSale.Size = eventType->Size;
optionSale.BidPrice = eventType->BidPrice;
optionSale.AskPrice = eventType->AskPrice;
optionSale.ExchangeSaleConditions = eventType->ExchangeSaleConditions;
optionSale.Flags = eventType->Flags;
optionSale.UnderlyingPrice = eventType->UnderlyingPrice;
optionSale.Volatility = eventType->Volatility;
optionSale.Delta = eventType->Delta;
optionSale.OptionSymbol = eventType->OptionSymbol;
var optionSale = new OptionSale();
Fill(eventType, optionSale);
return optionSale;
}

Expand Down Expand Up @@ -75,4 +64,25 @@ protected override unsafe OptionSale Convert(OptionSaleNative* eventType)
};
return ptr;
}

private static unsafe OptionSale Fill(OptionSaleNative* eventType, OptionSale optionSale)
{
AssignEventType((EventTypeNative*)eventType, optionSale);
optionSale.EventFlags = eventType->EventFlags;
optionSale.Index = eventType->Index;
optionSale.TimeSequence = eventType->TimeSequence;
optionSale.TimeNanoPart = eventType->TimeNanoPart;
optionSale.ExchangeCode = eventType->ExchangeCode;
optionSale.Price = eventType->Price;
optionSale.Size = eventType->Size;
optionSale.BidPrice = eventType->BidPrice;
optionSale.AskPrice = eventType->AskPrice;
optionSale.ExchangeSaleConditions = eventType->ExchangeSaleConditions;
optionSale.Flags = eventType->Flags;
optionSale.UnderlyingPrice = eventType->UnderlyingPrice;
optionSale.Volatility = eventType->Volatility;
optionSale.Delta = eventType->Delta;
optionSale.OptionSymbol = eventType->OptionSymbol;
return optionSale;
}
}
Loading

0 comments on commit a5a5859

Please sign in to comment.