Skip to content

Commit

Permalink
Issue #740 - The helper function for reading all pages of historical …
Browse files Browse the repository at this point in the history
…corporate action data was added.
  • Loading branch information
OlegRa committed Jan 5, 2025
1 parent 0b0434d commit 9fd2940
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="RichardSzalay.MockHttp" Version="7.0.0" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
12 changes: 6 additions & 6 deletions Alpaca.Markets.Extensions/Alpaca.Markets.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
</PropertyGroup>

<PropertyGroup>
<AssemblyVersion>7.1.1.0</AssemblyVersion>
<FileVersion>7.1.1.0</FileVersion>
<Version>7.1.1</Version>
<AssemblyVersion>7.2.0.0</AssemblyVersion>
<FileVersion>7.2.0.0</FileVersion>
<Version>7.2.0-beta1</Version>
</PropertyGroup>

<PropertyGroup>
<PackageReleaseNotes>
- Service release - the dependencies upgraded to be more up-to-date with the latest fixes.
- The `AlpacaDataClientExtensions.ListCorporateActionsAsAsyncEnumerable` helper method was added to simplify corporate actions pagination handling.
</PackageReleaseNotes>
<Description>C# SDK for Alpaca Trade API https://docs.alpaca.markets/</Description>
<RepositoryUrl>https://github.com/alpacahq/alpaca-trade-api-csharp</RepositoryUrl>
<Copyright>© 2018-2024 Alpaca Securities LLC. All rights reserved.</Copyright>
<Copyright>© 2018-2025 Alpaca Securities LLC. All rights reserved.</Copyright>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageTags>Aplaca API SDK REST WebSocket trading</PackageTags>
<Product>Extansions for .NET SDK for Alpaca Trade API</Product>
Expand Down Expand Up @@ -99,7 +99,7 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" PrivateAssets="compile;contentfiles;build;analyzers" />
<PackageReference Include="System.Threading.Channels" Version="9.0.0" PrivateAssets="compile;contentfiles;build;analyzers" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" PrivateAssets="compile;contentfiles;build;analyzers" />
<PackageReference Include="Alpaca.Markets" Version="7.1.0" PrivateAssets="compile;contentfiles;build;analyzers;" />
<PackageReference Include="Alpaca.Markets" Version="7.2.0-beta1" PrivateAssets="compile;contentfiles;build;analyzers;" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
Expand Down
89 changes: 89 additions & 0 deletions Alpaca.Markets.Extensions/Pagination/AlpacaDataClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,100 @@ public static IAsyncEnumerable<IReadOnlyDictionary<String, IReadOnlyList<IAuctio
getValidatedRequestWithoutPageToken(request.EnsureNotNull())
.GetResponsesByPages(client.EnsureNotNull().GetHistoricalAuctionsAsync, cancellationToken);

/// <summary>
/// Gets all items provided by <see cref="IAlpacaDataClient.ListCorporateActionsAsync"/> in pagination
/// mode as single stream of items (in form of <see cref="IAsyncEnumerable{ICorporateActionsResponse}"/> interface) so they
/// can be consumed by the <c>await foreach</c> statement on the caller side.
/// </summary>
/// <param name="client">Target instance of the <see cref="IAlpacaDataClient"/> interface.</param>
/// <param name="request">Original historical minute bars request (with empty next page token).</param>
/// <exception cref="RequestValidationException">
/// The <paramref name="request"/> argument contains invalid data or some required data is missing, unable to create a valid HTTP request.
/// </exception>
/// <exception cref="HttpRequestException">
/// The request failed due to an underlying issue such as network connectivity, DNS failure, server certificate validation or timeout.
/// </exception>
/// <exception cref="RestClientErrorException">
/// The response contains an error message or the received response cannot be deserialized properly due to JSON schema mismatch.
/// </exception>
/// <exception cref="SocketException">
/// The initial TPC socket connection failed due to an underlying low-level network connectivity issue.
/// </exception>
/// <exception cref="TaskCanceledException">
/// .NET Core and .NET 5 and later only: The request failed due to timeout.
/// </exception>
/// <exception cref="ArgumentNullException">
/// The <paramref name="client"/> or <paramref name="request"/> argument is <c>null</c>.
/// </exception>
[UsedImplicitly]
[CLSCompliant(false)]
public static IAsyncEnumerable<ICorporateActionsResponse> ListCorporateActionsAsAsyncEnumerable(
this IAlpacaDataClient client,
CorporateActionsRequest request) =>
ListCorporateActionsAsAsyncEnumerable(client, request, CancellationToken.None);

/// <summary>
/// Gets all items provided by <see cref="IAlpacaDataClient.ListCorporateActionsAsync"/> in pagination
/// mode as single stream of items (in form of <see cref="IAsyncEnumerable{ICorporateActionsResponse}"/> interface) so they
/// can be consumed by the <c>await foreach</c> statement on the caller side.
/// </summary>
/// <param name="client">Target instance of the <see cref="IAlpacaDataClient"/> interface.</param>
/// <param name="request">Original historical minute bars request (with empty next page token).</param>
/// <param name="cancellationToken">
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
/// <exception cref="RequestValidationException">
/// The <paramref name="request"/> argument contains invalid data or some required data is missing, unable to create a valid HTTP request.
/// </exception>
/// <exception cref="HttpRequestException">
/// The request failed due to an underlying issue such as network connectivity, DNS failure, server certificate validation or timeout.
/// </exception>
/// <exception cref="RestClientErrorException">
/// The response contains an error message or the received response cannot be deserialized properly due to JSON schema mismatch.
/// </exception>
/// <exception cref="SocketException">
/// The initial TPC socket connection failed due to an underlying low-level network connectivity issue.
/// </exception>
/// <exception cref="TaskCanceledException">
/// .NET Core and .NET 5 and later only: The request failed due to timeout.
/// </exception>
/// </param>
/// <exception cref="ArgumentNullException">
/// The <paramref name="client"/> or <paramref name="request"/> argument is <c>null</c>.
/// </exception>
[UsedImplicitly]
[CLSCompliant(false)]
public static IAsyncEnumerable<ICorporateActionsResponse> ListCorporateActionsAsAsyncEnumerable(
this IAlpacaDataClient client,
CorporateActionsRequest request,
CancellationToken cancellationToken) =>
getAllCorporateActionsPages(
client.EnsureNotNull(), getValidatedRequestWithoutPageToken(request.EnsureNotNull()), cancellationToken);

private static NewsArticlesRequest getValidatedRequestWithoutPageToken(
IHistoricalRequest<NewsArticlesRequest, INewsArticle> request) =>
request.GetValidatedRequestWithoutPageToken();

private static HistoricalAuctionsRequest getValidatedRequestWithoutPageToken(
IHistoricalRequest<HistoricalAuctionsRequest, IAuction> request) =>
request.GetValidatedRequestWithoutPageToken();

private static CorporateActionsRequest getValidatedRequestWithoutPageToken(
IHistoricalRequest<CorporateActionsRequest, ICorporateActionsResponse> request) =>
request.GetValidatedRequestWithoutPageToken();

private static async IAsyncEnumerable<ICorporateActionsResponse> getAllCorporateActionsPages(
IAlpacaDataClient client,
CorporateActionsRequest request,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
do
{
var page = await client.ListCorporateActionsAsync(
request, cancellationToken).ConfigureAwait(false);

yield return page;

request.Pagination.Token = page.NextPageToken ?? String.Empty;
} while (!String.IsNullOrEmpty(request.Pagination.Token));
}
}
2 changes: 2 additions & 0 deletions Alpaca.Markets.Extensions/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.GetNewsArticlesAsAsy
static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.GetNewsArticlesAsAsyncEnumerable(this Alpaca.Markets.IAlpacaDataClient! client, Alpaca.Markets.NewsArticlesRequest! request, System.Threading.CancellationToken cancellationToken) -> System.Collections.Generic.IAsyncEnumerable<Alpaca.Markets.INewsArticle!>!
static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.GetNewsArticlesPagesAsAsyncEnumerable(this Alpaca.Markets.IAlpacaDataClient! client, Alpaca.Markets.NewsArticlesRequest! request) -> System.Collections.Generic.IAsyncEnumerable<System.Collections.Generic.IReadOnlyList<Alpaca.Markets.INewsArticle!>!>!
static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.GetNewsArticlesPagesAsAsyncEnumerable(this Alpaca.Markets.IAlpacaDataClient! client, Alpaca.Markets.NewsArticlesRequest! request, System.Threading.CancellationToken cancellationToken) -> System.Collections.Generic.IAsyncEnumerable<System.Collections.Generic.IReadOnlyList<Alpaca.Markets.INewsArticle!>!>!
static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.ListCorporateActionsAsAsyncEnumerable(this Alpaca.Markets.IAlpacaDataClient! client, Alpaca.Markets.CorporateActionsRequest! request) -> System.Collections.Generic.IAsyncEnumerable<Alpaca.Markets.ICorporateActionsResponse!>!
static Alpaca.Markets.Extensions.AlpacaDataClientExtensions.ListCorporateActionsAsAsyncEnumerable(this Alpaca.Markets.IAlpacaDataClient! client, Alpaca.Markets.CorporateActionsRequest! request, System.Threading.CancellationToken cancellationToken) -> System.Collections.Generic.IAsyncEnumerable<Alpaca.Markets.ICorporateActionsResponse!>!
static Alpaca.Markets.Extensions.AlpacaDataStreamingClientExtensions.GetCancellationSubscription(this Alpaca.Markets.IAlpacaDataStreamingClient! client, params string![]! symbols) -> Alpaca.Markets.IAlpacaDataSubscription<Alpaca.Markets.ITrade!>!
static Alpaca.Markets.Extensions.AlpacaDataStreamingClientExtensions.GetCancellationSubscription(this Alpaca.Markets.IAlpacaDataStreamingClient! client, System.Collections.Generic.IEnumerable<string!>! symbols) -> Alpaca.Markets.IAlpacaDataSubscription<Alpaca.Markets.ITrade!>!
static Alpaca.Markets.Extensions.AlpacaDataStreamingClientExtensions.GetCorrectionSubscription(this Alpaca.Markets.IAlpacaDataStreamingClient! client, params string![]! symbols) -> Alpaca.Markets.IAlpacaDataSubscription<Alpaca.Markets.ICorrection!>!
Expand Down
Loading

0 comments on commit 9fd2940

Please sign in to comment.