Skip to content

Commit

Permalink
Issue #731 - The IAlpacaTradingClient interface was extended with t…
Browse files Browse the repository at this point in the history
…wo new `ExerciseOptionsContractBy...Async` methods.

(cherry picked from commit 2ec1dec)
  • Loading branch information
OlegRa committed Apr 14, 2024
1 parent d16daf3 commit 3953026
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Alpaca.Markets.Tests/AlpacaTradingClientTest.Positions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ public async Task DeleteAllPositionsWithOrdersAsyncWorks()
Assert.NotEmpty(statuses);
}

[Fact]
public async Task ExerciseOptionsPositionByIdAsyncWorks()
{
using var mock = mockClientsFactory.GetAlpacaTradingClientMock();

mock.AddPost("/v2/positions/*/exercise", new JObject());

Assert.True(await mock.Client.ExerciseOptionsPositionByIdAsync(Guid.NewGuid()));
}

[Fact]
public async Task ExerciseOptionsPositionBySymbolAsyncWorks()
{
using var mock = mockClientsFactory.GetAlpacaTradingClientMock();

mock.AddPost("/v2/positions/*/exercise", new JObject());

Assert.True(await mock.Client.ExerciseOptionsPositionBySymbolAsync(Stock));
}

[SuppressMessage("ReSharper", "StringLiteralTypo")]
private static JObject createPosition() =>
new(
Expand Down
12 changes: 12 additions & 0 deletions Alpaca.Markets/AlpacaTradingClient.Orders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,16 @@ public Task<IReadOnlyList<IOrderActionStatus>> CancelAllOrdersAsync(
CancellationToken cancellationToken = default) =>
_httpClient.DeleteAsync<IReadOnlyList<IOrderActionStatus>, List<JsonOrderActionStatus>>(
"v2/orders", _rateLimitHandler, cancellationToken);

public Task<Boolean> ExerciseOptionsPositionByIdAsync(
Guid contractId,
CancellationToken cancellationToken = default) =>
_httpClient.TryPostAsync(
$"v2/positions/{contractId:D}/exercise", _rateLimitHandler, cancellationToken);

public Task<Boolean> ExerciseOptionsPositionBySymbolAsync(
String symbol,
CancellationToken cancellationToken = default) =>
_httpClient.TryPostAsync(
$"v2/positions/{symbol.EnsureNotNull()}/exercise", _rateLimitHandler, cancellationToken);
}
42 changes: 42 additions & 0 deletions Alpaca.Markets/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,20 @@
<Right>lib/netstandard2.1/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
<Left>lib/net6.0/Alpaca.Markets.dll</Left>
<Right>lib/net6.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionBySymbolAsync(System.String,System.Threading.CancellationToken)</Target>
<Left>lib/net6.0/Alpaca.Markets.dll</Left>
<Right>lib/net6.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.GetOptionContractByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
Expand Down Expand Up @@ -1534,6 +1548,20 @@
<Right>lib/net6.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
<Left>lib/netstandard2.0/Alpaca.Markets.dll</Left>
<Right>lib/netstandard2.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionBySymbolAsync(System.String,System.Threading.CancellationToken)</Target>
<Left>lib/netstandard2.0/Alpaca.Markets.dll</Left>
<Right>lib/netstandard2.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.GetOptionContractByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
Expand Down Expand Up @@ -1583,6 +1611,20 @@
<Right>lib/netstandard2.0/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
<Left>lib/netstandard2.1/Alpaca.Markets.dll</Left>
<Right>lib/netstandard2.1/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionBySymbolAsync(System.String,System.Threading.CancellationToken)</Target>
<Left>lib/netstandard2.1/Alpaca.Markets.dll</Left>
<Right>lib/netstandard2.1/Alpaca.Markets.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Alpaca.Markets.IAlpacaTradingClient.GetOptionContractByIdAsync(System.Guid,System.Threading.CancellationToken)</Target>
Expand Down
16 changes: 16 additions & 0 deletions Alpaca.Markets/Helpers/HttpClientExtensions.Post.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

internal static partial class HttpClientExtensions
{
public static Task<Boolean> TryPostAsync(
this HttpClient httpClient,
UriBuilder uriBuilder,
RateLimitHandler rateLimitHandler,
CancellationToken cancellationToken) =>
callAndReturnSuccessCodeAsync(
httpClient, HttpMethod.Post, uriBuilder.Uri, rateLimitHandler, cancellationToken);

public static Task<Boolean> TryPostAsync(
this HttpClient httpClient,
String endpointUri,
RateLimitHandler rateLimitHandler,
CancellationToken cancellationToken) =>
callAndReturnSuccessCodeAsync(
httpClient, HttpMethod.Post, asUri(endpointUri), rateLimitHandler, cancellationToken);

public static Task<TApi> PostAsync<TApi, TJson, TRequest>(
this HttpClient httpClient,
String endpointUri,
Expand Down
43 changes: 43 additions & 0 deletions Alpaca.Markets/Interfaces/IAlpacaTradingClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -976,4 +976,47 @@ Task<IOptionContract> GetOptionContractByIdAsync(
Task<IOptionContract> GetOptionContractBySymbolAsync(
String symbol,
CancellationToken cancellationToken = default);

/// <summary>
/// Exercises a held option contract, converting it into the underlying asset based on the specified terms.
/// </summary>
/// <param name="contractId">Option contract unique identifier.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <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="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>
/// <returns>Returns <c>true</c> if operation completed successfully.</returns>
[UsedImplicitly]
Task<Boolean> ExerciseOptionsPositionByIdAsync(
Guid contractId,
CancellationToken cancellationToken = default);

/// <summary>
/// Exercises a held option contract, converting it into the underlying asset based on the specified terms.
/// </summary>
/// <param name="symbol">Option contract unique symbol name.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <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="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="symbol"/> argument is <c>null</c>.
/// </exception>
/// <returns>Returns <c>true</c> if operation completed successfully.</returns>
[UsedImplicitly]
Task<Boolean> ExerciseOptionsPositionBySymbolAsync(
String symbol,
CancellationToken cancellationToken = default);
}
2 changes: 1 addition & 1 deletion Alpaca.Markets/Parameters/OptionChainRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public sealed class OptionChainRequest : Validation.IRequest
{
/// <summary>
/// Creates new instance of <see cref="LatestOptionsDataRequest"/> object.
/// Creates new instance of <see cref="OptionChainRequest"/> object.
/// </summary>
/// <param name="underlyingSymbol">Option underlying symbol for data retrieval.</param>
/// <exception cref="ArgumentNullException">
Expand Down
2 changes: 2 additions & 0 deletions Alpaca.Markets/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#nullable enable
Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionByIdAsync(System.Guid contractId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<bool>!
Alpaca.Markets.IAlpacaTradingClient.ExerciseOptionsPositionBySymbolAsync(string! symbol, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<bool>!
Alpaca.Markets.LatestOptionsDataRequest
Alpaca.Markets.LatestOptionsDataRequest.LatestOptionsDataRequest(System.Collections.Generic.IEnumerable<string!>! symbols) -> void
Alpaca.Markets.LatestOptionsDataRequest.OptionsFeed.get -> Alpaca.Markets.OptionsFeed?
Expand Down

0 comments on commit 3953026

Please sign in to comment.