Skip to content

Commit

Permalink
Issue #667 - Added the new ErrorInformation property into the `Rest…
Browse files Browse the repository at this point in the history
…ClientException` class.
  • Loading branch information
OlegRa committed Sep 16, 2023
1 parent d7407c4 commit 8d1495a
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 3 deletions.
19 changes: 19 additions & 0 deletions Alpaca.Markets.Tests/ThrottleParametersTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,19 @@ public ThrottleParametersTest(
[Fact]
public async Task ThrottlingWithErrorMessageWorks()
{
const String symbol = "AAPL";
const Decimal money = 1_000M;
const Int32 orders = 10;

using var mock = _mockClientsFactory.GetAlpacaTradingClientMock();

var errorMessage = new JObject(
new JProperty("day_trading_buying_power", money),
new JProperty("max_dtbp_used_so_far", money),
new JProperty("open_orders", orders),
new JProperty("max_dtbp_used", money),
new JProperty("message", Message),
new JProperty("symbol", symbol),
new JProperty("code", ErrorCode)).ToString();

var delay = TimeSpan.FromMilliseconds(100);
Expand All @@ -46,6 +55,15 @@ public async Task ThrottlingWithErrorMessageWorks()
Assert.Equal(Message,exception.Message);
Assert.Equal(ErrorCode, exception.ErrorCode);
Assert.Equal(HttpStatusCode.ServiceUnavailable, exception.HttpStatusCode);

var info = exception.ErrorInformation;

Assert.NotNull(info);
Assert.Equal(symbol, info.Symbol);
Assert.Equal(orders, info.OpenOrdersCount);
Assert.Equal(money, info.DayTradingBuyingPower);
Assert.Equal(money, info.MaxDayTradingBuyingPowerUsed);
Assert.Equal(money, info.MaxDayTradingBuyingPowerUsedSoFar);
return;

KeyValuePair<String, String> AsHeader(
Expand Down Expand Up @@ -87,6 +105,7 @@ public async Task ThrottlingWithoutErrorMessageWorks()
var exception = await Assert.ThrowsAsync<RestClientErrorException>(
() => mock.Client.CancelOrderAsync(Guid.NewGuid()));

Assert.Null(exception.ErrorInformation);
Assert.NotEqual("HTTP 500: Unknown server error.",exception.Message);
Assert.Equal((Int32)HttpStatusCode.InternalServerError, exception.ErrorCode);
Assert.Equal(HttpStatusCode.InternalServerError, exception.HttpStatusCode);
Expand Down
1 change: 1 addition & 0 deletions Alpaca.Markets.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Contentless/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=CUSIP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Delisted/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dtbp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dtmc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=fractionable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gnss/@EntryIndexedValue">True</s:Boolean>
Expand Down
6 changes: 6 additions & 0 deletions Alpaca.Markets/Exceptions/RestClientErrorException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ internal RestClientErrorException(
JsonError error)
: base(error.Message)
{
ErrorInformation = error;
HttpStatusCode = message.StatusCode;
ErrorCode = error.Code ?? (Int32)HttpStatusCode;
}
Expand Down Expand Up @@ -82,4 +83,9 @@ internal RestClientErrorException(
/// Gets original HTTP status code returned by REST API endpoint.
/// </summary>
public HttpStatusCode? HttpStatusCode { get; }

/// <summary>
/// Gets extended error information if it provided by server.
/// </summary>
public IErrorInformation? ErrorInformation { get; }
}
32 changes: 32 additions & 0 deletions Alpaca.Markets/Interfaces/IErrorInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace Alpaca.Markets;

/// <summary>
/// Encapsulates extended error information from Alpaca error REST response.
/// </summary>
public interface IErrorInformation
{
/// <summary>
/// Gets the symbol name related for the error.
/// </summary>
String Symbol { get; }

/// <summary>
/// Gets the number of opened orders if this value related to the error.
/// </summary>
Int32? OpenOrdersCount { get; }

/// <summary>
/// Gets the day trading buying power if this value related to the error.
/// </summary>
Decimal? DayTradingBuyingPower { get; }

/// <summary>
/// Gets the maximal day trading buying power if this value related to the error.
/// </summary>
Decimal? MaxDayTradingBuyingPowerUsed { get; }

/// <summary>
/// Gets the used maximal day trading buying power if this value related to the error.
/// </summary>
Decimal? MaxDayTradingBuyingPowerUsedSoFar { get; }
}
17 changes: 16 additions & 1 deletion Alpaca.Markets/Messages/JsonError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,26 @@
[SuppressMessage(
"Microsoft.Performance", "CA1812:Avoid uninstantiated internal classes",
Justification = "Object instances of this class will be created by Newtonsoft.JSON library.")]
internal sealed class JsonError
internal sealed class JsonError : IErrorInformation
{
[JsonProperty(PropertyName = "code", Required = Required.Default)]
public Int32? Code { get; set; }

[JsonProperty(PropertyName = "message", Required = Required.Default)]
public String Message { get; set; } = String.Empty;

[JsonProperty(PropertyName = "symbol", Required = Required.Default)]
public String Symbol { get; set; } = String.Empty;

[JsonProperty(PropertyName = "open_orders", Required = Required.Default)]
public Int32? OpenOrdersCount { get; set; }

[JsonProperty(PropertyName = "day_trading_buying_power", Required = Required.Default)]
public Decimal? DayTradingBuyingPower { get; set; }

[JsonProperty(PropertyName = "max_dtbp_used", Required = Required.Default)]
public Decimal? MaxDayTradingBuyingPowerUsed { get; set; }

[JsonProperty(PropertyName = "max_dtbp_used_so_far", Required = Required.Default)]
public Decimal? MaxDayTradingBuyingPowerUsedSoFar { get; set; }
}
7 changes: 7 additions & 0 deletions Alpaca.Markets/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,12 @@ Alpaca.Markets.IEnvironment.AlpacaDataStreamingApi.get -> System.Uri!
Alpaca.Markets.IEnvironment.AlpacaNewsStreamingApi.get -> System.Uri!
Alpaca.Markets.IEnvironment.AlpacaStreamingApi.get -> System.Uri!
Alpaca.Markets.IEnvironment.AlpacaTradingApi.get -> System.Uri!
Alpaca.Markets.IErrorInformation
Alpaca.Markets.IErrorInformation.DayTradingBuyingPower.get -> decimal?
Alpaca.Markets.IErrorInformation.MaxDayTradingBuyingPowerUsed.get -> decimal?
Alpaca.Markets.IErrorInformation.MaxDayTradingBuyingPowerUsedSoFar.get -> decimal?
Alpaca.Markets.IErrorInformation.OpenOrdersCount.get -> int?
Alpaca.Markets.IErrorInformation.Symbol.get -> string!
Alpaca.Markets.IExclusiveTimeInterval
Alpaca.Markets.IInclusiveTimeInterval
Alpaca.Markets.IIntervalCalendar
Expand Down Expand Up @@ -1056,6 +1062,7 @@ Alpaca.Markets.RequestValidationException.RequestValidationException(string! mes
Alpaca.Markets.RequestValidationException.RequestValidationException(string! message, System.Exception! inner) -> void
Alpaca.Markets.RestClientErrorException
Alpaca.Markets.RestClientErrorException.ErrorCode.get -> int
Alpaca.Markets.RestClientErrorException.ErrorInformation.get -> Alpaca.Markets.IErrorInformation?
Alpaca.Markets.RestClientErrorException.HttpStatusCode.get -> System.Net.HttpStatusCode?
Alpaca.Markets.RestClientErrorException.RestClientErrorException() -> void
Alpaca.Markets.RestClientErrorException.RestClientErrorException(string! message) -> void
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ Use the `Environments.Paper.GetAlpacaDataStreamingClient(...)` factory method fo

| Branch | Version | Description | Milestone |
| -------------------------------------------- | ------- | -------------------------------------------- |--------------------------|
| [develop](../../tree/develop) | 7.0.x | Unstable - experimental, can contain bugs | [SDK 7.0.x Experimental](https://github.com/alpacahq/alpaca-trade-api-csharp/milestone/17) |
| [master](../../tree/master) | 6.x | Stable - good choice for the new development | [SDK 6.x Stable](https://github.com/alpacahq/alpaca-trade-api-csharp/milestone/16) |
| [develop](../../tree/develop) | 8.x | Unstable - experimental, can contain bugs | [SDK 8.x STS (WIP)](https://github.com/alpacahq/alpaca-trade-api-csharp/milestone/18) |
| [master](../../tree/develop) | 7.x | STS - good choice for the new development | [SDK 7.x LTS](https://github.com/alpacahq/alpaca-trade-api-csharp/milestone/17) |
| [support/6.x](../../tree/support/6.x) | 6.x | LTS - good choice for the new development | [SDK 6.x STS](https://github.com/alpacahq/alpaca-trade-api-csharp/milestone/16) |

### Build instructions

Expand Down

0 comments on commit 8d1495a

Please sign in to comment.