Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDAPI-96] [.NET] Retrieve latest events from feed #85

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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