From 3b3167f1011961f831a4db03f08500d7cdc2d9d9 Mon Sep 17 00:00:00 2001 From: artemiusgreat Date: Tue, 4 Jun 2024 16:24:00 -0400 Subject: [PATCH] Gateways --- Client/Client.csproj | 3 +- Client/Components/BaseComponent.razor.cs | 7 +- Client/Components/ChartsComponent.razor.cs | 23 +- Client/Components/PageComponent.razor | 10 +- Client/Components/PageComponent.razor.cs | 23 +- Client/Pages/Orders.razor.cs | 110 ++-- Client/Pages/Pairs.razor.cs | 112 ++-- Core/Core.csproj | 2 +- Core/Domains/Gateway.cs | 20 +- Core/Enums/OrderTimeSpanEnum.cs | 4 +- Gateways/Alpaca/Libs/Adapter.cs | 112 ++-- Gateways/Alpaca/Libs/Alpaca.csproj | 2 +- ...tActivity.cs => AccountActivityMessage.cs} | 2 +- ...tion.cs => AccountConfigurationMessage.cs} | 2 +- .../{JsonAccount.cs => AccountMessage.cs} | 2 +- ...onActiveStock.cs => ActiveStockMessage.cs} | 2 +- ...ActiveStocks.cs => ActiveStocksMessage.cs} | 4 +- ...Announcement.cs => AnnouncementMessage.cs} | 2 +- .../{JsonAsset.cs => AssetMessage.cs} | 2 +- ...AuctionEntry.cs => AuctionEntryMessage.cs} | 2 +- .../{JsonAuction.cs => AuctionMessage.cs} | 10 +- ...AuctionsPage.cs => AuctionsPageMessage.cs} | 6 +- ...onAuthRequest.cs => AuthRequestMessage.cs} | 2 +- ...AuthResponse.cs => AuthResponseMessage.cs} | 2 +- ...entication.cs => AuthenticationMessage.cs} | 2 +- .../{JsonBarsPage.cs => BarsPageMessage.cs} | 6 +- .../{JsonCalendar.cs => CalendarMessage.cs} | 2 +- .../{JsonClock.cs => ClockMessage.cs} | 2 +- ...Success.cs => ConnectionSuccessMessage.cs} | 2 +- ...JsonCorrection.cs => CorrectionMessage.cs} | 4 +- .../Libs/Messages/CryptoSnapshotMessage.cs | 24 + .../{JsonError.cs => ErrorMessage.cs} | 2 +- ...storicalBar.cs => HistoricalBarMessage.cs} | 2 +- ...ote.cs => HistoricalCryptoQuoteMessage.cs} | 2 +- ...rBook.cs => HistoricalOrderBookMessage.cs} | 10 +- ...icalQuote.cs => HistoricalQuoteMessage.cs} | 2 +- ...icalTrade.cs => HistoricalTradeMessage.cs} | 2 +- .../Libs/Messages/JsonCryptoSnapshot.cs | 24 - .../Alpaca/Libs/Messages/JsonMarketMovers.cs | 13 - .../Libs/Messages/JsonOptionSnapshot.cs | 12 - .../Libs/Messages/JsonRealTimeOrderBook.cs | 25 - Gateways/Alpaca/Libs/Messages/JsonSnapshot.cs | 24 - .../{JsonLatestBar.cs => LatestBarMessage.cs} | 4 +- ...dOffer.cs => LatestBestBidOfferMessage.cs} | 4 +- ...JsonLatestData.cs => LatestDataMessage.cs} | 6 +- ...onLatestQuote.cs => LatestQuoteMessage.cs} | 2 +- ...onLatestTrade.cs => LatestTradeMessage.cs} | 4 +- ...imitDown.cs => LimitUpLimitDownMessage.cs} | 2 +- ...stenRequest.cs => ListenRequestMessage.cs} | 2 +- ...onMarketMover.cs => MarketMoverMessage.cs} | 2 +- .../Libs/Messages/MarketMoversMessage.cs | 13 + ...onsPage.cs => MultiAuctionsPageMessage.cs} | 6 +- ...ltiBarsPage.cs => MultiBarsPageMessage.cs} | 6 +- ...uotesPage.cs => MultiQuotesPageMessage.cs} | 2 +- ...radesPage.cs => MultiTradesPageMessage.cs} | 2 +- ...onNewsArticle.cs => NewsArticleMessage.cs} | 2 +- .../{JsonNewsPage.cs => NewsPageMessage.cs} | 4 +- ...onContract.cs => OptionContractMessage.cs} | 2 +- ...sPage.cs => OptionContractsPageMessage.cs} | 4 +- ...onOptionQuote.cs => OptionQuoteMessage.cs} | 2 +- .../Libs/Messages/OptionSnapshotMessage.cs | 12 + ...onOptionTrade.cs => OptionTradeMessage.cs} | 2 +- ...nStatus.cs => OrderActionStatusMessage.cs} | 2 +- ...s.cs => OrderAdvancedAttributesMessage.cs} | 2 +- ...rBookEntry.cs => OrderBookEntryMessage.cs} | 2 +- ...sonNewOrder.cs => OrderCreationMessage.cs} | 6 +- .../{JsonOrder.cs => OrderMessage.cs} | 4 +- ...oHistory.cs => PortfolioHistoryMessage.cs} | 2 +- ...atus.cs => PositionActionStatusMessage.cs} | 2 +- .../{JsonPosition.cs => PositionMessage.cs} | 2 +- ...JsonQuotesPage.cs => QuotesPageMessage.cs} | 2 +- ...onRealTimeBar.cs => RealTimeBarMessage.cs} | 2 +- ...RealTimeBase.cs => RealTimeBaseMessage.cs} | 2 +- ...Quote.cs => RealTimeCryptoQuoteMessage.cs} | 2 +- .../Libs/Messages/RealTimeOrderBookMessage.cs | 25 + ...alTimeQuote.cs => RealTimeQuoteMessage.cs} | 2 +- ...alTimeTrade.cs => RealTimeTradeMessage.cs} | 2 +- .../Alpaca/Libs/Messages/SnapshotMessage.cs | 24 + ...onStreamError.cs => StreamErrorMessage.cs} | 2 +- ...Update.cs => SubscriptionUpdateMessage.cs} | 2 +- ...onTradeUpdate.cs => TradeUpdateMessage.cs} | 4 +- ...JsonTradesPage.cs => TradesPageMessage.cs} | 2 +- ...adingStatus.cs => TradingStatusMessage.cs} | 2 +- .../{JsonWatchList.cs => WatchListMessage.cs} | 4 +- Gateways/Oanda/Libs/Adapter.cs | 610 ++++++++++++++++++ Gateways/Schwab/Libs/Adapter.cs | 582 +++++++++++++++-- Gateways/Schwab/Libs/Authenticator.cs | 173 ----- .../Libs/Messages/AccountNumbersMessage.cs | 15 + .../Schwab/Libs/Messages/AccountsMessage.cs | 15 + .../Libs/Messages/AggregatedBalanceMessage.cs | 15 + .../Libs/Messages/ExecutionLegMessage.cs | 32 + .../Libs/Messages/InitialBalanceMessage.cs | 135 ++++ .../Schwab/Libs/Messages/InstrumentMessage.cs | 43 ++ .../Libs/Messages/OptionChainMessage.cs | 48 ++ .../Libs/Messages/OptionDeliverableMessage.cs | 21 + .../Schwab/Libs/Messages/OptionMessage.cs | 153 +++++ .../Libs/Messages/OrderActivityMessage.cs | 28 + .../Schwab/Libs/Messages/OrderLegMessage.cs | 43 ++ Gateways/Schwab/Libs/Messages/OrderMessage.cs | 153 +++++ .../Schwab/Libs/Messages/PositionMessage.cs | 67 ++ .../Libs/Messages/ProjectedBalanceMessage.cs | 43 ++ Gateways/Schwab/Libs/Messages/ScopeMessage.cs | 25 + .../Schwab/Libs/Messages/SecuritiesMessage.cs | 48 ++ .../Schwab/Libs/Messages/UnderlyingMessage.cs | 78 +++ Gateways/Schwab/Libs/Models/ChainModels.cs | 282 -------- Gateways/Schwab/Libs/Models/UserModels.cs | 38 -- Gateways/Schwab/Libs/Schwab.csproj | 4 +- Gateways/Schwab/Tests/Tests.csproj | 6 +- Gateways/Simulation/Libs/Adapter.cs | 25 +- Gateways/Simulation/Libs/Simulation.csproj | 1 - Gateways/Simulation/Tests/CreateOrders.cs | 4 +- Gateways/Simulation/Tests/DecreasePosition.cs | 4 +- Gateways/Simulation/Tests/IncreasePosition.cs | 4 +- Gateways/Simulation/Tests/Tests.csproj | 6 +- 114 files changed, 2518 insertions(+), 991 deletions(-) rename Gateways/Alpaca/Libs/Messages/{JsonAccountActivity.cs => AccountActivityMessage.cs} (93%) rename Gateways/Alpaca/Libs/Messages/{JsonAccountConfiguration.cs => AccountConfigurationMessage.cs} (90%) rename Gateways/Alpaca/Libs/Messages/{JsonAccount.cs => AccountMessage.cs} (95%) rename Gateways/Alpaca/Libs/Messages/{JsonActiveStock.cs => ActiveStockMessage.cs} (85%) rename Gateways/Alpaca/Libs/Messages/{JsonActiveStocks.cs => ActiveStocksMessage.cs} (56%) rename Gateways/Alpaca/Libs/Messages/{JsonAnnouncement.cs => AnnouncementMessage.cs} (93%) rename Gateways/Alpaca/Libs/Messages/{JsonAsset.cs => AssetMessage.cs} (94%) rename Gateways/Alpaca/Libs/Messages/{JsonAuctionEntry.cs => AuctionEntryMessage.cs} (88%) rename Gateways/Alpaca/Libs/Messages/{JsonAuction.cs => AuctionMessage.cs} (50%) rename Gateways/Alpaca/Libs/Messages/{JsonAuctionsPage.cs => AuctionsPageMessage.cs} (64%) rename Gateways/Alpaca/Libs/Messages/{JsonAuthRequest.cs => AuthRequestMessage.cs} (89%) rename Gateways/Alpaca/Libs/Messages/{JsonAuthResponse.cs => AuthResponseMessage.cs} (82%) rename Gateways/Alpaca/Libs/Messages/{JsonAuthentication.cs => AuthenticationMessage.cs} (84%) rename Gateways/Alpaca/Libs/Messages/{JsonBarsPage.cs => BarsPageMessage.cs} (63%) rename Gateways/Alpaca/Libs/Messages/{JsonCalendar.cs => CalendarMessage.cs} (91%) rename Gateways/Alpaca/Libs/Messages/{JsonClock.cs => ClockMessage.cs} (89%) rename Gateways/Alpaca/Libs/Messages/{JsonConnectionSuccess.cs => ConnectionSuccessMessage.cs} (74%) rename Gateways/Alpaca/Libs/Messages/{JsonCorrection.cs => CorrectionMessage.cs} (86%) create mode 100644 Gateways/Alpaca/Libs/Messages/CryptoSnapshotMessage.cs rename Gateways/Alpaca/Libs/Messages/{JsonError.cs => ErrorMessage.cs} (92%) rename Gateways/Alpaca/Libs/Messages/{JsonHistoricalBar.cs => HistoricalBarMessage.cs} (90%) rename Gateways/Alpaca/Libs/Messages/{JsonHistoricalCryptoQuote.cs => HistoricalCryptoQuoteMessage.cs} (88%) rename Gateways/Alpaca/Libs/Messages/{JsonHistoricalOrderBook.cs => HistoricalOrderBookMessage.cs} (50%) rename Gateways/Alpaca/Libs/Messages/{JsonHistoricalQuote.cs => HistoricalQuoteMessage.cs} (91%) rename Gateways/Alpaca/Libs/Messages/{JsonHistoricalTrade.cs => HistoricalTradeMessage.cs} (91%) delete mode 100644 Gateways/Alpaca/Libs/Messages/JsonCryptoSnapshot.cs delete mode 100644 Gateways/Alpaca/Libs/Messages/JsonMarketMovers.cs delete mode 100644 Gateways/Alpaca/Libs/Messages/JsonOptionSnapshot.cs delete mode 100644 Gateways/Alpaca/Libs/Messages/JsonRealTimeOrderBook.cs delete mode 100644 Gateways/Alpaca/Libs/Messages/JsonSnapshot.cs rename Gateways/Alpaca/Libs/Messages/{JsonLatestBar.cs => LatestBarMessage.cs} (64%) rename Gateways/Alpaca/Libs/Messages/{JsonLatestBestBidOffer.cs => LatestBestBidOfferMessage.cs} (61%) rename Gateways/Alpaca/Libs/Messages/{JsonLatestData.cs => LatestDataMessage.cs} (65%) rename Gateways/Alpaca/Libs/Messages/{JsonLatestQuote.cs => LatestQuoteMessage.cs} (79%) rename Gateways/Alpaca/Libs/Messages/{JsonLatestTrade.cs => LatestTradeMessage.cs} (63%) rename Gateways/Alpaca/Libs/Messages/{JsonLimitUpLimitDown.cs => LimitUpLimitDownMessage.cs} (86%) rename Gateways/Alpaca/Libs/Messages/{JsonListenRequest.cs => ListenRequestMessage.cs} (87%) rename Gateways/Alpaca/Libs/Messages/{JsonMarketMover.cs => MarketMoverMessage.cs} (87%) create mode 100644 Gateways/Alpaca/Libs/Messages/MarketMoversMessage.cs rename Gateways/Alpaca/Libs/Messages/{JsonMultiAuctionsPage.cs => MultiAuctionsPageMessage.cs} (52%) rename Gateways/Alpaca/Libs/Messages/{JsonMultiBarsPage.cs => MultiBarsPageMessage.cs} (52%) rename Gateways/Alpaca/Libs/Messages/{JsonMultiQuotesPage.cs => MultiQuotesPageMessage.cs} (86%) rename Gateways/Alpaca/Libs/Messages/{JsonMultiTradesPage.cs => MultiTradesPageMessage.cs} (86%) rename Gateways/Alpaca/Libs/Messages/{JsonNewsArticle.cs => NewsArticleMessage.cs} (93%) rename Gateways/Alpaca/Libs/Messages/{JsonNewsPage.cs => NewsPageMessage.cs} (67%) rename Gateways/Alpaca/Libs/Messages/{JsonOptionContract.cs => OptionContractMessage.cs} (93%) rename Gateways/Alpaca/Libs/Messages/{JsonOptionContractsPage.cs => OptionContractsPageMessage.cs} (55%) rename Gateways/Alpaca/Libs/Messages/{JsonOptionQuote.cs => OptionQuoteMessage.cs} (90%) create mode 100644 Gateways/Alpaca/Libs/Messages/OptionSnapshotMessage.cs rename Gateways/Alpaca/Libs/Messages/{JsonOptionTrade.cs => OptionTradeMessage.cs} (88%) rename Gateways/Alpaca/Libs/Messages/{JsonOrderActionStatus.cs => OrderActionStatusMessage.cs} (80%) rename Gateways/Alpaca/Libs/Messages/{JsonNewOrderAdvancedAttributes.cs => OrderAdvancedAttributesMessage.cs} (80%) rename Gateways/Alpaca/Libs/Messages/{JsonOrderBookEntry.cs => OrderBookEntryMessage.cs} (80%) rename Gateways/Alpaca/Libs/Messages/{JsonNewOrder.cs => OrderCreationMessage.cs} (84%) rename Gateways/Alpaca/Libs/Messages/{JsonOrder.cs => OrderMessage.cs} (92%) rename Gateways/Alpaca/Libs/Messages/{JsonPortfolioHistory.cs => PortfolioHistoryMessage.cs} (92%) rename Gateways/Alpaca/Libs/Messages/{JsonPositionActionStatus.cs => PositionActionStatusMessage.cs} (80%) rename Gateways/Alpaca/Libs/Messages/{JsonPosition.cs => PositionMessage.cs} (94%) rename Gateways/Alpaca/Libs/Messages/{JsonQuotesPage.cs => QuotesPageMessage.cs} (87%) rename Gateways/Alpaca/Libs/Messages/{JsonRealTimeBar.cs => RealTimeBarMessage.cs} (89%) rename Gateways/Alpaca/Libs/Messages/{JsonRealTimeBase.cs => RealTimeBaseMessage.cs} (85%) rename Gateways/Alpaca/Libs/Messages/{JsonRealTimeCryptoQuote.cs => RealTimeCryptoQuoteMessage.cs} (89%) create mode 100644 Gateways/Alpaca/Libs/Messages/RealTimeOrderBookMessage.cs rename Gateways/Alpaca/Libs/Messages/{JsonRealTimeQuote.cs => RealTimeQuoteMessage.cs} (91%) rename Gateways/Alpaca/Libs/Messages/{JsonRealTimeTrade.cs => RealTimeTradeMessage.cs} (90%) create mode 100644 Gateways/Alpaca/Libs/Messages/SnapshotMessage.cs rename Gateways/Alpaca/Libs/Messages/{JsonStreamError.cs => StreamErrorMessage.cs} (82%) rename Gateways/Alpaca/Libs/Messages/{JsonSubscriptionUpdate.cs => SubscriptionUpdateMessage.cs} (92%) rename Gateways/Alpaca/Libs/Messages/{JsonTradeUpdate.cs => TradeUpdateMessage.cs} (83%) rename Gateways/Alpaca/Libs/Messages/{JsonTradesPage.cs => TradesPageMessage.cs} (87%) rename Gateways/Alpaca/Libs/Messages/{JsonTradingStatus.cs => TradingStatusMessage.cs} (88%) rename Gateways/Alpaca/Libs/Messages/{JsonWatchList.cs => WatchListMessage.cs} (81%) create mode 100644 Gateways/Oanda/Libs/Adapter.cs delete mode 100644 Gateways/Schwab/Libs/Authenticator.cs create mode 100644 Gateways/Schwab/Libs/Messages/AccountNumbersMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/AccountsMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/AggregatedBalanceMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/ExecutionLegMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/InitialBalanceMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/InstrumentMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OptionChainMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OptionDeliverableMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OptionMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OrderActivityMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OrderLegMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/OrderMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/PositionMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/ProjectedBalanceMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/ScopeMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/SecuritiesMessage.cs create mode 100644 Gateways/Schwab/Libs/Messages/UnderlyingMessage.cs delete mode 100644 Gateways/Schwab/Libs/Models/ChainModels.cs delete mode 100644 Gateways/Schwab/Libs/Models/UserModels.cs diff --git a/Client/Client.csproj b/Client/Client.csproj index 237e7fe6b..1ea3ce1d3 100644 --- a/Client/Client.csproj +++ b/Client/Client.csproj @@ -7,13 +7,14 @@ - + + diff --git a/Client/Components/BaseComponent.razor.cs b/Client/Components/BaseComponent.razor.cs index b025786a2..6e1034c2b 100644 --- a/Client/Components/BaseComponent.razor.cs +++ b/Client/Components/BaseComponent.razor.cs @@ -1,15 +1,12 @@ using Distribution.Services; using Microsoft.AspNetCore.Components; using System; -using System.Threading; using System.Threading.Tasks; namespace Client.Components { public class BaseComponent : ComponentBase { - private static object protection = new(); - /// /// Updater /// @@ -18,10 +15,10 @@ public class BaseComponent : ComponentBase /// /// Render /// - protected virtual Task Render(Action action) => Updater.Send(() => + protected virtual Task Render(Action action, bool isRemovable = true) => Updater.Send(() => { action(); InvokeAsync(StateHasChanged); - }).Task; + }, isRemovable).Task; } } diff --git a/Client/Components/ChartsComponent.razor.cs b/Client/Components/ChartsComponent.razor.cs index 6c5220279..de68791bc 100644 --- a/Client/Components/ChartsComponent.razor.cs +++ b/Client/Components/ChartsComponent.razor.cs @@ -21,7 +21,7 @@ public partial class ChartsComponent : IDisposable /// /// Points /// - protected virtual IList Shapes { get; set; } = new List(); + protected virtual IList Shapes { get; set; } = []; /// /// Series @@ -31,13 +31,13 @@ public partial class ChartsComponent : IDisposable /// /// Indices /// - protected virtual IDictionary Indices { get; set; } = new Dictionary(); + protected virtual IDictionary Indices { get; set; } = new Dictionary(); /// /// Define chart model /// /// - public virtual async Task Create(IGroupShape group) + public virtual async Task Create(IShape group) { (View.Item = group) .Groups @@ -58,18 +58,23 @@ public virtual Task UpdateItems(IList> inputs, { var inputValue = input.Value; var index = inputValue.Time.Value.Ticks; - var previousPoint = (Shapes.ElementAtOrDefault(Shapes.Count - 2) ?? View.Item.Clone()) as IGroupShape; + var areaKey = Maps.Get(input.Key); - if (Indices.TryGetValue(index, out IGroupShape currentPoint) is false) + if (areaKey is null) { - currentPoint = previousPoint.Clone() as IGroupShape; + continue; + } + + if (Indices.TryGetValue(index, out IShape currentPoint) is false) + { + currentPoint = (Shapes.LastOrDefault()?.Clone() ?? View.Item.Clone()) as IShape; currentPoint.X = index; Shapes.Add(currentPoint); Indices[index] = currentPoint; } - var series = currentPoint?.Groups?.Get(Maps.Get(input.Key))?.Groups?.Get(input.Key); + var series = currentPoint?.Groups?.Get(areaKey)?.Groups?.Get(input.Key); if (series is not null) { @@ -89,7 +94,7 @@ public virtual Task UpdateItems(IList> inputs, var domain = new DomainModel { - IndexDomain = new int[] { Shapes.Count - (count ?? Shapes.Count), Shapes.Count } + IndexDomain = [Shapes.Count - (count ?? Shapes.Count), Shapes.Count] }; return Render(() => View.Update(domain, Shapes)); @@ -102,7 +107,7 @@ public virtual void Clear() { Shapes.Clear(); Indices.Clear(); - UpdateItems(Array.Empty>(), 0); + Render(() => View.Update(new DomainModel { IndexDomain = [0, 0] }, Shapes), false); } /// diff --git a/Client/Components/PageComponent.razor b/Client/Components/PageComponent.razor index feb85c748..2a5565d8b 100644 --- a/Client/Components/PageComponent.razor +++ b/Client/Components/PageComponent.razor @@ -2,13 +2,13 @@ - - + + @if (IsConnection) { - - + + } @@ -81,7 +81,7 @@ Statements - Update + Update diff --git a/Client/Components/PageComponent.razor.cs b/Client/Components/PageComponent.razor.cs index f8618dc80..ad4e1a282 100644 --- a/Client/Components/PageComponent.razor.cs +++ b/Client/Components/PageComponent.razor.cs @@ -1,6 +1,4 @@ using Distribution.Services; -using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.Configuration; using System; using System.Linq; using System.Threading.Tasks; @@ -11,8 +9,6 @@ namespace Client.Components { public partial class PageComponent { - [Inject] IConfiguration Configuration { get; set; } - /// /// Controls /// @@ -25,19 +21,22 @@ public partial class PageComponent public virtual PositionsComponent PositionsView { get; set; } public virtual StatementsComponent StatementsView { get; set; } public virtual IGateway Adapter { get; set; } - public virtual Action Setup { get; set; } + public virtual Action OnPreConnect { get; set; } + public virtual Action OnPostConnect { get; set; } - public virtual async Task OnConnect() + public virtual async Task Connect() { try { - OnDisconnect(); - Setup(); + Disconnect(); + OnPreConnect(); IsConnection = true; IsSubscription = true; await Adapter.Connect(); + + OnPostConnect(); } catch (Exception e) { @@ -45,7 +44,7 @@ public virtual async Task OnConnect() } } - public virtual void OnDisconnect() + public virtual void Disconnect() { try { @@ -63,7 +62,7 @@ public virtual void OnDisconnect() } } - public virtual void OnSubscribe() + public virtual void Subscribe() { try { @@ -76,7 +75,7 @@ public virtual void OnSubscribe() } } - public virtual void OnUnsubscribe() + public virtual void Unsubscribe() { try { @@ -89,7 +88,7 @@ public virtual void OnUnsubscribe() } } - public virtual void OnOpenStatements() + public virtual void OpenState() { if (Adapter?.Account is not null) { diff --git a/Client/Pages/Orders.razor.cs b/Client/Pages/Orders.razor.cs index a1bc1a966..2a2224524 100644 --- a/Client/Pages/Orders.razor.cs +++ b/Client/Pages/Orders.razor.cs @@ -33,60 +33,72 @@ protected override async Task OnAfterRenderAsync(bool setup) { if (setup) { - var indUp = new ComponentModel { Color = SKColors.DeepSkyBlue }; - var indDown = new ComponentModel { Color = SKColors.OrangeRed }; - var indAreas = new GroupShape(); - var indCharts = new GroupShape(); + await CreateViews(); + View.OnPreConnect = CreateAccounts; + View.OnPostConnect = () => + { + View.DealsView.UpdateItems(Account.Positions); + View.OrdersView.UpdateItems(Account.ActiveOrders); + View.PositionsView.UpdateItems(Account.ActivePositions); + }; + } - indCharts.Groups["Ups"] = new BarShape { Component = indUp }; - indCharts.Groups["Downs"] = new BarShape { Component = indDown }; - indAreas.Groups["Prices"] = indCharts; + await base.OnAfterRenderAsync(setup); + } - await View.ChartsView.Create(indAreas); + protected virtual async Task CreateViews() + { + var indUp = new ComponentModel { Color = SKColors.DeepSkyBlue }; + var indDown = new ComponentModel { Color = SKColors.OrangeRed }; + var indAreas = new Shape(); + var indCharts = new Shape(); - var pnlGain = new ComponentModel { Color = SKColors.OrangeRed, Size = 5 }; - var pnlBalance = new ComponentModel { Color = SKColors.Black }; - var pnlAreas = new GroupShape(); - var pnlCharts = new GroupShape(); + indCharts.Groups["Ups"] = new BarShape { Component = indUp }; + indCharts.Groups["Downs"] = new BarShape { Component = indDown }; + indAreas.Groups["Prices"] = indCharts; - pnlCharts.Groups["PnL"] = new LineShape { Component = pnlGain }; - pnlCharts.Groups["Balance"] = new AreaShape { Component = pnlBalance }; - pnlAreas.Groups["Performance"] = pnlCharts; + await View.ChartsView.Create(indAreas); - await View.ReportsView.Create(pnlAreas); + var pnlGain = new ComponentModel { Color = SKColors.OrangeRed, Size = 5 }; + var pnlBalance = new ComponentModel { Color = SKColors.Black }; + var pnlAreas = new Shape(); + var pnlCharts = new Shape(); - View.Setup = () => + pnlCharts.Groups["PnL"] = new LineShape { Component = pnlGain }; + pnlCharts.Groups["Balance"] = new AreaShape { Component = pnlBalance }; + pnlAreas.Groups["Performance"] = pnlCharts; + + await View.ReportsView.Create(pnlAreas); + } + + protected virtual void CreateAccounts() + { + Account = new Account + { + Descriptor = "Demo", + Instruments = new Dictionary { - Account = new Account - { - Descriptor = "Demo", - Instruments = new Dictionary - { - [_asset] = new Instrument { Name = _asset } - } - }; - - View.Adapter = new Adapter - { - Account = Account, - ConsumerKey = Configuration["Alpaca:Token"], - ConsumerSecret = Configuration["Alpaca:Secret"], - StreamUri = "wss://stream.data.alpaca.markets/v2/test" - }; - - Performance = new PerformanceIndicator { Name = "Balance" }; - - Account - .Instruments - .Values - .ForEach(o => o.Points.CollectionChanged += (_, e) => e - .NewItems - .OfType() - .ForEach(async o => await OnData(o))); - }; - } + [_asset] = new Instrument { Name = _asset } + } + }; - await base.OnAfterRenderAsync(setup); + View.Adapter = new Adapter + { + Account = Account, + ConsumerKey = Configuration["Alpaca:Token"], + ConsumerSecret = Configuration["Alpaca:Secret"], + StreamUri = "wss://stream.data.alpaca.markets/v2/test" + }; + + Performance = new PerformanceIndicator { Name = "Balance" }; + + Account + .Instruments + .Values + .ForEach(o => o.Points.CollectionChanged += (_, e) => e + .NewItems + .OfType() + .ForEach(async o => await OnData(o))); } private async Task OnData(PointModel point) @@ -138,8 +150,8 @@ private void OpenPositions(IInstrument assetBuy, IInstrument assetSell) } }; - View.Adapter.SendOrders(orderBuy); - View.Adapter.SendOrders(orderSell); + View.Adapter.CreateOrders(orderBuy); + View.Adapter.CreateOrders(orderSell); var account = View.Adapter.Account; var buy = account.ActivePositions.Values.First(o => o.Order.Side == OrderSideEnum.Buy); @@ -171,7 +183,7 @@ private void ClosePositions() } }; - View.Adapter.SendOrders(order); + View.Adapter.CreateOrders(order); //points.Add(new PointModel { Time = order.Time, Name = nameof(OrderSideEnum.Buy), Last = price }); } diff --git a/Client/Pages/Pairs.razor.cs b/Client/Pages/Pairs.razor.cs index 167c6baee..695b7bb8f 100644 --- a/Client/Pages/Pairs.razor.cs +++ b/Client/Pages/Pairs.razor.cs @@ -34,61 +34,73 @@ protected override async Task OnAfterRenderAsync(bool setup) { if (setup) { - var indUp = new ComponentModel { Color = SKColors.DeepSkyBlue }; - var indDown = new ComponentModel { Color = SKColors.OrangeRed }; - var indAreas = new GroupShape(); - var indCharts = new GroupShape(); + await CreateViews(); + View.OnPreConnect = CreateAccounts; + View.OnPostConnect = () => + { + View.DealsView.UpdateItems(Account.Positions); + View.OrdersView.UpdateItems(Account.ActiveOrders); + View.PositionsView.UpdateItems(Account.ActivePositions); + }; + } - indCharts.Groups["Ups"] = new ArrowShape { Component = indUp }; - indCharts.Groups["Downs"] = new ArrowShape { Component = indDown }; - indCharts.Groups["Range"] = new AreaShape { Component = indUp }; - indAreas.Groups["Prices"] = indCharts; + await base.OnAfterRenderAsync(setup); + } - await View.ChartsView.Create(indAreas); + protected virtual async Task CreateViews() + { + var indUp = new ComponentModel { Color = SKColors.DeepSkyBlue }; + var indDown = new ComponentModel { Color = SKColors.OrangeRed }; + var indAreas = new Shape(); + var indCharts = new Shape(); - var pnlGain = new ComponentModel { Color = SKColors.OrangeRed, Size = 5 }; - var pnlBalance = new ComponentModel { Color = SKColors.Black }; - var pnlAreas = new GroupShape(); - var pnlCharts = new GroupShape(); + indCharts.Groups["Ups"] = new ArrowShape { Component = indUp }; + indCharts.Groups["Downs"] = new ArrowShape { Component = indDown }; + indCharts.Groups["Range"] = new AreaShape { Component = indUp }; + indAreas.Groups["Prices"] = indCharts; - pnlCharts.Groups["PnL"] = new LineShape { Component = pnlGain }; - pnlCharts.Groups["Balance"] = new AreaShape { Component = pnlBalance }; - pnlAreas.Groups["Performance"] = pnlCharts; + await View.ChartsView.Create(indAreas); - await View.ReportsView.Create(pnlAreas); + var pnlGain = new ComponentModel { Color = SKColors.OrangeRed, Size = 5 }; + var pnlBalance = new ComponentModel { Color = SKColors.Black }; + var pnlAreas = new Shape(); + var pnlCharts = new Shape(); - View.Setup = () => + pnlCharts.Groups["PnL"] = new LineShape { Component = pnlGain }; + pnlCharts.Groups["Balance"] = new AreaShape { Component = pnlBalance }; + pnlAreas.Groups["Performance"] = pnlCharts; + + await View.ReportsView.Create(pnlAreas); + } + + protected virtual void CreateAccounts() + { + Account = new Account + { + Balance = 25000, + Instruments = new Dictionary { - Account = new Account - { - Balance = 25000, - Instruments = new Dictionary - { - [_assetX] = new Instrument { Name = _assetX }, - [_assetY] = new Instrument { Name = _assetY } - } - }; - - View.Adapter = new Adapter - { - Speed = 1, - Account = Account, - Source = Configuration["Simulation:Source"] - }; - - Performance = new PerformanceIndicator { Name = "Balance" }; - - Account - .Instruments - .Values - .ForEach(o => o.Points.CollectionChanged += (_, e) => e - .NewItems - .OfType() - .ForEach(async o => await OnData(o))); - }; - } + [_assetX] = new Instrument { Name = _assetX }, + [_assetY] = new Instrument { Name = _assetY } + } + }; - await base.OnAfterRenderAsync(setup); + View.Adapter = new Adapter + { + Speed = 1, + Account = Account, + Source = Configuration["Simulation:Source"] + }; + + Performance = new PerformanceIndicator { Name = "Balance" }; + + Account + .Instruments + .Values + .ForEach(o => o.Points.CollectionChanged += (_, e) => e + .NewItems + .OfType() + .ForEach(async o => await OnData(o))); } private async Task OnData(PointModel point) @@ -175,8 +187,8 @@ private void OpenPositions(IInstrument assetBuy, IInstrument assetSell) } }; - View.Adapter.SendOrders(orderBuy); - View.Adapter.SendOrders(orderSell); + View.Adapter.CreateOrders(orderBuy); + View.Adapter.CreateOrders(orderSell); var account = View.Adapter.Account; var buy = account.ActivePositions.Values.First(o => o.Order.Side == OrderSideEnum.Buy); @@ -208,7 +220,7 @@ private void ClosePositions() } }; - View.Adapter.SendOrders(order); + View.Adapter.CreateOrders(order); //points.Add(new PointModel { Time = order.Time, Name = nameof(OrderSideEnum.Buy), Last = price }); } diff --git a/Core/Core.csproj b/Core/Core.csproj index 09e3add9f..b7d066656 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -5,7 +5,7 @@ - + diff --git a/Core/Domains/Gateway.cs b/Core/Domains/Gateway.cs index 6598e8eb3..00371b88c 100644 --- a/Core/Domains/Gateway.cs +++ b/Core/Domains/Gateway.cs @@ -38,12 +38,6 @@ public interface IGateway : IDisposable /// Task> Unsubscribe(string name); - /// - /// Get quote - /// - /// - Task> GetPoint(PointMessageModel message); - /// /// Get quotes history /// @@ -60,13 +54,13 @@ public interface IGateway : IDisposable /// Send new orders /// /// - Task> SendOrders(params OrderModel[] orders); + Task> CreateOrders(params OrderModel[] orders); /// /// Cancel orders /// /// - Task> CancelOrders(params OrderModel[] orders); + Task> DeleteOrders(params OrderModel[] orders); } /// @@ -109,12 +103,6 @@ public Gateway() /// public abstract Task> Unsubscribe(string name); - /// - /// Get quote - /// - /// - public abstract Task> GetPoint(PointMessageModel message); - /// /// Get quotes history /// @@ -131,13 +119,13 @@ public Gateway() /// Send new orders /// /// - public abstract Task> SendOrders(params OrderModel[] orders); + public abstract Task> CreateOrders(params OrderModel[] orders); /// /// Cancel orders /// /// - public abstract Task> CancelOrders(params OrderModel[] orders); + public abstract Task> DeleteOrders(params OrderModel[] orders); /// /// Dispose diff --git a/Core/Enums/OrderTimeSpanEnum.cs b/Core/Enums/OrderTimeSpanEnum.cs index fa2fec8bf..590ee2a96 100644 --- a/Core/Enums/OrderTimeSpanEnum.cs +++ b/Core/Enums/OrderTimeSpanEnum.cs @@ -7,7 +7,7 @@ public enum OrderTimeSpanEnum : byte Fok = 2, Gtc = 3, Ioc = 4, - Omo = 5, - Omc = 6 + Am = 5, + Pm = 6 } } diff --git a/Gateways/Alpaca/Libs/Adapter.cs b/Gateways/Alpaca/Libs/Adapter.cs index 0ed389809..8af24ceeb 100644 --- a/Gateways/Alpaca/Libs/Adapter.cs +++ b/Gateways/Alpaca/Libs/Adapter.cs @@ -54,26 +54,20 @@ public class Adapter : Gateway public virtual string ConsumerSecret { get; set; } /// - /// Secret + /// Data source /// public virtual string DataUri { get; set; } /// - /// Secret + /// Streaming source /// public virtual string StreamUri { get; set; } - /// - /// Environment setter - /// - public virtual EnvironmentEnum Environment { get; set; } - /// /// Constructor /// public Adapter() { - Environment = EnvironmentEnum.Live; StreamUri = "wss://stream.data.alpaca.markets/v2/iex"; DataUri = "https://api.alpaca.markets"; @@ -94,7 +88,7 @@ public override async Task> Connect() _sender = new Service(); _streamer = await GetConnection(ws, scheduler); - await SendStream(_streamer, new JsonAuthentication + await SendStream(_streamer, new AuthenticationMessage { Action = "auth", SecretKey = ConsumerSecret, @@ -118,7 +112,7 @@ public override async Task> Connect() public override async Task> Subscribe(string name) { await Unsubscribe(name); - await SendStream(_streamer, new JsonSubscriptionUpdate + await SendStream(_streamer, new SubscriptionUpdateMessage { Action = "subscribe", Trades = [name], @@ -133,10 +127,10 @@ public override async Task> Subscribe(string name) /// public override Task> Disconnect() { - _connections?.ForEach(o => o.Dispose()); + _connections?.ForEach(o => o?.Dispose()); _connections?.Clear(); - return Task.FromResult(null as IList); + return Task.FromResult>(null); } /// @@ -144,7 +138,7 @@ public override Task> Disconnect() /// public override async Task> Unsubscribe(string name) { - await SendStream(_streamer, new JsonSubscriptionUpdate + await SendStream(_streamer, new SubscriptionUpdateMessage { Action = "unsubscribe", Trades = [name], @@ -157,20 +151,6 @@ public override async Task> Unsubscribe(string name) return null; } - /// - /// Get quote - /// - /// - public override Task> GetPoint(PointMessageModel message) - { - var response = new ResponseItemModel - { - Data = Account.Instruments[message.Name].Points.LastOrDefault() - }; - - return Task.FromResult(response); - } - /// /// Get option chains /// @@ -180,6 +160,11 @@ public override Task>> GetOptions(OptionMes throw new NotImplementedException(); } + /// + /// Quotes + /// + /// + /// public override Task>> GetPoints(PointMessageModel message) { var response = new ResponseItemModel> @@ -190,25 +175,35 @@ public override Task>> GetPoints(PointMessag return Task.FromResult(response); } - public override async Task> SendOrders(params OrderModel[] orders) + /// + /// Send orders + /// + /// + /// + public override async Task> CreateOrders(params OrderModel[] orders) { var response = new ResponseMapModel(); foreach (var order in orders) { - response.Items.Add(await SendOrder(order)); + response.Items.Add(await CreateOrder(order)); } return response; } - public override async Task> CancelOrders(params OrderModel[] orders) + /// + /// Cancel orders + /// + /// + /// + public override async Task> DeleteOrders(params OrderModel[] orders) { var response = new ResponseMapModel(); foreach (var order in orders) { - response.Items.Add(await CancelOrder(order)); + response.Items.Add(await DeleteOrder(order)); } return response; @@ -218,11 +213,11 @@ public override async Task> CancelOrders(params Ord /// Sync open balance, order, and positions /// /// - public async Task GetAccountData() + protected async Task GetAccountData() { - var account = await SendData("/v2/account"); - var positions = await SendData("/v2/positions"); - var orders = await SendData("/v2/orders"); + var account = await SendData("/v2/account"); + var positions = await SendData("/v2/positions"); + var orders = await SendData("/v2/orders"); try { @@ -308,7 +303,7 @@ protected void ProcessPoint(string content) try { var streamPoint = JsonSerializer - .Deserialize(content, _sender.Options) + .Deserialize(content, _sender.Options) .FirstOrDefault(); var instrument = Account.Instruments.Get(streamPoint.Symbol) ?? new Instrument(); @@ -342,7 +337,7 @@ protected void ProcessTrade(string content) try { var order = JsonSerializer - .Deserialize(content, _sender.Options) + .Deserialize(content, _sender.Options) .FirstOrDefault(); } catch (Exception e) @@ -357,14 +352,15 @@ protected void ProcessTrade(string content) /// /// /// - /// + /// /// protected async Task> SendData( string source, HttpMethod verb = null, - Hashtable inputs = null) + Hashtable query = null, + object content = null) { - inputs ??= []; + query ??= []; verb ??= HttpMethod.Get; var uri = new UriBuilder(DataUri) @@ -379,19 +375,17 @@ protected void ProcessTrade(string content) switch (true) { - case true when Equals(verb, HttpMethod.Get): uri.Query = inputs.ToQuery(); break; + case true when Equals(verb, HttpMethod.Get): uri.Query = query.ToQuery(); break; case true when Equals(verb, HttpMethod.Put): case true when Equals(verb, HttpMethod.Post): - case true when Equals(verb, HttpMethod.Patch): message.Content = new StringContent(JsonSerializer.Serialize(inputs)); break; + case true when Equals(verb, HttpMethod.Patch): message.Content = new StringContent(JsonSerializer.Serialize(content)); break; } message.RequestUri = uri.Uri; message.Headers.Add("APCA-API-KEY-ID", ConsumerKey); message.Headers.Add("APCA-API-SECRET-KEY", ConsumerSecret); - var service = InstanceService.Instance; - - return await service.Send(message, service.Options); + return await _sender.Send(message, _sender.Options); } /// @@ -399,14 +393,14 @@ protected void ProcessTrade(string content) /// /// /// - protected async Task> SendOrder(OrderModel order) + protected async Task> CreateOrder(OrderModel order) { var inResponse = new ResponseItemModel(); try { var exOrder = GetExternalOrder(order); - var exResponse = await SendData("/v2/orders", HttpMethod.Post); + var exResponse = await SendData("/v2/orders", HttpMethod.Post, null, exOrder); inResponse.Data = order; inResponse.Data.Transaction.Id = $"{exResponse.Data.OrderId}"; @@ -433,13 +427,13 @@ protected async Task> SendOrder(OrderModel order) /// /// /// - protected async Task> CancelOrder(OrderModel order) + protected async Task> DeleteOrder(OrderModel order) { var inResponse = new ResponseItemModel(); try { - var exResponse = await SendData($"/v2/orders/{order.Transaction.Id}", HttpMethod.Delete); + var exResponse = await SendData($"/v2/orders/{order.Transaction.Id}", HttpMethod.Delete); inResponse.Data = order; inResponse.Data.Transaction.Id = $"{exResponse.Data.OrderId}"; @@ -466,10 +460,10 @@ protected async Task> CancelOrder(OrderModel order /// /// /// - protected JsonNewOrder GetExternalOrder(OrderModel order) + protected OrderCreationMessage GetExternalOrder(OrderModel order) { var action = order.Transaction; - var message = new JsonNewOrder + var message = new OrderCreationMessage { Quantity = action.Volume, Symbol = action.Instrument.Name, @@ -524,8 +518,8 @@ protected string GetExternalTimeSpan(OrderTimeSpanEnum span) case OrderTimeSpanEnum.Fok: return "fok"; case OrderTimeSpanEnum.Gtc: return "gtc"; case OrderTimeSpanEnum.Ioc: return "ioc"; - case OrderTimeSpanEnum.Omo: return "opg"; - case OrderTimeSpanEnum.Omc: return "cls"; + case OrderTimeSpanEnum.Am: return "opg"; + case OrderTimeSpanEnum.Pm: return "cls"; } return null; @@ -537,7 +531,7 @@ protected string GetExternalTimeSpan(OrderTimeSpanEnum span) /// /// /// - protected JsonNewOrderAdvancedAttributes GetExternalBracket(OrderModel order, double direction) + protected OrderAdvancedAttributesMessage GetExternalBracket(OrderModel order, double direction) { var nextOrder = order .Orders @@ -545,7 +539,7 @@ protected JsonNewOrderAdvancedAttributes GetExternalBracket(OrderModel order, do if (nextOrder is not null) { - return new JsonNewOrderAdvancedAttributes { StopPrice = nextOrder.Price }; + return new OrderAdvancedAttributesMessage { StopPrice = nextOrder.Price }; } return null; @@ -556,7 +550,7 @@ protected JsonNewOrderAdvancedAttributes GetExternalBracket(OrderModel order, do /// /// /// - protected OrderModel GetInternalOrder(JsonOrder order) + protected OrderModel GetInternalOrder(OrderMessage order) { var instrument = new Instrument { @@ -609,7 +603,7 @@ protected OrderModel GetInternalOrder(JsonOrder order) /// /// /// - protected PositionModel GetInternalPosition(JsonPosition position) + protected PositionModel GetInternalPosition(PositionMessage position) { var instrument = new Instrument { @@ -724,8 +718,8 @@ protected OrderTimeSpanEnum GetInternalTimeSpan(string span) case "fok": return OrderTimeSpanEnum.Fok; case "gtc": return OrderTimeSpanEnum.Gtc; case "ioc": return OrderTimeSpanEnum.Ioc; - case "opg": return OrderTimeSpanEnum.Omo; - case "cls": return OrderTimeSpanEnum.Omc; + case "opg": return OrderTimeSpanEnum.Am; + case "cls": return OrderTimeSpanEnum.Pm; } return OrderTimeSpanEnum.None; diff --git a/Gateways/Alpaca/Libs/Alpaca.csproj b/Gateways/Alpaca/Libs/Alpaca.csproj index 0414b45c6..e981b8fee 100644 --- a/Gateways/Alpaca/Libs/Alpaca.csproj +++ b/Gateways/Alpaca/Libs/Alpaca.csproj @@ -7,7 +7,7 @@ - + diff --git a/Gateways/Alpaca/Libs/Messages/JsonAccountActivity.cs b/Gateways/Alpaca/Libs/Messages/AccountActivityMessage.cs similarity index 93% rename from Gateways/Alpaca/Libs/Messages/JsonAccountActivity.cs rename to Gateways/Alpaca/Libs/Messages/AccountActivityMessage.cs index c46fa6cae..9b284c91a 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAccountActivity.cs +++ b/Gateways/Alpaca/Libs/Messages/AccountActivityMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonAccountActivity +public class AccountActivityMessage { [JsonPropertyName("activity_type")] public string ActivityType { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAccountConfiguration.cs b/Gateways/Alpaca/Libs/Messages/AccountConfigurationMessage.cs similarity index 90% rename from Gateways/Alpaca/Libs/Messages/JsonAccountConfiguration.cs rename to Gateways/Alpaca/Libs/Messages/AccountConfigurationMessage.cs index 7d93f1928..95c7c3578 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAccountConfiguration.cs +++ b/Gateways/Alpaca/Libs/Messages/AccountConfigurationMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonAccountConfiguration +public class AccountConfigurationMessage { [JsonPropertyName("dtbp_check")] public string DayTradeMarginCallProtection { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAccount.cs b/Gateways/Alpaca/Libs/Messages/AccountMessage.cs similarity index 95% rename from Gateways/Alpaca/Libs/Messages/JsonAccount.cs rename to Gateways/Alpaca/Libs/Messages/AccountMessage.cs index 74e1db33b..40b050906 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAccount.cs +++ b/Gateways/Alpaca/Libs/Messages/AccountMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonAccount +public class AccountMessage { [JsonPropertyName("id")] public string AccountId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonActiveStock.cs b/Gateways/Alpaca/Libs/Messages/ActiveStockMessage.cs similarity index 85% rename from Gateways/Alpaca/Libs/Messages/JsonActiveStock.cs rename to Gateways/Alpaca/Libs/Messages/ActiveStockMessage.cs index b754401bc..9fa877dea 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonActiveStock.cs +++ b/Gateways/Alpaca/Libs/Messages/ActiveStockMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonActiveStock +public class ActiveStockMessage { [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonActiveStocks.cs b/Gateways/Alpaca/Libs/Messages/ActiveStocksMessage.cs similarity index 56% rename from Gateways/Alpaca/Libs/Messages/JsonActiveStocks.cs rename to Gateways/Alpaca/Libs/Messages/ActiveStocksMessage.cs index 86491fbe2..57ce40eb4 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonActiveStocks.cs +++ b/Gateways/Alpaca/Libs/Messages/ActiveStocksMessage.cs @@ -3,8 +3,8 @@ namespace Alpaca.Markets; -public class JsonActiveStocks +public class ActiveStocksMessage { [JsonPropertyName("most_actives")] - public List MostActives { get; set; } = []; + public List MostActives { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAnnouncement.cs b/Gateways/Alpaca/Libs/Messages/AnnouncementMessage.cs similarity index 93% rename from Gateways/Alpaca/Libs/Messages/JsonAnnouncement.cs rename to Gateways/Alpaca/Libs/Messages/AnnouncementMessage.cs index d050f6556..949dda0c2 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAnnouncement.cs +++ b/Gateways/Alpaca/Libs/Messages/AnnouncementMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonAnnouncement +public class AnnouncementMessage { [JsonPropertyName("id")] public string Id { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAsset.cs b/Gateways/Alpaca/Libs/Messages/AssetMessage.cs similarity index 94% rename from Gateways/Alpaca/Libs/Messages/JsonAsset.cs rename to Gateways/Alpaca/Libs/Messages/AssetMessage.cs index 63895dc02..a78742796 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAsset.cs +++ b/Gateways/Alpaca/Libs/Messages/AssetMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonAsset +public class AssetMessage { [JsonPropertyName("id")] public string AssetId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuctionEntry.cs b/Gateways/Alpaca/Libs/Messages/AuctionEntryMessage.cs similarity index 88% rename from Gateways/Alpaca/Libs/Messages/JsonAuctionEntry.cs rename to Gateways/Alpaca/Libs/Messages/AuctionEntryMessage.cs index 08d514fa2..8ecfcaee2 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuctionEntry.cs +++ b/Gateways/Alpaca/Libs/Messages/AuctionEntryMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonAuctionEntry +public class AuctionEntryMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuction.cs b/Gateways/Alpaca/Libs/Messages/AuctionMessage.cs similarity index 50% rename from Gateways/Alpaca/Libs/Messages/JsonAuction.cs rename to Gateways/Alpaca/Libs/Messages/AuctionMessage.cs index d863426b8..2b661cdce 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuction.cs +++ b/Gateways/Alpaca/Libs/Messages/AuctionMessage.cs @@ -4,23 +4,23 @@ namespace Alpaca.Markets; -public class JsonAuction +public class AuctionMessage { [JsonPropertyName("d")] internal DateTime? DateTime { get; set; } [JsonPropertyName("o")] - internal List OpeningsList { get; set; } = []; + internal List OpeningsList { get; set; } = []; [JsonPropertyName("c")] - internal List ClosingsList { get; set; } = []; + internal List ClosingsList { get; set; } = []; [JsonIgnore] public string Symbol { get; set; } [JsonIgnore] - public List Openings { get; set; } = []; + public List Openings { get; set; } = []; [JsonIgnore] - public List Closings { get; set; } = []; + public List Closings { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuctionsPage.cs b/Gateways/Alpaca/Libs/Messages/AuctionsPageMessage.cs similarity index 64% rename from Gateways/Alpaca/Libs/Messages/JsonAuctionsPage.cs rename to Gateways/Alpaca/Libs/Messages/AuctionsPageMessage.cs index 5d01b8f31..b54ccb648 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuctionsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/AuctionsPageMessage.cs @@ -3,10 +3,10 @@ namespace Alpaca.Markets; -public class JsonAuctionsPage +public class AuctionsPageMessage { [JsonPropertyName("auctions")] - public List ItemsList { get; set; } = []; + public List ItemsList { get; set; } = []; [JsonPropertyName("symbol")] public string Symbol { get; set; } @@ -15,5 +15,5 @@ public class JsonAuctionsPage public string NextPageToken { get; set; } [JsonIgnore] - public List Items { get; set; } = []; + public List Items { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuthRequest.cs b/Gateways/Alpaca/Libs/Messages/AuthRequestMessage.cs similarity index 89% rename from Gateways/Alpaca/Libs/Messages/JsonAuthRequest.cs rename to Gateways/Alpaca/Libs/Messages/AuthRequestMessage.cs index d080500af..2496dc6c3 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuthRequest.cs +++ b/Gateways/Alpaca/Libs/Messages/AuthRequestMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonAuthRequest +public class AuthRequestMessage { public class JsonData { diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuthResponse.cs b/Gateways/Alpaca/Libs/Messages/AuthResponseMessage.cs similarity index 82% rename from Gateways/Alpaca/Libs/Messages/JsonAuthResponse.cs rename to Gateways/Alpaca/Libs/Messages/AuthResponseMessage.cs index a73aca2ef..df02dabf4 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuthResponse.cs +++ b/Gateways/Alpaca/Libs/Messages/AuthResponseMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonAuthResponse +public class AuthResponseMessage { [JsonPropertyName("status")] public string Status { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonAuthentication.cs b/Gateways/Alpaca/Libs/Messages/AuthenticationMessage.cs similarity index 84% rename from Gateways/Alpaca/Libs/Messages/JsonAuthentication.cs rename to Gateways/Alpaca/Libs/Messages/AuthenticationMessage.cs index b3d939f68..6eb072208 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonAuthentication.cs +++ b/Gateways/Alpaca/Libs/Messages/AuthenticationMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonAuthentication +public class AuthenticationMessage { [JsonPropertyName("action")] public string Action { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonBarsPage.cs b/Gateways/Alpaca/Libs/Messages/BarsPageMessage.cs similarity index 63% rename from Gateways/Alpaca/Libs/Messages/JsonBarsPage.cs rename to Gateways/Alpaca/Libs/Messages/BarsPageMessage.cs index 29e2f862f..9ecd00d77 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonBarsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/BarsPageMessage.cs @@ -3,10 +3,10 @@ namespace Alpaca.Markets; -public class JsonBarsPage +public class BarsPageMessage { [JsonPropertyName("bars")] - public List ItemsList { get; set; } = []; + public List ItemsList { get; set; } = []; [JsonPropertyName("symbol")] public string Symbol { get; set; } @@ -15,5 +15,5 @@ public class JsonBarsPage public string NextPageToken { get; set; } [JsonIgnore] - public List Items { get; set; } = []; + public List Items { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonCalendar.cs b/Gateways/Alpaca/Libs/Messages/CalendarMessage.cs similarity index 91% rename from Gateways/Alpaca/Libs/Messages/JsonCalendar.cs rename to Gateways/Alpaca/Libs/Messages/CalendarMessage.cs index 368111e9d..fbdfefedd 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonCalendar.cs +++ b/Gateways/Alpaca/Libs/Messages/CalendarMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonCalendar +public class CalendarMessage { [JsonPropertyName("date")] public DateOnly? TradingDate { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonClock.cs b/Gateways/Alpaca/Libs/Messages/ClockMessage.cs similarity index 89% rename from Gateways/Alpaca/Libs/Messages/JsonClock.cs rename to Gateways/Alpaca/Libs/Messages/ClockMessage.cs index a345db994..5c2c18971 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonClock.cs +++ b/Gateways/Alpaca/Libs/Messages/ClockMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonClock +public class ClockMessage { [JsonPropertyName("timestamp")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonConnectionSuccess.cs b/Gateways/Alpaca/Libs/Messages/ConnectionSuccessMessage.cs similarity index 74% rename from Gateways/Alpaca/Libs/Messages/JsonConnectionSuccess.cs rename to Gateways/Alpaca/Libs/Messages/ConnectionSuccessMessage.cs index ed7e79f5a..d9f69b520 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonConnectionSuccess.cs +++ b/Gateways/Alpaca/Libs/Messages/ConnectionSuccessMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonConnectionSuccess +public class ConnectionSuccessMessage { [JsonPropertyName("msg")] public string Status { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonCorrection.cs b/Gateways/Alpaca/Libs/Messages/CorrectionMessage.cs similarity index 86% rename from Gateways/Alpaca/Libs/Messages/JsonCorrection.cs rename to Gateways/Alpaca/Libs/Messages/CorrectionMessage.cs index 3da7a1673..0a393fc1d 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonCorrection.cs +++ b/Gateways/Alpaca/Libs/Messages/CorrectionMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonCorrection +public class CorrectionMessage { [JsonPropertyName("x")] public string Exchange { get; set; } @@ -39,5 +39,5 @@ public class JsonCorrection public string TakerSide { get; set; } [JsonIgnore] - public JsonRealTimeTrade CorrectedTrade { get; set; } + public RealTimeTradeMessage CorrectedTrade { get; set; } } diff --git a/Gateways/Alpaca/Libs/Messages/CryptoSnapshotMessage.cs b/Gateways/Alpaca/Libs/Messages/CryptoSnapshotMessage.cs new file mode 100644 index 000000000..de6807db8 --- /dev/null +++ b/Gateways/Alpaca/Libs/Messages/CryptoSnapshotMessage.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace Alpaca.Markets; + +public class CryptoSnapshotMessage +{ + [JsonPropertyName("latestQuote")] + public HistoricalCryptoQuoteMessage JsonQuote { get; set; } + + [JsonPropertyName("latestTrade")] + public HistoricalTradeMessage JsonTrade { get; set; } + + [JsonPropertyName("minuteBar")] + public HistoricalBarMessage JsonMinuteBar { get; set; } + + [JsonPropertyName("dailyBar")] + public HistoricalBarMessage JsonCurrentDailyBar { get; set; } + + [JsonPropertyName("prevDailyBar")] + public HistoricalBarMessage JsonPreviousDailyBar { get; set; } + + [JsonPropertyName("symbol")] + public string Symbol { get; set; } +} diff --git a/Gateways/Alpaca/Libs/Messages/JsonError.cs b/Gateways/Alpaca/Libs/Messages/ErrorMessage.cs similarity index 92% rename from Gateways/Alpaca/Libs/Messages/JsonError.cs rename to Gateways/Alpaca/Libs/Messages/ErrorMessage.cs index 333d1cac2..8a671c67b 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonError.cs +++ b/Gateways/Alpaca/Libs/Messages/ErrorMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonError +public class ErrorMessage { [JsonPropertyName("code")] public int? Code { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonHistoricalBar.cs b/Gateways/Alpaca/Libs/Messages/HistoricalBarMessage.cs similarity index 90% rename from Gateways/Alpaca/Libs/Messages/JsonHistoricalBar.cs rename to Gateways/Alpaca/Libs/Messages/HistoricalBarMessage.cs index 43b1c6b0a..929a7abe3 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonHistoricalBar.cs +++ b/Gateways/Alpaca/Libs/Messages/HistoricalBarMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonHistoricalBar +public class HistoricalBarMessage { [JsonIgnore] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonHistoricalCryptoQuote.cs b/Gateways/Alpaca/Libs/Messages/HistoricalCryptoQuoteMessage.cs similarity index 88% rename from Gateways/Alpaca/Libs/Messages/JsonHistoricalCryptoQuote.cs rename to Gateways/Alpaca/Libs/Messages/HistoricalCryptoQuoteMessage.cs index b8e361eda..b0ecee88e 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonHistoricalCryptoQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/HistoricalCryptoQuoteMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonHistoricalCryptoQuote +public class HistoricalCryptoQuoteMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonHistoricalOrderBook.cs b/Gateways/Alpaca/Libs/Messages/HistoricalOrderBookMessage.cs similarity index 50% rename from Gateways/Alpaca/Libs/Messages/JsonHistoricalOrderBook.cs rename to Gateways/Alpaca/Libs/Messages/HistoricalOrderBookMessage.cs index fc7e07799..fbff547b3 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonHistoricalOrderBook.cs +++ b/Gateways/Alpaca/Libs/Messages/HistoricalOrderBookMessage.cs @@ -4,23 +4,23 @@ namespace Alpaca.Markets; -public class JsonHistoricalOrderBook +public class HistoricalOrderBookMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } [JsonPropertyName("b")] - public List BidsList { get; set; } = []; + public List BidsList { get; set; } = []; [JsonPropertyName("a")] - public List AsksList { get; set; } = []; + public List AsksList { get; set; } = []; [JsonIgnore] public string Symbol { get; set; } [JsonIgnore] - public List Bids { get; set; } = []; + public List Bids { get; set; } = []; [JsonIgnore] - public List Asks { get; set; } = []; + public List Asks { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonHistoricalQuote.cs b/Gateways/Alpaca/Libs/Messages/HistoricalQuoteMessage.cs similarity index 91% rename from Gateways/Alpaca/Libs/Messages/JsonHistoricalQuote.cs rename to Gateways/Alpaca/Libs/Messages/HistoricalQuoteMessage.cs index 4090cb49b..7d312a2d0 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonHistoricalQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/HistoricalQuoteMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonHistoricalQuote +public class HistoricalQuoteMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonHistoricalTrade.cs b/Gateways/Alpaca/Libs/Messages/HistoricalTradeMessage.cs similarity index 91% rename from Gateways/Alpaca/Libs/Messages/JsonHistoricalTrade.cs rename to Gateways/Alpaca/Libs/Messages/HistoricalTradeMessage.cs index 2b7de3fd8..c15e03759 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonHistoricalTrade.cs +++ b/Gateways/Alpaca/Libs/Messages/HistoricalTradeMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonHistoricalTrade +public class HistoricalTradeMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonCryptoSnapshot.cs b/Gateways/Alpaca/Libs/Messages/JsonCryptoSnapshot.cs deleted file mode 100644 index 0362c66e5..000000000 --- a/Gateways/Alpaca/Libs/Messages/JsonCryptoSnapshot.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Alpaca.Markets; - -public class JsonCryptoSnapshot -{ - [JsonPropertyName("latestQuote")] - public JsonHistoricalCryptoQuote JsonQuote { get; set; } - - [JsonPropertyName("latestTrade")] - public JsonHistoricalTrade JsonTrade { get; set; } - - [JsonPropertyName("minuteBar")] - public JsonHistoricalBar JsonMinuteBar { get; set; } - - [JsonPropertyName("dailyBar")] - public JsonHistoricalBar JsonCurrentDailyBar { get; set; } - - [JsonPropertyName("prevDailyBar")] - public JsonHistoricalBar JsonPreviousDailyBar { get; set; } - - [JsonPropertyName("symbol")] - public string Symbol { get; set; } -} diff --git a/Gateways/Alpaca/Libs/Messages/JsonMarketMovers.cs b/Gateways/Alpaca/Libs/Messages/JsonMarketMovers.cs deleted file mode 100644 index 56dc6af18..000000000 --- a/Gateways/Alpaca/Libs/Messages/JsonMarketMovers.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Alpaca.Markets; - -public class JsonMarketMovers -{ - [JsonPropertyName("losers")] - public List LosersList { get; set; } = []; - - [JsonPropertyName("gainers")] - public List GainersList { get; set; } = []; -} diff --git a/Gateways/Alpaca/Libs/Messages/JsonOptionSnapshot.cs b/Gateways/Alpaca/Libs/Messages/JsonOptionSnapshot.cs deleted file mode 100644 index 8d3a46a97..000000000 --- a/Gateways/Alpaca/Libs/Messages/JsonOptionSnapshot.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Alpaca.Markets; - -public class JsonOptionSnapshot -{ - [JsonPropertyName("latestQuote")] - public JsonOptionQuote JsonQuote { get; set; } - - [JsonPropertyName("latestTrade")] - public JsonOptionTrade JsonTrade { get; set; } -} diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeOrderBook.cs b/Gateways/Alpaca/Libs/Messages/JsonRealTimeOrderBook.cs deleted file mode 100644 index fc397ac4f..000000000 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeOrderBook.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Alpaca.Markets; - -public class JsonRealTimeOrderBook -{ - [JsonPropertyName("x")] - public string Exchange { get; set; } - - [JsonPropertyName("b")] - public List BidsList { get; set; } = []; - - [JsonPropertyName("a")] - public List AsksList { get; set; } = []; - - [JsonPropertyName("r")] - public bool IsReset { get; set; } - - [JsonIgnore] - public List Bids { get; set; } = []; - - [JsonIgnore] - public List Asks { get; set; } = []; -} diff --git a/Gateways/Alpaca/Libs/Messages/JsonSnapshot.cs b/Gateways/Alpaca/Libs/Messages/JsonSnapshot.cs deleted file mode 100644 index 80a977dcc..000000000 --- a/Gateways/Alpaca/Libs/Messages/JsonSnapshot.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Alpaca.Markets; - -public class JsonSnapshot -{ - [JsonPropertyName("latestQuote")] - public JsonHistoricalQuote JsonQuote { get; set; } - - [JsonPropertyName("latestTrade")] - public JsonHistoricalTrade JsonTrade { get; set; } - - [JsonPropertyName("minuteBar")] - public JsonHistoricalBar JsonMinuteBar { get; set; } - - [JsonPropertyName("dailyBar")] - public JsonHistoricalBar JsonCurrentDailyBar { get; set; } - - [JsonPropertyName("prevDailyBar")] - public JsonHistoricalBar JsonPreviousDailyBar { get; set; } - - [JsonPropertyName("symbol")] - public string Symbol { get; set; } -} diff --git a/Gateways/Alpaca/Libs/Messages/JsonLatestBar.cs b/Gateways/Alpaca/Libs/Messages/LatestBarMessage.cs similarity index 64% rename from Gateways/Alpaca/Libs/Messages/JsonLatestBar.cs rename to Gateways/Alpaca/Libs/Messages/LatestBarMessage.cs index c85c40676..cf1755a4c 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLatestBar.cs +++ b/Gateways/Alpaca/Libs/Messages/LatestBarMessage.cs @@ -2,10 +2,10 @@ namespace Alpaca.Markets; -public class JsonLatestBar +public class LatestBarMessage { [JsonPropertyName("bar")] - public JsonHistoricalBar Nested { get; set; } + public HistoricalBarMessage Nested { get; set; } [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonLatestBestBidOffer.cs b/Gateways/Alpaca/Libs/Messages/LatestBestBidOfferMessage.cs similarity index 61% rename from Gateways/Alpaca/Libs/Messages/JsonLatestBestBidOffer.cs rename to Gateways/Alpaca/Libs/Messages/LatestBestBidOfferMessage.cs index 87110d724..910e32835 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLatestBestBidOffer.cs +++ b/Gateways/Alpaca/Libs/Messages/LatestBestBidOfferMessage.cs @@ -2,10 +2,10 @@ namespace Alpaca.Markets; -public class JsonLatestBestBidOffer +public class LatestBestBidOfferMessage { [JsonPropertyName("xbbo")] - public JsonHistoricalQuote Nested { get; set; } + public HistoricalQuoteMessage Nested { get; set; } [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonLatestData.cs b/Gateways/Alpaca/Libs/Messages/LatestDataMessage.cs similarity index 65% rename from Gateways/Alpaca/Libs/Messages/JsonLatestData.cs rename to Gateways/Alpaca/Libs/Messages/LatestDataMessage.cs index 04bbfe768..4c4f9d5a6 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLatestData.cs +++ b/Gateways/Alpaca/Libs/Messages/LatestDataMessage.cs @@ -3,13 +3,13 @@ namespace Alpaca.Markets; -public class JsonLatestData +public class LatestDataMessage { [JsonPropertyName("quotes")] public Dictionary Quotes { get; set; } = []; [JsonPropertyName("bars")] - public Dictionary Bars { get; set; } = []; + public Dictionary Bars { get; set; } = []; [JsonPropertyName("trades")] public Dictionary Trades { get; set; } = []; @@ -18,5 +18,5 @@ public class JsonLatestData public Dictionary Snapshots { get; set; } = []; [JsonPropertyName("orderbooks")] - public Dictionary OrderBooks { get; set; } = []; + public Dictionary OrderBooks { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonLatestQuote.cs b/Gateways/Alpaca/Libs/Messages/LatestQuoteMessage.cs similarity index 79% rename from Gateways/Alpaca/Libs/Messages/JsonLatestQuote.cs rename to Gateways/Alpaca/Libs/Messages/LatestQuoteMessage.cs index bac23e056..d7230c39e 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLatestQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/LatestQuoteMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonLatestQuote +public class LatestQuoteMessage { [JsonPropertyName("quote")] public TQuote Nested { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonLatestTrade.cs b/Gateways/Alpaca/Libs/Messages/LatestTradeMessage.cs similarity index 63% rename from Gateways/Alpaca/Libs/Messages/JsonLatestTrade.cs rename to Gateways/Alpaca/Libs/Messages/LatestTradeMessage.cs index b1d07f74f..261b36ae9 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLatestTrade.cs +++ b/Gateways/Alpaca/Libs/Messages/LatestTradeMessage.cs @@ -2,10 +2,10 @@ namespace Alpaca.Markets; -public class JsonLatestTrade +public class LatestTradeMessage { [JsonPropertyName("trade")] - public JsonHistoricalTrade Nested { get; set; } + public HistoricalTradeMessage Nested { get; set; } [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonLimitUpLimitDown.cs b/Gateways/Alpaca/Libs/Messages/LimitUpLimitDownMessage.cs similarity index 86% rename from Gateways/Alpaca/Libs/Messages/JsonLimitUpLimitDown.cs rename to Gateways/Alpaca/Libs/Messages/LimitUpLimitDownMessage.cs index 55bf4f8c0..4a955f4ee 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonLimitUpLimitDown.cs +++ b/Gateways/Alpaca/Libs/Messages/LimitUpLimitDownMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonLimitUpLimitDown +public class LimitUpLimitDownMessage { [JsonPropertyName("u")] public double? LimitUpPrice { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonListenRequest.cs b/Gateways/Alpaca/Libs/Messages/ListenRequestMessage.cs similarity index 87% rename from Gateways/Alpaca/Libs/Messages/JsonListenRequest.cs rename to Gateways/Alpaca/Libs/Messages/ListenRequestMessage.cs index 7e049a500..ec735318b 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonListenRequest.cs +++ b/Gateways/Alpaca/Libs/Messages/ListenRequestMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonListenRequest +public class ListenRequestMessage { public class JsonData { diff --git a/Gateways/Alpaca/Libs/Messages/JsonMarketMover.cs b/Gateways/Alpaca/Libs/Messages/MarketMoverMessage.cs similarity index 87% rename from Gateways/Alpaca/Libs/Messages/JsonMarketMover.cs rename to Gateways/Alpaca/Libs/Messages/MarketMoverMessage.cs index 42ecf0201..6b6aec952 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonMarketMover.cs +++ b/Gateways/Alpaca/Libs/Messages/MarketMoverMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonMarketMover +public class MarketMoverMessage { [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/MarketMoversMessage.cs b/Gateways/Alpaca/Libs/Messages/MarketMoversMessage.cs new file mode 100644 index 000000000..6e90748ae --- /dev/null +++ b/Gateways/Alpaca/Libs/Messages/MarketMoversMessage.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Alpaca.Markets; + +public class MarketMoversMessage +{ + [JsonPropertyName("losers")] + public List LosersList { get; set; } = []; + + [JsonPropertyName("gainers")] + public List GainersList { get; set; } = []; +} diff --git a/Gateways/Alpaca/Libs/Messages/JsonMultiAuctionsPage.cs b/Gateways/Alpaca/Libs/Messages/MultiAuctionsPageMessage.cs similarity index 52% rename from Gateways/Alpaca/Libs/Messages/JsonMultiAuctionsPage.cs rename to Gateways/Alpaca/Libs/Messages/MultiAuctionsPageMessage.cs index 5353f8107..186b915ea 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonMultiAuctionsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/MultiAuctionsPageMessage.cs @@ -3,14 +3,14 @@ namespace Alpaca.Markets; -public class JsonMultiAuctionsPage +public class MultiAuctionsPageMessage { [JsonPropertyName("auctions")] - public Dictionary> ItemsDictionary { get; set; } = []; + public Dictionary> ItemsDictionary { get; set; } = []; [JsonPropertyName("next_page_token")] public string NextPageToken { get; set; } [JsonIgnore] - public Dictionary> Items { get; set; } = []; + public Dictionary> Items { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonMultiBarsPage.cs b/Gateways/Alpaca/Libs/Messages/MultiBarsPageMessage.cs similarity index 52% rename from Gateways/Alpaca/Libs/Messages/JsonMultiBarsPage.cs rename to Gateways/Alpaca/Libs/Messages/MultiBarsPageMessage.cs index c3eca84f7..a704f67ab 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonMultiBarsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/MultiBarsPageMessage.cs @@ -4,14 +4,14 @@ namespace Alpaca.Markets; -public class JsonMultiBarsPage +public class MultiBarsPageMessage { [JsonPropertyName("bars")] - public Dictionary> ItemsDictionary { get; set; } = []; + public Dictionary> ItemsDictionary { get; set; } = []; [JsonPropertyName("next_page_token")] public string NextPageToken { get; set; } [JsonIgnore] - public Dictionary> Items { get; set; } = []; + public Dictionary> Items { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonMultiQuotesPage.cs b/Gateways/Alpaca/Libs/Messages/MultiQuotesPageMessage.cs similarity index 86% rename from Gateways/Alpaca/Libs/Messages/JsonMultiQuotesPage.cs rename to Gateways/Alpaca/Libs/Messages/MultiQuotesPageMessage.cs index 517740831..1474f531c 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonMultiQuotesPage.cs +++ b/Gateways/Alpaca/Libs/Messages/MultiQuotesPageMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonMultiQuotesPage +public class MultiQuotesPageMessage { [JsonPropertyName("quotes")] public Dictionary> ItemsDictionary { get; set; } = []; diff --git a/Gateways/Alpaca/Libs/Messages/JsonMultiTradesPage.cs b/Gateways/Alpaca/Libs/Messages/MultiTradesPageMessage.cs similarity index 86% rename from Gateways/Alpaca/Libs/Messages/JsonMultiTradesPage.cs rename to Gateways/Alpaca/Libs/Messages/MultiTradesPageMessage.cs index ae40f9b1b..e9a9330a2 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonMultiTradesPage.cs +++ b/Gateways/Alpaca/Libs/Messages/MultiTradesPageMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonMultiTradesPage +public class MultiTradesPageMessage { [JsonPropertyName("trades")] public Dictionary> ItemsDictionary { get; set; } = []; diff --git a/Gateways/Alpaca/Libs/Messages/JsonNewsArticle.cs b/Gateways/Alpaca/Libs/Messages/NewsArticleMessage.cs similarity index 93% rename from Gateways/Alpaca/Libs/Messages/JsonNewsArticle.cs rename to Gateways/Alpaca/Libs/Messages/NewsArticleMessage.cs index fcfd4f40e..cc613ea18 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonNewsArticle.cs +++ b/Gateways/Alpaca/Libs/Messages/NewsArticleMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonNewsArticle +public class NewsArticleMessage { public class Image { diff --git a/Gateways/Alpaca/Libs/Messages/JsonNewsPage.cs b/Gateways/Alpaca/Libs/Messages/NewsPageMessage.cs similarity index 67% rename from Gateways/Alpaca/Libs/Messages/JsonNewsPage.cs rename to Gateways/Alpaca/Libs/Messages/NewsPageMessage.cs index 8fc39fcb9..bd8e73923 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonNewsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/NewsPageMessage.cs @@ -3,10 +3,10 @@ namespace Alpaca.Markets; -public class JsonNewsPage +public class NewsPageMessage { [JsonPropertyName("news")] - public List ItemsList { get; set; } = []; + public List ItemsList { get; set; } = []; [JsonPropertyName("next_page_token")] public string NextPageToken { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOptionContract.cs b/Gateways/Alpaca/Libs/Messages/OptionContractMessage.cs similarity index 93% rename from Gateways/Alpaca/Libs/Messages/JsonOptionContract.cs rename to Gateways/Alpaca/Libs/Messages/OptionContractMessage.cs index e9f417e79..d1602e309 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOptionContract.cs +++ b/Gateways/Alpaca/Libs/Messages/OptionContractMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonOptionContract +public class OptionContractMessage { [JsonPropertyName("id")] public string ContractId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOptionContractsPage.cs b/Gateways/Alpaca/Libs/Messages/OptionContractsPageMessage.cs similarity index 55% rename from Gateways/Alpaca/Libs/Messages/JsonOptionContractsPage.cs rename to Gateways/Alpaca/Libs/Messages/OptionContractsPageMessage.cs index 7d64f4254..1b8ff95f1 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOptionContractsPage.cs +++ b/Gateways/Alpaca/Libs/Messages/OptionContractsPageMessage.cs @@ -3,8 +3,8 @@ namespace Alpaca.Markets; -public class JsonOptionContractsPage +public class OptionContractsPageMessage { [JsonPropertyName("option_contracts")] - public List Contracts { get; set; } = []; + public List Contracts { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOptionQuote.cs b/Gateways/Alpaca/Libs/Messages/OptionQuoteMessage.cs similarity index 90% rename from Gateways/Alpaca/Libs/Messages/JsonOptionQuote.cs rename to Gateways/Alpaca/Libs/Messages/OptionQuoteMessage.cs index fdcd9cc23..549a070d7 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOptionQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/OptionQuoteMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonOptionQuote +public class OptionQuoteMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/OptionSnapshotMessage.cs b/Gateways/Alpaca/Libs/Messages/OptionSnapshotMessage.cs new file mode 100644 index 000000000..9c1dc8ec6 --- /dev/null +++ b/Gateways/Alpaca/Libs/Messages/OptionSnapshotMessage.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Alpaca.Markets; + +public class OptionSnapshotMessage +{ + [JsonPropertyName("latestQuote")] + public OptionQuoteMessage JsonQuote { get; set; } + + [JsonPropertyName("latestTrade")] + public OptionTradeMessage JsonTrade { get; set; } +} diff --git a/Gateways/Alpaca/Libs/Messages/JsonOptionTrade.cs b/Gateways/Alpaca/Libs/Messages/OptionTradeMessage.cs similarity index 88% rename from Gateways/Alpaca/Libs/Messages/JsonOptionTrade.cs rename to Gateways/Alpaca/Libs/Messages/OptionTradeMessage.cs index edb398cb1..dfc999dac 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOptionTrade.cs +++ b/Gateways/Alpaca/Libs/Messages/OptionTradeMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonOptionTrade +public class OptionTradeMessage { [JsonPropertyName("t")] public DateTime? TimestampUtc { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOrderActionStatus.cs b/Gateways/Alpaca/Libs/Messages/OrderActionStatusMessage.cs similarity index 80% rename from Gateways/Alpaca/Libs/Messages/JsonOrderActionStatus.cs rename to Gateways/Alpaca/Libs/Messages/OrderActionStatusMessage.cs index ef3f47a95..830724064 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOrderActionStatus.cs +++ b/Gateways/Alpaca/Libs/Messages/OrderActionStatusMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonOrderActionStatus +public class OrderActionStatusMessage { [JsonPropertyName("id")] public string OrderId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonNewOrderAdvancedAttributes.cs b/Gateways/Alpaca/Libs/Messages/OrderAdvancedAttributesMessage.cs similarity index 80% rename from Gateways/Alpaca/Libs/Messages/JsonNewOrderAdvancedAttributes.cs rename to Gateways/Alpaca/Libs/Messages/OrderAdvancedAttributesMessage.cs index 4af82df7b..7f67e3826 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonNewOrderAdvancedAttributes.cs +++ b/Gateways/Alpaca/Libs/Messages/OrderAdvancedAttributesMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonNewOrderAdvancedAttributes +public class OrderAdvancedAttributesMessage { [JsonPropertyName("limit_price")] public double? LimitPrice { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOrderBookEntry.cs b/Gateways/Alpaca/Libs/Messages/OrderBookEntryMessage.cs similarity index 80% rename from Gateways/Alpaca/Libs/Messages/JsonOrderBookEntry.cs rename to Gateways/Alpaca/Libs/Messages/OrderBookEntryMessage.cs index 648f7fbd7..9bfd6e217 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOrderBookEntry.cs +++ b/Gateways/Alpaca/Libs/Messages/OrderBookEntryMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonOrderBookEntry +public class OrderBookEntryMessage { [JsonPropertyName("p")] public double? Price { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonNewOrder.cs b/Gateways/Alpaca/Libs/Messages/OrderCreationMessage.cs similarity index 84% rename from Gateways/Alpaca/Libs/Messages/JsonNewOrder.cs rename to Gateways/Alpaca/Libs/Messages/OrderCreationMessage.cs index a2a7bbbe2..c6ae43dc1 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonNewOrder.cs +++ b/Gateways/Alpaca/Libs/Messages/OrderCreationMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonNewOrder +public class OrderCreationMessage { [JsonPropertyName("symbol")] public string Symbol { get; set; } @@ -44,8 +44,8 @@ public class JsonNewOrder public string OrderClass { get; set; } [JsonPropertyName("take_profit")] - public JsonNewOrderAdvancedAttributes TakeProfit { get; set; } + public OrderAdvancedAttributesMessage TakeProfit { get; set; } [JsonPropertyName("stop_loss")] - public JsonNewOrderAdvancedAttributes StopLoss { get; set; } + public OrderAdvancedAttributesMessage StopLoss { get; set; } } diff --git a/Gateways/Alpaca/Libs/Messages/JsonOrder.cs b/Gateways/Alpaca/Libs/Messages/OrderMessage.cs similarity index 92% rename from Gateways/Alpaca/Libs/Messages/JsonOrder.cs rename to Gateways/Alpaca/Libs/Messages/OrderMessage.cs index b1fe6aec8..66b1bbc56 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonOrder.cs +++ b/Gateways/Alpaca/Libs/Messages/OrderMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonOrder +public class OrderMessage { [JsonPropertyName("id")] public string OrderId { get; set; } @@ -102,5 +102,5 @@ public class JsonOrder public string ReplacesOrderId { get; set; } [JsonPropertyName("legs")] - public List LegsList { get; set; } = []; + public List LegsList { get; set; } = []; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonPortfolioHistory.cs b/Gateways/Alpaca/Libs/Messages/PortfolioHistoryMessage.cs similarity index 92% rename from Gateways/Alpaca/Libs/Messages/JsonPortfolioHistory.cs rename to Gateways/Alpaca/Libs/Messages/PortfolioHistoryMessage.cs index 83c289dcb..9d434db62 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonPortfolioHistory.cs +++ b/Gateways/Alpaca/Libs/Messages/PortfolioHistoryMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonPortfolioHistory +public class PortfolioHistoryMessage { public class Item { diff --git a/Gateways/Alpaca/Libs/Messages/JsonPositionActionStatus.cs b/Gateways/Alpaca/Libs/Messages/PositionActionStatusMessage.cs similarity index 80% rename from Gateways/Alpaca/Libs/Messages/JsonPositionActionStatus.cs rename to Gateways/Alpaca/Libs/Messages/PositionActionStatusMessage.cs index 1d8b1ad75..e90367105 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonPositionActionStatus.cs +++ b/Gateways/Alpaca/Libs/Messages/PositionActionStatusMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonPositionActionStatus +public class PositionActionStatusMessage { [JsonPropertyName("symbol")] public string Symbol { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonPosition.cs b/Gateways/Alpaca/Libs/Messages/PositionMessage.cs similarity index 94% rename from Gateways/Alpaca/Libs/Messages/JsonPosition.cs rename to Gateways/Alpaca/Libs/Messages/PositionMessage.cs index 7a5c47e75..eb59b783f 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonPosition.cs +++ b/Gateways/Alpaca/Libs/Messages/PositionMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonPosition +public class PositionMessage { [JsonPropertyName("asset_id")] public string AssetId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonQuotesPage.cs b/Gateways/Alpaca/Libs/Messages/QuotesPageMessage.cs similarity index 87% rename from Gateways/Alpaca/Libs/Messages/JsonQuotesPage.cs rename to Gateways/Alpaca/Libs/Messages/QuotesPageMessage.cs index 55832a0c6..7cba8b7e9 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonQuotesPage.cs +++ b/Gateways/Alpaca/Libs/Messages/QuotesPageMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonQuotesPage +public class QuotesPageMessage { [JsonPropertyName("quotes")] public List ItemsList { get; set; } = []; diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeBar.cs b/Gateways/Alpaca/Libs/Messages/RealTimeBarMessage.cs similarity index 89% rename from Gateways/Alpaca/Libs/Messages/JsonRealTimeBar.cs rename to Gateways/Alpaca/Libs/Messages/RealTimeBarMessage.cs index 5021a8c03..523db1d6d 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeBar.cs +++ b/Gateways/Alpaca/Libs/Messages/RealTimeBarMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonRealTimeBar +public class RealTimeBarMessage { [JsonPropertyName("o")] public double? Open { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeBase.cs b/Gateways/Alpaca/Libs/Messages/RealTimeBaseMessage.cs similarity index 85% rename from Gateways/Alpaca/Libs/Messages/JsonRealTimeBase.cs rename to Gateways/Alpaca/Libs/Messages/RealTimeBaseMessage.cs index 0b3e0434e..61bcfd2ce 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeBase.cs +++ b/Gateways/Alpaca/Libs/Messages/RealTimeBaseMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonRealTimeBase +public class RealTimeBaseMessage { [JsonPropertyName("T")] public string Channel { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeCryptoQuote.cs b/Gateways/Alpaca/Libs/Messages/RealTimeCryptoQuoteMessage.cs similarity index 89% rename from Gateways/Alpaca/Libs/Messages/JsonRealTimeCryptoQuote.cs rename to Gateways/Alpaca/Libs/Messages/RealTimeCryptoQuoteMessage.cs index e6956474c..1b901eb27 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeCryptoQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/RealTimeCryptoQuoteMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonRealTimeCryptoQuote +public class RealTimeCryptoQuoteMessage { [JsonPropertyName("x")] public string BidExchange { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/RealTimeOrderBookMessage.cs b/Gateways/Alpaca/Libs/Messages/RealTimeOrderBookMessage.cs new file mode 100644 index 000000000..074bb16e8 --- /dev/null +++ b/Gateways/Alpaca/Libs/Messages/RealTimeOrderBookMessage.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Alpaca.Markets; + +public class RealTimeOrderBookMessage +{ + [JsonPropertyName("x")] + public string Exchange { get; set; } + + [JsonPropertyName("b")] + public List BidsList { get; set; } = []; + + [JsonPropertyName("a")] + public List AsksList { get; set; } = []; + + [JsonPropertyName("r")] + public bool IsReset { get; set; } + + [JsonIgnore] + public List Bids { get; set; } = []; + + [JsonIgnore] + public List Asks { get; set; } = []; +} diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeQuote.cs b/Gateways/Alpaca/Libs/Messages/RealTimeQuoteMessage.cs similarity index 91% rename from Gateways/Alpaca/Libs/Messages/JsonRealTimeQuote.cs rename to Gateways/Alpaca/Libs/Messages/RealTimeQuoteMessage.cs index db8dee1b5..3ee55a439 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeQuote.cs +++ b/Gateways/Alpaca/Libs/Messages/RealTimeQuoteMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonRealTimeQuote +public class RealTimeQuoteMessage { [JsonPropertyName("bx")] public string BidExchange { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonRealTimeTrade.cs b/Gateways/Alpaca/Libs/Messages/RealTimeTradeMessage.cs similarity index 90% rename from Gateways/Alpaca/Libs/Messages/JsonRealTimeTrade.cs rename to Gateways/Alpaca/Libs/Messages/RealTimeTradeMessage.cs index 8cce68e3c..a63c01cfe 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonRealTimeTrade.cs +++ b/Gateways/Alpaca/Libs/Messages/RealTimeTradeMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonRealTimeTrade +public class RealTimeTradeMessage { [JsonPropertyName("i")] public string TradeId { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/SnapshotMessage.cs b/Gateways/Alpaca/Libs/Messages/SnapshotMessage.cs new file mode 100644 index 000000000..d925fbeec --- /dev/null +++ b/Gateways/Alpaca/Libs/Messages/SnapshotMessage.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace Alpaca.Markets; + +public class SnapshotMessage +{ + [JsonPropertyName("latestQuote")] + public HistoricalQuoteMessage JsonQuote { get; set; } + + [JsonPropertyName("latestTrade")] + public HistoricalTradeMessage JsonTrade { get; set; } + + [JsonPropertyName("minuteBar")] + public HistoricalBarMessage JsonMinuteBar { get; set; } + + [JsonPropertyName("dailyBar")] + public HistoricalBarMessage JsonCurrentDailyBar { get; set; } + + [JsonPropertyName("prevDailyBar")] + public HistoricalBarMessage JsonPreviousDailyBar { get; set; } + + [JsonPropertyName("symbol")] + public string Symbol { get; set; } +} diff --git a/Gateways/Alpaca/Libs/Messages/JsonStreamError.cs b/Gateways/Alpaca/Libs/Messages/StreamErrorMessage.cs similarity index 82% rename from Gateways/Alpaca/Libs/Messages/JsonStreamError.cs rename to Gateways/Alpaca/Libs/Messages/StreamErrorMessage.cs index c7dd560eb..6f0a5c0f4 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonStreamError.cs +++ b/Gateways/Alpaca/Libs/Messages/StreamErrorMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonStreamError +public class StreamErrorMessage { [JsonPropertyName("code")] public double? Code { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonSubscriptionUpdate.cs b/Gateways/Alpaca/Libs/Messages/SubscriptionUpdateMessage.cs similarity index 92% rename from Gateways/Alpaca/Libs/Messages/JsonSubscriptionUpdate.cs rename to Gateways/Alpaca/Libs/Messages/SubscriptionUpdateMessage.cs index 14b967c99..00050b08f 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonSubscriptionUpdate.cs +++ b/Gateways/Alpaca/Libs/Messages/SubscriptionUpdateMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonSubscriptionUpdate +public class SubscriptionUpdateMessage { [JsonPropertyName("action")] public string Action { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonTradeUpdate.cs b/Gateways/Alpaca/Libs/Messages/TradeUpdateMessage.cs similarity index 83% rename from Gateways/Alpaca/Libs/Messages/JsonTradeUpdate.cs rename to Gateways/Alpaca/Libs/Messages/TradeUpdateMessage.cs index b0328872f..712a868cc 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonTradeUpdate.cs +++ b/Gateways/Alpaca/Libs/Messages/TradeUpdateMessage.cs @@ -3,7 +3,7 @@ namespace Alpaca.Markets; -public class JsonTradeUpdate +public class TradeUpdateMessage { [JsonPropertyName("event")] public string Event { get; set; } @@ -24,5 +24,5 @@ public class JsonTradeUpdate public DateTime? TimestampUtc { get; set; } [JsonPropertyName("order")] - public JsonOrder JsonOrder { get; set; } = new(); + public OrderMessage JsonOrder { get; set; } = new(); } diff --git a/Gateways/Alpaca/Libs/Messages/JsonTradesPage.cs b/Gateways/Alpaca/Libs/Messages/TradesPageMessage.cs similarity index 87% rename from Gateways/Alpaca/Libs/Messages/JsonTradesPage.cs rename to Gateways/Alpaca/Libs/Messages/TradesPageMessage.cs index 14e9e11b3..6657aff11 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonTradesPage.cs +++ b/Gateways/Alpaca/Libs/Messages/TradesPageMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonTradesPage +public class TradesPageMessage { [JsonPropertyName("trades")] public List ItemsList { get; set; } = []; diff --git a/Gateways/Alpaca/Libs/Messages/JsonTradingStatus.cs b/Gateways/Alpaca/Libs/Messages/TradingStatusMessage.cs similarity index 88% rename from Gateways/Alpaca/Libs/Messages/JsonTradingStatus.cs rename to Gateways/Alpaca/Libs/Messages/TradingStatusMessage.cs index d4887529f..f1a3d1f02 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonTradingStatus.cs +++ b/Gateways/Alpaca/Libs/Messages/TradingStatusMessage.cs @@ -2,7 +2,7 @@ namespace Alpaca.Markets; -public class JsonTradingStatus +public class TradingStatusMessage { [JsonPropertyName("sc")] public string StatusCode { get; set; } diff --git a/Gateways/Alpaca/Libs/Messages/JsonWatchList.cs b/Gateways/Alpaca/Libs/Messages/WatchListMessage.cs similarity index 81% rename from Gateways/Alpaca/Libs/Messages/JsonWatchList.cs rename to Gateways/Alpaca/Libs/Messages/WatchListMessage.cs index de394ee9b..6ef58a3d6 100644 --- a/Gateways/Alpaca/Libs/Messages/JsonWatchList.cs +++ b/Gateways/Alpaca/Libs/Messages/WatchListMessage.cs @@ -4,7 +4,7 @@ namespace Alpaca.Markets; -public class JsonWatchList +public class WatchListMessage { [JsonPropertyName("id")] public string WatchListId { get; set; } @@ -22,5 +22,5 @@ public class JsonWatchList public string AccountId { get; set; } [JsonPropertyName("assets")] - public List AssetsList { get; set; } = []; + public List AssetsList { get; set; } = []; } diff --git a/Gateways/Oanda/Libs/Adapter.cs b/Gateways/Oanda/Libs/Adapter.cs new file mode 100644 index 000000000..c51db0382 --- /dev/null +++ b/Gateways/Oanda/Libs/Adapter.cs @@ -0,0 +1,610 @@ +using Distribution.Services; +using Distribution.Stream; +using Distribution.Stream.Extensions; +using Oanda.Messages; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.WebSockets; +using System.Text.Json; +using System.Threading.Tasks; +using Terminal.Core.Domains; +using Terminal.Core.Enums; +using Terminal.Core.Models; + +namespace Oanda +{ + public class Adapter : Gateway + { + /// + /// HTTP client + /// + protected Service _sender; + + /// + /// Disposable connections + /// + protected IList _connections; + + /// + /// Disposable subscriptions + /// + protected IList _subscriptions; + + /// + /// Key + /// + public virtual string Token { get; set; } + + /// + /// Secret + /// + public virtual string DataUri { get; set; } + + /// + /// Secret + /// + public virtual string StreamUri { get; set; } + + /// + /// Constructor + /// + public Adapter() + { + StreamUri = "https://stream-fxpractice.oanda.com"; + DataUri = "https://api-fxpractice.oanda.com"; + + _subscriptions = []; + _connections = []; + } + + /// + /// Connect + /// + public override async Task> Connect() + { + var ws = new ClientWebSocket(); + var scheduler = new ScheduleService(); + + await Disconnect(); + + _sender = new Service(); + + await GetAccountData(); + + _connections.Add(_sender); + _connections.Add(scheduler); + + Account.Instruments.ForEach(async o => await Subscribe(o.Key)); + + return null; + } + + /// + /// Subscribe to data streams + /// + public override async Task> Subscribe(string name) + { + await Unsubscribe(name); + + return null; + } + + /// + /// Save state and dispose + /// + public override Task> Disconnect() + { + _connections?.ForEach(o => o.Dispose()); + _connections?.Clear(); + + return Task.FromResult(null as IList); + } + + /// + /// Unsubscribe from data streams + /// + public override Task> Unsubscribe(string name) + { + _subscriptions?.ForEach(o => o.Dispose()); + _subscriptions?.Clear(); + + return Task.FromResult(null as IList); + } + + /// + /// Get quote + /// + /// + public override Task> GetPoint(PointMessageModel message) + { + var response = new ResponseItemModel + { + Data = Account.Instruments[message.Name].Points.LastOrDefault() + }; + + return Task.FromResult(response); + } + + /// + /// Get option chains + /// + /// + public override Task>> GetOptions(OptionMessageModel message) + { + throw new NotImplementedException(); + } + + public override Task>> GetPoints(PointMessageModel message) + { + var response = new ResponseItemModel> + { + Data = Account.Instruments[message.Name].Points + }; + + return Task.FromResult(response); + } + + public override async Task> CreateOrders(params OrderModel[] orders) + { + var response = new ResponseMapModel(); + + foreach (var order in orders) + { + response.Items.Add(await CreateOrder(order)); + } + + return response; + } + + public override async Task> DeleteOrders(params OrderModel[] orders) + { + var response = new ResponseMapModel(); + + foreach (var order in orders) + { + response.Items.Add(await DeleteOrder(order)); + } + + return response; + } + + /// + /// Sync open balance, order, and positions + /// + /// + public async Task GetAccountData() + { + var account = await SendData($"/v3/accounts/{Account.Descriptor}"); + var positions = await SendData($"/v3/accounts/{Account.Descriptor}/positions"); + var orders = await SendData($"/v3/accounts/{Account.Descriptor}/orders"); + + //Account.Balance = account.Data.Equity; + //Account.Descriptor = account.Data.AccountNumber; + //Account.ActiveOrders = orders.Data.Select(GetInternalOrder).ToDictionary(o => o.Transaction.Id, o => o); + //Account.ActivePositions = positions.Data.Select(GetInternalPosition).ToDictionary(o => o.Order.Transaction.Id, o => o); + + //Account.ActiveOrders.ForEach(async o => await Subscribe(o.Value.Transaction.Instrument.Name)); + //Account.ActivePositions.ForEach(async o => await Subscribe(o.Value.Order.Transaction.Instrument.Name)); + } + + /// + /// Process quote from the stream + /// + /// + protected void ProcessPoint(string content) + { + try + { + //var streamPoint = JsonSerializer + // .Deserialize(content, _sender.Options) + // .FirstOrDefault(); + + //var instrument = Account.Instruments.Get(streamPoint.Symbol) ?? new Instrument(); + //var point = new PointModel(); + + //point.Ask = streamPoint.AskPrice; + //point.Bid = streamPoint.BidPrice; + //point.AskSize = streamPoint.AskSize ?? 0; + //point.BidSize = streamPoint.BidSize ?? 0; + //point.Last = streamPoint.BidPrice ?? streamPoint.AskPrice; + //point.Time = streamPoint.TimestampUtc ?? DateTime.Now; + //point.TimeFrame = instrument.TimeFrame; + //point.Instrument = instrument; + + //instrument.Name = streamPoint.Symbol; + //instrument.Points.Add(point); + //instrument.PointGroups.Add(point, instrument.TimeFrame, true); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + /// + /// Process quote from the stream + /// + /// + protected void ProcessTrade(string content) + { + try + { + //var order = JsonSerializer + // .Deserialize(content, _sender.Options) + // .FirstOrDefault(); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + /// + /// Send data to the API + /// + /// + /// + /// + /// + /// + protected async Task> SendData( + string source, + HttpMethod verb = null, + Hashtable query = null, + object data = null) + { + var uri = new UriBuilder(DataUri) + { + Path = source, + Query = (query ?? []).ToQuery() + }; + + var message = new HttpRequestMessage + { + Method = verb ?? HttpMethod.Get + }; + + switch (true) + { + case true when Equals(message.Method, HttpMethod.Put): + case true when Equals(message.Method, HttpMethod.Post): + case true when Equals(message.Method, HttpMethod.Patch): message.Content = new StringContent(JsonSerializer.Serialize(data ?? new { })); break; + } + + message.RequestUri = uri.Uri; + message.Headers.Add("Authorization", Token); + + var service = InstanceService.Instance; + + return await service.Send(message, service.Options).ConfigureAwait(false); + } + + /// + /// Send order + /// + /// + /// + protected async Task> CreateOrder(OrderModel order) + { + var inResponse = new ResponseItemModel(); + + try + { + var exOrder = GetExternalOrder(order); + var exResponse = await SendData("/v3/orders", HttpMethod.Post, [], exOrder); + + inResponse.Data = order; + inResponse.Data.Transaction.Id = $"{exResponse.Data?.Id}"; + inResponse.Data.Transaction.Status = GetInternalStatus(exResponse.Data?.State); + + if (exResponse.Status < 400) + { + Account.ActiveOrders.Add(order.Transaction.Id, order); + } + } + catch (Exception e) + { + inResponse.Errors.Add(new ErrorModel + { + ErrorMessage = e.Message + }); + } + + return inResponse; + } + + + /// + /// Cancel order + /// + /// + /// + protected async Task> DeleteOrder(OrderModel order) + { + await Task.CompletedTask; + + var inResponse = new ResponseItemModel(); + + try + { + //var exResponse = await SendData($"/v2/orders/{order.Transaction.Id}", HttpMethod.Delete); + + //inResponse.Data = order; + //inResponse.Data.Transaction.Id = $"{exResponse.Data.OrderId}"; + //inResponse.Data.Transaction.Status = GetInternalStatus(exResponse.Data.OrderStatus); + + //if (exResponse.Status < 400) + //{ + // Account.ActiveOrders.Remove(order.Transaction.Id); + //} + } + catch (Exception e) + { + inResponse.Errors.Add(new ErrorModel + { + ErrorMessage = e.Message + }); + } + + return inResponse; + } + + /// + /// Convert remote order from brokerage to local record + /// + /// + /// + protected JsonOrder GetExternalOrder(OrderModel order) + { + //var action = order.Transaction; + //var message = new Order + //{ + // Quantity = action.Volume, + // Symbol = action.Instrument.Name, + // TimeInForce = GetExternalTimeSpan(order.TimeSpan.Value), + // OrderType = "market" + //}; + + //switch (order.Side) + //{ + // case OrderSideEnum.Buy: message.OrderSide = "buy"; break; + // case OrderSideEnum.Sell: message.OrderSide = "sell"; break; + //} + + //switch (order.Type) + //{ + // case OrderTypeEnum.Stop: message.StopPrice = order.Price; break; + // case OrderTypeEnum.Limit: message.LimitPrice = order.Price; break; + // case OrderTypeEnum.StopLimit: message.StopPrice = order.ActivationPrice; message.LimitPrice = order.Price; break; + //} + + //if (order.Orders.Any()) + //{ + // message.OrderClass = "bracket"; + + // switch (order.Side) + // { + // case OrderSideEnum.Buy: + // message.StopLoss = GetExternalBracket(order, 1); + // message.TakeProfit = GetExternalBracket(order, -1); + // break; + + // case OrderSideEnum.Sell: + // message.StopLoss = GetExternalBracket(order, -1); + // message.TakeProfit = GetExternalBracket(order, 1); + // break; + // } + //} + + return null; + } + + /// + /// Convert local time in force to remote + /// + /// + /// + protected string GetExternalTimeSpan(OrderTimeSpanEnum span) + { + switch (span) + { + case OrderTimeSpanEnum.Day: return "day"; + case OrderTimeSpanEnum.Fok: return "fok"; + case OrderTimeSpanEnum.Gtc: return "gtc"; + case OrderTimeSpanEnum.Ioc: return "ioc"; + case OrderTimeSpanEnum.Omo: return "opg"; + case OrderTimeSpanEnum.Omc: return "cls"; + } + + return null; + } + + /// + /// Convert remote order to local + /// + /// + /// + protected OrderModel GetInternalOrder(JsonOrder order) + { + //var instrument = new Terminal.Core.Domains.Instrument + //{ + // Name = order.Symbol + //}; + + //var action = new TransactionModel + //{ + // Id = $"{order.OrderId}", + // Descriptor = order.ClientOrderId, + // Instrument = instrument, + // CurrentVolume = order.FilledQuantity, + // Volume = order.Quantity, + // Time = order.CreatedAtUtc, + // Status = GetInternalStatus(order.OrderStatus) + //}; + + //var inOrder = new OrderModel + //{ + // Transaction = action, + // Type = OrderTypeEnum.Market, + // Side = GetInternalOrderSide(order.OrderSide), + // TimeSpan = GetInternalTimeSpan(order.TimeInForce) + //}; + + //switch (order.OrderType) + //{ + // case "stop": + // inOrder.Type = OrderTypeEnum.Stop; + // inOrder.Price = order.StopPrice; + // break; + + // case "limit": + // inOrder.Type = OrderTypeEnum.Limit; + // inOrder.Price = order.LimitPrice; + // break; + + // case "stop_limit": + // inOrder.Type = OrderTypeEnum.StopLimit; + // inOrder.Price = order.StopPrice; + // inOrder.ActivationPrice = order.LimitPrice; + // break; + //} + + //return inOrder; + + return null; + } + + /// + /// Convert remote position to local + /// + /// + /// + protected PositionModel GetInternalPosition(JsonPosition position) + { + //var instrument = new Terminal.Core.Domains.Instrument + //{ + // Name = position.Instrument + //}; + + //var action = new TransactionModel + //{ + // Descriptor = position.Instrument, + // Instrument = instrument, + // CurrentVolume = position.AvailableQuantity, + // Volume = position.Long + //}; + + //var order = new OrderModel + //{ + // Transaction = action, + // Type = OrderTypeEnum.Market, + // Side = GetInternalPositionSide(position) + //}; + + //var gainLossPoints = position.AverageEntryPrice - position.AssetCurrentPrice; + //var gainLoss = position.CostBasis - position.MarketValue; + + //return new PositionModel + //{ + // GainLossPointsMax = gainLossPoints, + // GainLossPointsMin = gainLossPoints, + // GainLossPoints = gainLossPoints, + // GainLossMax = gainLoss, + // GainLossMin = gainLoss, + // GainLoss = gainLoss, + // Order = order, + // Orders = [order] + //}; + + return null; + } + + /// + /// Convert remote order status to local + /// + /// + /// + protected OrderStatusEnum GetInternalStatus(string status) + { + switch (status) + { + case "fill": + case "filled": return OrderStatusEnum.Filled; + case "partial_fill": + case "partially_filled": return OrderStatusEnum.Partitioned; + case "stopped": + case "expired": + case "rejected": + case "canceled": + case "done_for_day": return OrderStatusEnum.Canceled; + case "new": + case "held": + case "accepted": + case "suspended": + case "pending_new": + case "pending_cancel": + case "pending_replace": return OrderStatusEnum.Pending; + } + + return OrderStatusEnum.None; + } + + /// + /// Convert remote order side to local + /// + /// + /// + protected OrderSideEnum GetInternalOrderSide(string side) + { + switch (side) + { + case "buy": return OrderSideEnum.Buy; + case "sell": return OrderSideEnum.Sell; + } + + return OrderSideEnum.None; + } + + /// + /// Convert remote position side to local + /// + /// + /// + protected OrderSideEnum GetInternalPositionSide(JsonPosition position) + { + var buy = position.Long.Units.GetValueOrDefault(); + var sell = position.Short.Units.GetValueOrDefault(); + + switch (true) + { + case true when buy.IsEqual(0) is false: return OrderSideEnum.Buy; + case true when sell.IsEqual(0) is false: return OrderSideEnum.Sell; + } + + return OrderSideEnum.None; + } + + /// + /// Convert remote time in force to local + /// + /// + /// + protected OrderTimeSpanEnum GetInternalTimeSpan(string span) + { + switch (span) + { + case "day": return OrderTimeSpanEnum.Day; + case "fok": return OrderTimeSpanEnum.Fok; + case "gtc": return OrderTimeSpanEnum.Gtc; + case "ioc": return OrderTimeSpanEnum.Ioc; + case "opg": return OrderTimeSpanEnum.Omo; + case "cls": return OrderTimeSpanEnum.Omc; + } + + return OrderTimeSpanEnum.None; + } + } +} diff --git a/Gateways/Schwab/Libs/Adapter.cs b/Gateways/Schwab/Libs/Adapter.cs index 494772159..cc479b4c0 100644 --- a/Gateways/Schwab/Libs/Adapter.cs +++ b/Gateways/Schwab/Libs/Adapter.cs @@ -4,81 +4,81 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net.Http; -using System.Threading; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Terminal.Core.Domains; using Terminal.Core.Enums; using Terminal.Core.Models; -using Terminal.Gateway.Ameritrade.Models; +using Terminal.Core.Services; +using Terminal.Gateway.Schwab.Messages; namespace Schwab { public class Adapter : Gateway { /// - /// User + /// Encrypted account number /// - protected UserModel _user; + protected string _accountCode; /// - /// Disposable connections + /// Tokens /// - protected IList _connections; + protected ScopeMessage _scope = new() { AccessToken = "I0.b2F1dGgyLmJkYy5zY2h3YWIuY29t.c9oJ7z9jReYMe4DvYwz6vVBcj-7edvMrVZTFj79frQA@" }; /// - /// Application ID + /// HTTP client /// - public virtual string ConsumerKey { get; set; } + protected Service _sender; /// - /// Username + /// Socket connection /// - public virtual string Username { get; set; } + protected ClientWebSocket _streamer; /// - /// Password + /// Disposable connections /// - public virtual string Password { get; set; } + protected IList _connections; /// - /// Answer to a secret question + /// Disposable subscriptions /// - public virtual string Answer { get; set; } + protected IList _subscriptions; /// - /// Query URL + /// Key /// - public virtual string QueryUri { get; set; } + public virtual string ConsumerKey { get; set; } /// - /// Authentication URL + /// Secret /// - public virtual string SignInRemoteUri { get; set; } + public virtual string ConsumerSecret { get; set; } /// - /// Authentication URL for API + /// Data endpoint /// - public virtual string SignInApiUri { get; set; } + public virtual string DataUri { get; set; } /// - /// Local return URL for authentication + /// Streaming endpoint /// - public virtual string SignInLocalUri { get; set; } + public virtual string StreamUri { get; set; } /// /// Constructor /// public Adapter() { - _connections = new List(); + DataUri = "https://api.schwabapi.com"; - QueryUri = "https://api.tdameritrade.com/v1"; - SignInApiUri = "https://api.tdameritrade.com/v1/oauth2/token"; - SignInRemoteUri = "https://auth.tdameritrade.com/auth"; - SignInLocalUri = "http://localhost"; + _subscriptions = []; + _connections = []; } /// @@ -88,12 +88,12 @@ public override async Task> Connect() { await Disconnect(); - var automator = new Authenticator - { - Location = Path.GetTempPath() - }; + _sender = new Service(); + + await GetAccountData(); - _user = await automator.SignIn(this); + _connections.Add(_sender); + _connections.Add(_streamer); return null; } @@ -113,7 +113,7 @@ public override async Task> Subscribe(string name) /// public override Task> Disconnect() { - _connections?.ForEach(o => o.Dispose()); + _connections?.ForEach(o => o?.Dispose()); _connections?.Clear(); return Task.FromResult>(null); @@ -124,21 +124,10 @@ public override Task> Disconnect() /// public override Task> Unsubscribe(string name) { - return Task.FromResult>(null); - } + _subscriptions?.ForEach(o => o.Dispose()); + _subscriptions?.Clear(); - /// - /// Get quote - /// - /// - public override Task> GetPoint(PointMessageModel message) - { - var response = new ResponseItemModel - { - Data = Account.Instruments[message.Name].Points.LastOrDefault() - }; - - return Task.FromResult(response); + return Task.FromResult>(null); } /// @@ -155,15 +144,7 @@ public override async Task>> GetOptions(Opt ["includeQuotes"] = "TRUE" }; - var query = new HttpRequestMessage - { - RequestUri = new Uri($"{QueryUri}/marketdata/chains?{props.ToQuery()}") - }; - - query.Headers.Add("Authorization", $"{_user.TokenType} {_user.AccessToken}"); - - var service = InstanceService.Instance; - var response = await service.Send(query, service.Options, new CancellationTokenSource()); + var response = await SendData($"/marketdata/v1/chains?{props.ToQuery()}", HttpMethod.Get, props); var options = response .Data .PutExpDateMap @@ -218,7 +199,7 @@ public override async Task>> GetOptions(Opt return option; - })?.ToList() ?? new List(); + })?.ToList() ?? []; return new ResponseItemModel> { @@ -226,19 +207,494 @@ public override async Task>> GetOptions(Opt }; } + /// + /// Get points + /// + /// + /// + /// public override Task>> GetPoints(PointMessageModel message) { - throw new NotImplementedException(); + var response = new ResponseItemModel> + { + Data = Account.Instruments[message.Name].Points + }; + + return Task.FromResult(response); + } + + /// + /// Create orders + /// + /// + /// + /// + public override async Task> CreateOrders(params OrderModel[] orders) + { + var response = new ResponseMapModel(); + + foreach (var order in orders) + { + response.Items.Add(await CreateOrder(order)); + } + + return response; + } + + /// + /// Cancel orders + /// + /// + /// + public override async Task> DeleteOrders(params OrderModel[] orders) + { + var response = new ResponseMapModel(); + + foreach (var order in orders) + { + response.Items.Add(await DeleteOrder(order)); + } + + return response; + } + + /// + /// Sync open balance, order, and positions + /// + /// + protected async Task GetAccountData() + { + try + { + var dateFormat = "yyyy-MM-ddTHH:mm:ss.fffZ"; + var orderProps = new Hashtable + { + ["maxResults"] = 50, + ["toEnteredTime"] = DateTime.Now.AddDays(5).ToString(dateFormat), + ["fromEnteredTime"] = DateTime.Now.AddDays(-100).ToString(dateFormat) + }; + + var accountProps = new Hashtable { ["fields"] = "positions" }; + var accountNumbers = await SendData("/trader/v1/accounts/accountNumbers"); + + _accountCode = accountNumbers.Data.First(o => Equals(o.AccountNumber, Account.Descriptor)).HashValue; + + var account = await SendData($"/trader/v1/accounts/{_accountCode}", HttpMethod.Get, accountProps); + var orders = await SendData($"/trader/v1/accounts/{_accountCode}/orders", HttpMethod.Get, orderProps); + + Account.Balance = account.Data.AggregatedBalance.CurrentLiquidationValue; + Account.ActiveOrders = orders + .Data + .Where(o => o.CloseTime is null) + .Select(GetInternalOrder) + .ToDictionary(o => o.Transaction.Id, o => o); + + Account.ActivePositions = account + .Data + .SecuritiesAccount + .Positions + .Select(GetInternalPosition).ToDictionary(o => o.Order.Transaction.Id, o => o); + + Account.ActiveOrders.ForEach(async o => await Subscribe(o.Value.Transaction.Instrument.Name)); + Account.ActivePositions.ForEach(async o => await Subscribe(o.Value.Order.Transaction.Instrument.Name)); + } + catch (Exception e) + { + InstanceService.Instance.OnMessage($"{e}"); + } + } + + /// + /// Convert remote position to local + /// + /// + /// + protected PositionModel GetInternalPosition(PositionMessage position) + { + var instrument = new Instrument + { + Name = position.Instrument.Symbol + }; + + var action = new TransactionModel + { + Instrument = instrument, + Price = position.AveragePrice, + Descriptor = position.Instrument.Symbol, + Volume = position.LongQuantity + position.ShortQuantity, + CurrentVolume = position.LongQuantity + position.ShortQuantity + }; + + var order = new OrderModel + { + Transaction = action, + Type = OrderTypeEnum.Market, + Side = GetInternalPositionSide(position) + }; + + var gainLossPoints = 0.0; + var gainLoss = position.LongOpenProfitLoss; + + return new PositionModel + { + GainLossPointsMax = gainLossPoints, + GainLossPointsMin = gainLossPoints, + GainLossPoints = gainLossPoints, + GainLossMax = gainLoss, + GainLossMin = gainLoss, + GainLoss = gainLoss, + Order = order, + Orders = [order] + }; + } + + /// + /// Convert remote position side to local + /// + /// + /// + protected OrderSideEnum GetInternalPositionSide(PositionMessage position) + { + switch (true) + { + case true when position.LongQuantity > 0: return OrderSideEnum.Buy; + case true when position.ShortQuantity > 0: return OrderSideEnum.Sell; + } + + return OrderSideEnum.None; + } + + /// + /// Convert remote order to local + /// + /// + /// + protected OrderModel GetInternalOrder(OrderMessage order) + { + var assets = order + ?.OrderLegCollection + ?.Select(o => o?.Instrument?.Symbol); + + var instrument = new Instrument + { + Name = string.Join($" {Environment.NewLine}", assets) + }; + + var action = new TransactionModel + { + Id = $"{order.OrderId}", + Descriptor = order.OrderId, + Instrument = instrument, + CurrentVolume = order.FilledQuantity, + Volume = order.Quantity, + Time = order.EnteredTime, + Status = GetInternalStatus(order) + }; + + var inOrder = new OrderModel + { + Transaction = action, + Type = OrderTypeEnum.Market, + Side = GetInternalOrderSide(order), + TimeSpan = GetInternalTimeSpan(order) + }; + + switch (order.OrderType.ToUpper()) + { + case "STOP": + inOrder.Type = OrderTypeEnum.Stop; + inOrder.Price = order.Price; + break; + + case "LIMIT": + inOrder.Type = OrderTypeEnum.Limit; + inOrder.Price = order.Price; + break; + + case "STOP_LIMIT": + inOrder.Type = OrderTypeEnum.StopLimit; + inOrder.Price = order.Price; + inOrder.ActivationPrice = order.StopPrice; + break; + } + + return inOrder; + } + + /// + /// Send data to the API + /// + /// + /// + /// + /// + /// + protected async Task> SendData( + string source, + HttpMethod verb = null, + Hashtable query = null, + object content = null) + { + query ??= []; + verb ??= HttpMethod.Get; + + var uri = new UriBuilder(DataUri) + { + Path = source + }; + + var message = new HttpRequestMessage + { + Method = verb + }; + + switch (true) + { + case true when Equals(verb, HttpMethod.Get): uri.Query = query.ToQuery(); break; + case true when Equals(verb, HttpMethod.Put): + case true when Equals(verb, HttpMethod.Post): + case true when Equals(verb, HttpMethod.Patch): message.Content = new StringContent(JsonSerializer.Serialize(content)); break; + } + + message.RequestUri = uri.Uri; + message.Headers.Add("Authorization", $"Bearer {_scope.AccessToken}"); + + return await _sender.Send(message, _sender.Options); } + /// + /// Refresh token + /// + /// + /// + /// + protected async Task UpdateToken(string source) + { + var uri = new UriBuilder(DataUri) + { + Path = source + }; + + var content = new FormUrlEncodedContent(new Dictionary + { + ["grant_type"] = "refresh_token", + ["refresh_token"] = _scope.RefreshToken + }); + + var message = new HttpRequestMessage(); + var basicToken = Encoding.UTF8.GetBytes($"{ConsumerKey}:{ConsumerSecret}"); - public override Task> SendOrders(params OrderModel[] orders) + message.Content = content; + message.RequestUri = uri.Uri; + message.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); + message.Headers.Add("Authorization", $"Basic {Convert.ToBase64String(basicToken)}"); + + var response = await _sender.Send(message, _sender.Options); + + return _scope = response.Data; + } + + /// + /// Send order + /// + /// + /// + protected async Task> CreateOrder(OrderModel order) { - throw new NotImplementedException(); + var inResponse = new ResponseItemModel(); + + try + { + var exOrder = GetExternalOrder(order); + var exResponse = await SendData($"/trader/v1/accounts/{_accountCode}/orders", HttpMethod.Post, null, exOrder); + + inResponse.Data = order; + inResponse.Data.Transaction.Id = $"{exResponse.Data.OrderId}"; + inResponse.Data.Transaction.Status = GetInternalStatus(exResponse.Data); + + if (exResponse.Status < 400) + { + Account.ActiveOrders.Add(order.Transaction.Id, order); + } + } + catch (Exception e) + { + inResponse.Errors.Add(new ErrorModel + { + ErrorMessage = e.Message + }); + } + + return inResponse; } - public override Task> CancelOrders(params OrderModel[] orders) + + /// + /// Convert remote order from brokerage to local record + /// + /// + /// + protected OrderMessage GetExternalOrder(OrderModel order) + { + var action = order.Transaction; + var message = new OrderMessage + { + //Quantity = action.Volume, + //Symbol = action.Instrument.Name, + //TimeInForce = GetExternalTimeSpan(order.TimeSpan.Value), + //OrderType = "market" + }; + + //switch (order.Side) + //{ + // case OrderSideEnum.Buy: message.OrderSide = "buy"; break; + // case OrderSideEnum.Sell: message.OrderSide = "sell"; break; + //} + + //switch (order.Type) + //{ + // case OrderTypeEnum.Stop: message.StopPrice = order.Price; break; + // case OrderTypeEnum.Limit: message.LimitPrice = order.Price; break; + // case OrderTypeEnum.StopLimit: message.StopPrice = order.ActivationPrice; message.LimitPrice = order.Price; break; + //} + + //if (order.Orders.Any()) + //{ + // message.OrderClass = "bracket"; + + // switch (order.Side) + // { + // case OrderSideEnum.Buy: + // message.StopLoss = GetExternalBracket(order, 1); + // message.TakeProfit = GetExternalBracket(order, -1); + // break; + + // case OrderSideEnum.Sell: + // message.StopLoss = GetExternalBracket(order, -1); + // message.TakeProfit = GetExternalBracket(order, 1); + // break; + // } + //} + + return null; + } + + /// + /// Cancel order + /// + /// + /// + protected async Task> DeleteOrder(OrderModel order) + { + var inResponse = new ResponseItemModel(); + + try + { + var exResponse = await SendData($"/trader/v1/accounts/{_accountCode}/orders", HttpMethod.Delete); + + inResponse.Data = order; + inResponse.Data.Transaction.Id = $"{exResponse.Data.OrderId}"; + inResponse.Data.Transaction.Status = GetInternalStatus(exResponse.Data); + + if (exResponse.Status < 400) + { + Account.ActiveOrders.Remove(order.Transaction.Id); + } + } + catch (Exception e) + { + inResponse.Errors.Add(new ErrorModel + { + ErrorMessage = e.Message + }); + } + + return inResponse; + } + + /// + /// Convert remote order status to local + /// + /// + /// + protected OrderStatusEnum GetInternalStatus(OrderMessage order) + { + switch (order.Status.ToUpper()) + { + case "FILLED": + case "REPLACED": return OrderStatusEnum.Filled; + case "WORKING": return OrderStatusEnum.Partitioned; + case "REJECTED": + case "CANCELED": + case "EXPIRED": return OrderStatusEnum.Canceled; + case "NEW": + case "PENDING_RECALL": + case "PENDING_CANCEL": + case "PENDING_REPLACE": + case "PENDING_ACTIVATION": + case "PENDING_ACKNOWLEDGEMENT": + case "AWAITING_CONDITION": + case "AWAITING_PARENT_ORDER": + case "AWAITING_RELEASE_TIME": + case "AWAITING_MANUAL_REVIEW": + case "AWAITING_STOP_CONDITION": return OrderStatusEnum.Pending; + } + + return OrderStatusEnum.None; + } + + /// + /// Convert remote order side to local + /// + /// + /// + protected OrderSideEnum GetInternalOrderSide(OrderMessage order) + { + static bool E(string x, string o) => string.Equals(x, o, StringComparison.OrdinalIgnoreCase); + + var position = order + ?.OrderLegCollection + ?.FirstOrDefault(); + + if (E(position.OrderLegType, "EQUITY")) + { + switch (position.Instruction.ToUpper()) + { + case "BUY": + case "BUY_TO_OPEN": + case "BUY_TO_CLOSE": return OrderSideEnum.Buy; + + case "SELL": + case "SELL_TO_OPEN": + case "SELL_TO_CLOSE": return OrderSideEnum.Sell; + } + } + + return OrderSideEnum.None; + } + + /// + /// Convert remote time in force to local + /// + /// + /// + protected OrderTimeSpanEnum GetInternalTimeSpan(OrderMessage order) { - throw new NotImplementedException(); + var span = order.Duration; + var session = order.Session; + + static bool E(string x, string o) => string.Equals(x, o, StringComparison.OrdinalIgnoreCase); + + switch (true) + { + case true when E(span, "DAY"): return OrderTimeSpanEnum.Day; + case true when E(span, "FOK") || E(span, "FILL_OR_KILL"): return OrderTimeSpanEnum.Fok; + case true when E(span, "GTC") || E(span, "GOOD_TILL_CANCEL"): return OrderTimeSpanEnum.Gtc; + case true when E(span, "IOC") || E(span, "IMMEDIATE_OR_CANCEL"): return OrderTimeSpanEnum.Ioc; + case true when E(session, "AM"): return OrderTimeSpanEnum.Am; + case true when E(session, "PM"): return OrderTimeSpanEnum.Pm; + } + + return OrderTimeSpanEnum.None; } } } diff --git a/Gateways/Schwab/Libs/Authenticator.cs b/Gateways/Schwab/Libs/Authenticator.cs deleted file mode 100644 index 2e2fee3e2..000000000 --- a/Gateways/Schwab/Libs/Authenticator.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Distribution.Stream; -using Distribution.Services; -using Microsoft.AspNetCore.Http.Extensions; -using PuppeteerSharp; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; -using Terminal.Core.Extensions; -using Terminal.Gateway.Ameritrade.Models; -using Distribution.Stream.Extensions; - -namespace Schwab -{ - public class Authenticator - { - /// - /// Keys - /// - public virtual string Location { get; set; } - - /// - /// Load keys - /// - /// - /// - public virtual T GetUser(string name) - { - var location = Path.Combine(Location, name); - - if (File.Exists(location)) - { - return File.ReadAllText(location).Deserialize(); - } - - return default; - } - - /// - /// Save keys - /// - /// - /// - public virtual void SaveUser(string name, T model) - { - File.WriteAllText(Path.Combine(Location, name), JsonSerializer.Serialize(model)); - } - - /// - /// Manual sign in - /// - /// - /// - public virtual async Task SignIn(Adapter adapter) - { - var user = GetUser(nameof(Authenticator)); - - if (user.ExpirationDate > DateTime.UtcNow.Ticks) - { - return user; - } - - using (var browserFetcher = new BrowserFetcher()) - { - await browserFetcher.DownloadAsync(); - - var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); - var source = new UriBuilder(adapter.SignInRemoteUri); - var page = await browser.NewPageAsync(); - var nav = page.WaitForNavigationAsync(); - - source.Query = new QueryBuilder - { - { "response_type", "code" }, - { "redirect_uri", adapter.SignInLocalUri }, - { "client_id", $"{adapter.ConsumerKey}@AMER.OAUTHAP" } - } + string.Empty; - - page.Request += (sender, e) => - { - if (e.Request.ResourceType == ResourceType.StyleSheet) - { - e.Request.AbortAsync(); - return; - } - - e.Request.ContinueAsync(); - }; - - await page.SetRequestInterceptionAsync(true); - await page.GoToAsync($"{source}"); - await page.WaitForSelectorAsync(".accept.button"); - await page.TypeAsync("[name=su_username]", adapter.Username); - await page.TypeAsync("[name=su_password]", adapter.Password); - await page.ClickAsync(".accept.button"); - await nav; - - var verification = await page.WaitForSelectorAsync(".alternates .row"); - - if (verification is not null) - { - nav = page.WaitForNavigationAsync(); - - await page.ClickAsync(".alternates .row"); - await page.WaitForSelectorAsync("[name=init_secretquestion]"); - await page.ClickAsync("[name=init_secretquestion]"); - await nav; - - nav = page.WaitForNavigationAsync(); - - await page.WaitForSelectorAsync("[name=su_secretquestion]"); - await page.TypeAsync("[name=su_secretquestion]", adapter.Answer); - await page.ClickAsync(".accept.button"); - await nav; - - nav = page.WaitForNavigationAsync(); - - await page.WaitForSelectorAsync("[name=su_trustthisdevice]"); - await page.ClickAsync("[name=su_trustthisdevice]"); - await page.WaitForSelectorAsync("input[type='radio']:checked"); - await page.ClickAsync(".accept.button"); - await nav; - } - - nav = page.WaitForNavigationAsync(); - - await page.ClickAsync(".accept.button"); - await nav; - - #pragma warning disable CS0618 // Type or member is obsolete - var codeSource = page.Target.Url; - #pragma warning restore CS0618 // Type or member is obsolete - var securityCode = codeSource.ToPairs().Get("code"); - var userModel = await Authenticate(adapter, securityCode); - - userModel.SecurityCode = securityCode; - userModel.ConsumerKey = adapter.ConsumerKey; - userModel.ExpirationDate = DateTime.UtcNow.AddSeconds(userModel.ExpiresIn).Ticks; - - SaveUser(nameof(Authenticator), userModel); - - return userModel; - } - } - - /// - /// Get API token - /// - /// - /// - /// - public async Task Authenticate(Adapter adapter, string securityCode) - { - var props = new Dictionary - { - { "grant_type", "authorization_code" }, - { "access_type", "offline" }, - { "client_id", $"{adapter.ConsumerKey}@AMER.OAUTHAP" }, - { "redirect_uri", adapter.SignInLocalUri }, - { "code", securityCode } - }; - - var query = new HttpRequestMessage(HttpMethod.Post, adapter.SignInApiUri) - { - Content = new FormUrlEncodedContent(props) - }; - - return (await InstanceService.Instance.Send(query)).Data; - } - } -} diff --git a/Gateways/Schwab/Libs/Messages/AccountNumbersMessage.cs b/Gateways/Schwab/Libs/Messages/AccountNumbersMessage.cs new file mode 100644 index 000000000..986fa7853 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/AccountNumbersMessage.cs @@ -0,0 +1,15 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class AccountNumberMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("accountNumber")] + public string AccountNumber { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("hashValue")] + public string HashValue { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/AccountsMessage.cs b/Gateways/Schwab/Libs/Messages/AccountsMessage.cs new file mode 100644 index 000000000..180bc07ff --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/AccountsMessage.cs @@ -0,0 +1,15 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class AccountsMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("securitiesAccount")] + public SecuritiesMessage SecuritiesAccount { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("aggregatedBalance")] + public AggregatedBalanceMessage AggregatedBalance { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/AggregatedBalanceMessage.cs b/Gateways/Schwab/Libs/Messages/AggregatedBalanceMessage.cs new file mode 100644 index 000000000..6965d38bb --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/AggregatedBalanceMessage.cs @@ -0,0 +1,15 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class AggregatedBalanceMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("currentLiquidationValue")] + public double? CurrentLiquidationValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("liquidationValue")] + public double? LiquidationValue { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/ExecutionLegMessage.cs b/Gateways/Schwab/Libs/Messages/ExecutionLegMessage.cs new file mode 100644 index 000000000..ae4bbdcbd --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/ExecutionLegMessage.cs @@ -0,0 +1,32 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System; + using System.Text.Json.Serialization; + + public partial class ExecutionLegMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("legId")] + public string LegId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("price")] + public double? Price { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quantity")] + public double? Quantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("mismarkedQuantity")] + public double? MismarkedQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("instrumentId")] + public string InstrumentId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("time")] + public DateTime? Time { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/InitialBalanceMessage.cs b/Gateways/Schwab/Libs/Messages/InitialBalanceMessage.cs new file mode 100644 index 000000000..f571fe63c --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/InitialBalanceMessage.cs @@ -0,0 +1,135 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class InitialBalanceMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("accruedInterest")] + public double? AccruedInterest { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("availableFundsNonMarginableTrade")] + public double? AvailableFundsNonMarginableTrade { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("bondValue")] + public double? BondValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("buyingPower")] + public double? BuyingPower { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cashBalance")] + public double? CashBalance { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cashAvailableForTrading")] + public double? CashAvailableForTrading { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cashReceipts")] + public double? CashReceipts { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("dayTradingBuyingPower")] + public double? DayTradingBuyingPower { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("dayTradingBuyingPowerCall")] + public double? DayTradingBuyingPowerCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("dayTradingEquityCall")] + public double? DayTradingEquityCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("equity")] + public double? Equity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("equityPercentage")] + public double? EquityPercentage { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("liquidationValue")] + public double? LiquidationValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("longMarginValue")] + public double? LongMarginValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("longOptionMarketValue")] + public double? LongOptionMarketValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("longStockValue")] + public double? LongStockValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("maintenanceCall")] + public double? MaintenanceCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("maintenanceRequirement")] + public double? MaintenanceRequirement { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("margin")] + public double? Margin { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("marginEquity")] + public double? MarginEquity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("moneyMarketFund")] + public double? MoneyMarketFund { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("mutualFundValue")] + public double? MutualFundValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("regTCall")] + public double? RegTCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("shortMarginValue")] + public double? ShortMarginValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("shortOptionMarketValue")] + public double? ShortOptionMarketValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("shortStockValue")] + public double? ShortStockValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalCash")] + public double? TotalCash { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("isInCall")] + public bool? IsInCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("pendingDeposits")] + public double? PendingDeposits { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("marginBalance")] + public double? MarginBalance { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("shortBalance")] + public double? ShortBalance { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("accountValue")] + public double? AccountValue { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/InstrumentMessage.cs b/Gateways/Schwab/Libs/Messages/InstrumentMessage.cs new file mode 100644 index 000000000..317a7ab11 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/InstrumentMessage.cs @@ -0,0 +1,43 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class InstrumentMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("assetType")] + public string AssetType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cusip")] + public string Cusip { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("netChange")] + public double? NetChange { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("putCall")] + public string PutCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("underlyingSymbol")] + public string UnderlyingSymbol { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("instrumentId")] + public string InstrumentId { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OptionChainMessage.cs b/Gateways/Schwab/Libs/Messages/OptionChainMessage.cs new file mode 100644 index 000000000..eedfe9b9a --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OptionChainMessage.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Terminal.Gateway.Schwab.Messages +{ + public class OptionChainMessage + { + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("underlying")] + public UnderlyingMessage Underlying { get; set; } + + [JsonPropertyName("strategy")] + public string Strategy { get; set; } + + [JsonPropertyName("interval")] + public double? Interval { get; set; } + + [JsonPropertyName("isDelayed")] + public bool? IsDelayed { get; set; } + + [JsonPropertyName("isIndex")] + public bool? IsIndex { get; set; } + + [JsonPropertyName("daysToExpiration")] + public double? DaysToExpiration { get; set; } + + [JsonPropertyName("interestRate")] + public double? InterestRate { get; set; } + + [JsonPropertyName("underlyingPrice")] + public double? UnderlyingPrice { get; set; } + + [JsonPropertyName("volatility")] + public double? Volatility { get; set; } + + [JsonPropertyName("callExpDateMap")] + public Dictionary>> CallExpDateMap { get; set; } + + [JsonPropertyName("putExpDateMap")] + public Dictionary>> PutExpDateMap { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OptionDeliverableMessage.cs b/Gateways/Schwab/Libs/Messages/OptionDeliverableMessage.cs new file mode 100644 index 000000000..4538668ab --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OptionDeliverableMessage.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Terminal.Gateway.Schwab.Messages +{ + public class OptionDeliverableMessage + { + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + + [JsonPropertyName("assetType")] + public string AssetType { get; set; } + + [JsonPropertyName("deliverableUnits")] + public string DeliverableUnits { get; set; } + + [JsonPropertyName("currencyType")] + public string CurrencyType { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OptionMessage.cs b/Gateways/Schwab/Libs/Messages/OptionMessage.cs new file mode 100644 index 000000000..b44bb5a92 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OptionMessage.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Terminal.Gateway.Schwab.Messages +{ + public class OptionMessage + { + [JsonPropertyName("putCall")] + public string PutCall { get; set; } + + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("exchangeName")] + public string ExchangeName { get; set; } + + [JsonPropertyName("bid")] + public double? Bid { get; set; } + + [JsonPropertyName("ask")] + public double? Ask { get; set; } + + [JsonPropertyName("last")] + public double? Last { get; set; } + + [JsonPropertyName("mark")] + public double? Mark { get; set; } + + [JsonPropertyName("bidSize")] + public double? BidSize { get; set; } + + [JsonPropertyName("askSize")] + public double? AskSize { get; set; } + + [JsonPropertyName("bidAskSize")] + public string BidAskSize { get; set; } + + [JsonPropertyName("lastSize")] + public double? LastSize { get; set; } + + [JsonPropertyName("highPrice")] + public double? HighPrice { get; set; } + + [JsonPropertyName("lowPrice")] + public double? LowPrice { get; set; } + + [JsonPropertyName("openPrice")] + public double? OpenPrice { get; set; } + + [JsonPropertyName("closePrice")] + public double? ClosePrice { get; set; } + + [JsonPropertyName("totalVolume")] + public double? TotalVolume { get; set; } + + [JsonPropertyName("tradeDate")] + public DateTime TradeDate { get; set; } + + [JsonPropertyName("quoteTimeInLong")] + public long? QuoteTimeInLong { get; set; } + + [JsonPropertyName("tradeTimeInLong")] + public long? TradeTimeInLong { get; set; } + + [JsonPropertyName("netChange")] + public double? NetChange { get; set; } + + [JsonPropertyName("volatility")] + public double? Volatility { get; set; } + + [JsonPropertyName("delta")] + public double? Delta { get; set; } + + [JsonPropertyName("gamma")] + public double? Gamma { get; set; } + + [JsonPropertyName("theta")] + public double? Theta { get; set; } + + [JsonPropertyName("vega")] + public double? Vega { get; set; } + + [JsonPropertyName("rho")] + public double? Rho { get; set; } + + [JsonPropertyName("timeValue")] + public double? TimeValue { get; set; } + + [JsonPropertyName("openInterest")] + public double? OpenInterest { get; set; } + + [JsonPropertyName("inTheMoney")] + public bool? IsInTheMoney { get; set; } + + [JsonPropertyName("theoreticalOptionValue")] + public double? TheoreticalOptionValue { get; set; } + + [JsonPropertyName("theoreticalVolatility")] + public double? TheoreticalVolatility { get; set; } + + [JsonPropertyName("mini")] + public bool? IsMini { get; set; } + + [JsonPropertyName("nonStandard")] + public bool? IsNonStandard { get; set; } + + [JsonPropertyName("optionDeliverablesList")] + public List OptionDeliverablesList { get; set; } + + [JsonPropertyName("strikePrice")] + public double? StrikePrice { get; set; } + + [JsonPropertyName("lastTradingDay")] + public double? LastTradingDay { get; set; } + + [JsonPropertyName("expirationDate")] + public long? ExpirationDate { get; set; } + + [JsonPropertyName("expirationType")] + public string ExpirationType { get; set; } + + [JsonPropertyName("multiplier")] + public double? Multiplier { get; set; } + + [JsonPropertyName("intrinsicValue")] + public double? IntrinsicValue { get; set; } + + [JsonPropertyName("settlementType")] + public string SettlementType { get; set; } + + [JsonPropertyName("deliverableNote")] + public string DeliverableNote { get; set; } + + [JsonPropertyName("isIndexOption")] + public bool? IsIndexOption { get; set; } + + [JsonPropertyName("pennyPilot")] + public bool? IsPennyPilot { get; set; } + + [JsonPropertyName("percentChange")] + public double? PercentChange { get; set; } + + [JsonPropertyName("markChange")] + public double? MarkChange { get; set; } + + [JsonPropertyName("markPercentChange")] + public double? MarkPercentChange { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OrderActivityMessage.cs b/Gateways/Schwab/Libs/Messages/OrderActivityMessage.cs new file mode 100644 index 000000000..de27c4de6 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OrderActivityMessage.cs @@ -0,0 +1,28 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Collections.Generic; + using System.Text.Json.Serialization; + + public partial class OrderActivityMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("activityType")] + public string ActivityType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("executionType")] + public string ExecutionType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quantity")] + public double? Quantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderRemainingQuantity")] + public double? OrderRemainingQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("executionLegs")] + public List ExecutionLegs { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OrderLegMessage.cs b/Gateways/Schwab/Libs/Messages/OrderLegMessage.cs new file mode 100644 index 000000000..4e6508bb6 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OrderLegMessage.cs @@ -0,0 +1,43 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class OrderLegMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderLegType")] + public string OrderLegType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("legId")] + public string LegId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("instrument")] + public InstrumentMessage Instrument { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("instruction")] + public string Instruction { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("positionEffect")] + public string PositionEffect { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quantity")] + public double? Quantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quantityType")] + public string QuantityType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("divCapGains")] + public string DivCapGains { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("toSymbol")] + public string ToSymbol { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/OrderMessage.cs b/Gateways/Schwab/Libs/Messages/OrderMessage.cs new file mode 100644 index 000000000..2b98fe3cd --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/OrderMessage.cs @@ -0,0 +1,153 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System; + using System.Collections.Generic; + using System.Text.Json.Serialization; + + public partial class OrderMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("session")] + public string Session { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("duration")] + public string Duration { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderType")] + public string OrderType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cancelTime")] + public DateTime? CancelTime { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("complexOrderStrategyType")] + public string ComplexOrderStrategyType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quantity")] + public double? Quantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("filledQuantity")] + public double? FilledQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("remainingQuantity")] + public double? RemainingQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("requestedDestination")] + public string RequestedDestination { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("destinationLinkName")] + public string DestinationLinkName { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("releaseTime")] + public DateTime? ReleaseTime { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopPrice")] + public double? StopPrice { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopPriceLinkBasis")] + public string StopPriceLinkBasis { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopPriceLinkType")] + public string StopPriceLinkType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopPriceOffset")] + public double? StopPriceOffset { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopType")] + public string StopType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("priceLinkBasis")] + public string PriceLinkBasis { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("priceLinkType")] + public string PriceLinkType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("price")] + public double? Price { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("taxLotMethod")] + public string TaxLotMethod { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderLegCollection")] + public List OrderLegCollection { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("activationPrice")] + public double? ActivationPrice { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("specialInstruction")] + public string SpecialInstruction { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderStrategyType")] + public string OrderStrategyType { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderId")] + public string OrderId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cancelable")] + public bool? Cancelable { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("editable")] + public bool? Editable { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("enteredTime")] + public DateTime? EnteredTime { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("closeTime")] + public DateTime? CloseTime { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("tag")] + public string Tag { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("accountNumber")] + public string AccountNumber { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("orderActivityCollection")] + public List OrderActivityCollection { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("replacingOrderCollection")] + public List ReplacingOrderCollection { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("childOrderStrategies")] + public List ChildOrderStrategies { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("statusDescription")] + public string StatusDescription { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/PositionMessage.cs b/Gateways/Schwab/Libs/Messages/PositionMessage.cs new file mode 100644 index 000000000..8c72212de --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/PositionMessage.cs @@ -0,0 +1,67 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class PositionMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("shortQuantity")] + public double? ShortQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("averagePrice")] + public double? AveragePrice { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("currentDayProfitLoss")] + public double? CurrentDayProfitLoss { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("currentDayProfitLossPercentage")] + public double? CurrentDayProfitLossPercentage { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("longQuantity")] + public double? LongQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("settledLongQuantity")] + public double? SettledLongQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("settledShortQuantity")] + public double? SettledShortQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("instrument")] + public InstrumentMessage Instrument { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("marketValue")] + public double? MarketValue { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("maintenanceRequirement")] + public double? MaintenanceRequirement { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("averageLongPrice")] + public double? AverageLongPrice { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("taxLotAverageLongPrice")] + public double? TaxLotAverageLongPrice { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("longOpenProfitLoss")] + public double? LongOpenProfitLoss { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("previousSessionLongQuantity")] + public double? PreviousSessionLongQuantity { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("currentDayCost")] + public double? CurrentDayCost { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/ProjectedBalanceMessage.cs b/Gateways/Schwab/Libs/Messages/ProjectedBalanceMessage.cs new file mode 100644 index 000000000..df91f6b0b --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/ProjectedBalanceMessage.cs @@ -0,0 +1,43 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Text.Json.Serialization; + + public partial class ProjectedBalanceMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("availableFunds")] + public double? AvailableFunds { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("availableFundsNonMarginableTrade")] + public double? AvailableFundsNonMarginableTrade { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("buyingPower")] + public double? BuyingPower { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("dayTradingBuyingPower")] + public double? DayTradingBuyingPower { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("dayTradingBuyingPowerCall")] + public double? DayTradingBuyingPowerCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("maintenanceCall")] + public double? MaintenanceCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("regTCall")] + public double? RegTCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("isInCall")] + public bool? IsInCall { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stockBuyingPower")] + public double? StockBuyingPower { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/ScopeMessage.cs b/Gateways/Schwab/Libs/Messages/ScopeMessage.cs new file mode 100644 index 000000000..c39bd8f69 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/ScopeMessage.cs @@ -0,0 +1,25 @@ +using System.Text.Json.Serialization; + +namespace Terminal.Gateway.Schwab.Messages +{ + public class ScopeMessage + { + [JsonPropertyName("access_token")] + public string AccessToken { get; set; } + + [JsonPropertyName("refresh_token")] + public string RefreshToken { get; set; } + + [JsonPropertyName("scope")] + public string Scope { get; set; } + + [JsonPropertyName("expires_in")] + public int ExpiresIn { get; set; } + + [JsonPropertyName("token_type")] + public string TokenType { get; set; } + + [JsonPropertyName("id_token")] + public string Token { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/SecuritiesMessage.cs b/Gateways/Schwab/Libs/Messages/SecuritiesMessage.cs new file mode 100644 index 000000000..19bbc199e --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/SecuritiesMessage.cs @@ -0,0 +1,48 @@ +namespace Terminal.Gateway.Schwab.Messages +{ + using System.Collections.Generic; + using System.Text.Json.Serialization; + + public partial class SecuritiesMessage + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("accountNumber")] + public string AccountNumber { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("roundTrips")] + public string RoundTrips { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("isDayTrader")] + public bool? IsDayTrader { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("isClosingOnlyRestricted")] + public bool? IsClosingOnlyRestricted { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("pfcbFlag")] + public bool? PfcbFlag { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("positions")] + public List Positions { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("initialBalances")] + public InitialBalanceMessage InitialBalances { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("currentBalances")] + public Dictionary CurrentBalances { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("projectedBalances")] + public ProjectedBalanceMessage ProjectedBalances { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Messages/UnderlyingMessage.cs b/Gateways/Schwab/Libs/Messages/UnderlyingMessage.cs new file mode 100644 index 000000000..2959847f8 --- /dev/null +++ b/Gateways/Schwab/Libs/Messages/UnderlyingMessage.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Terminal.Gateway.Schwab.Messages +{ + public class UnderlyingMessage + { + [JsonPropertyName("ask")] + public double? Ask { get; set; } + + [JsonPropertyName("askSize")] + public double? AskSize { get; set; } + + [JsonPropertyName("bid")] + public double? Bid { get; set; } + + [JsonPropertyName("bidSize")] + public double? BidSize { get; set; } + + [JsonPropertyName("change")] + public double? Change { get; set; } + + [JsonPropertyName("close")] + public double? Close { get; set; } + + [JsonPropertyName("delayed")] + public bool? Delayed { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("exchangeName")] + public string ExchangeName { get; set; } + + [JsonPropertyName("fiftyTwoWeekHigh")] + public double? FiftyTwoWeekHigh { get; set; } + + [JsonPropertyName("fiftyTwoWeekLow")] + public double? FiftyTwoWeekLow { get; set; } + + [JsonPropertyName("highPrice")] + public double? HighPrice { get; set; } + + [JsonPropertyName("last")] + public double? Last { get; set; } + + [JsonPropertyName("lowPrice")] + public double? LowPrice { get; set; } + + [JsonPropertyName("mark")] + public double? Mark { get; set; } + + [JsonPropertyName("markChange")] + public double? MarkChange { get; set; } + + [JsonPropertyName("markPercentChange")] + public double? MarkPercentChange { get; set; } + + [JsonPropertyName("openPrice")] + public double? OpenPrice { get; set; } + + [JsonPropertyName("percentChange")] + public double? PercentChange { get; set; } + + [JsonPropertyName("quoteTime")] + public double? QuoteTime { get; set; } + + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + + [JsonPropertyName("totalVolume")] + public double? TotalVolume { get; set; } + + [JsonPropertyName("tradeTime")] + public double? TradeTime { get; set; } + } +} diff --git a/Gateways/Schwab/Libs/Models/ChainModels.cs b/Gateways/Schwab/Libs/Models/ChainModels.cs deleted file mode 100644 index 5e39c41be..000000000 --- a/Gateways/Schwab/Libs/Models/ChainModels.cs +++ /dev/null @@ -1,282 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Terminal.Gateway.Ameritrade.Models -{ - public struct Option - { - [JsonPropertyName("putCall")] - public string PutCall { get; set; } - - [JsonPropertyName("symbol")] - public string Symbol { get; set; } - - [JsonPropertyName("description")] - public string Description { get; set; } - - [JsonPropertyName("exchangeName")] - public string ExchangeName { get; set; } - - [JsonPropertyName("bid")] - public double? Bid { get; set; } - - [JsonPropertyName("ask")] - public double? Ask { get; set; } - - [JsonPropertyName("last")] - public double? Last { get; set; } - - [JsonPropertyName("mark")] - public double? Mark { get; set; } - - [JsonPropertyName("bidSize")] - public double? BidSize { get; set; } - - [JsonPropertyName("askSize")] - public double? AskSize { get; set; } - - [JsonPropertyName("bidAskSize")] - public string BidAskSize { get; set; } - - [JsonPropertyName("lastSize")] - public double? LastSize { get; set; } - - [JsonPropertyName("highPrice")] - public double? HighPrice { get; set; } - - [JsonPropertyName("lowPrice")] - public double? LowPrice { get; set; } - - [JsonPropertyName("openPrice")] - public double? OpenPrice { get; set; } - - [JsonPropertyName("closePrice")] - public double? ClosePrice { get; set; } - - [JsonPropertyName("totalVolume")] - public double? TotalVolume { get; set; } - - [JsonPropertyName("tradeDate")] - public DateTime TradeDate { get; set; } - - [JsonPropertyName("quoteTimeInLong")] - public long? QuoteTimeInLong { get; set; } - - [JsonPropertyName("tradeTimeInLong")] - public long? TradeTimeInLong { get; set; } - - [JsonPropertyName("netChange")] - public double? NetChange { get; set; } - - [JsonPropertyName("volatility")] - public double? Volatility { get; set; } - - [JsonPropertyName("delta")] - public double? Delta { get; set; } - - [JsonPropertyName("gamma")] - public double? Gamma { get; set; } - - [JsonPropertyName("theta")] - public double? Theta { get; set; } - - [JsonPropertyName("vega")] - public double? Vega { get; set; } - - [JsonPropertyName("rho")] - public double? Rho { get; set; } - - [JsonPropertyName("timeValue")] - public double? TimeValue { get; set; } - - [JsonPropertyName("openInterest")] - public double? OpenInterest { get; set; } - - [JsonPropertyName("inTheMoney")] - public bool? IsInTheMoney { get; set; } - - [JsonPropertyName("theoreticalOptionValue")] - public double? TheoreticalOptionValue { get; set; } - - [JsonPropertyName("theoreticalVolatility")] - public double? TheoreticalVolatility { get; set; } - - [JsonPropertyName("mini")] - public bool? IsMini { get; set; } - - [JsonPropertyName("nonStandard")] - public bool? IsNonStandard { get; set; } - - [JsonPropertyName("optionDeliverablesList")] - public List OptionDeliverablesList { get; set; } - - [JsonPropertyName("strikePrice")] - public double? StrikePrice { get; set; } - - [JsonPropertyName("lastTradingDay")] - public double? LastTradingDay { get; set; } - - [JsonPropertyName("expirationDate")] - public long? ExpirationDate { get; set; } - - [JsonPropertyName("expirationType")] - public string ExpirationType { get; set; } - - [JsonPropertyName("multiplier")] - public double? Multiplier { get; set; } - - [JsonPropertyName("intrinsicValue")] - public double? IntrinsicValue { get; set; } - - [JsonPropertyName("settlementType")] - public string SettlementType { get; set; } - - [JsonPropertyName("deliverableNote")] - public string DeliverableNote { get; set; } - - [JsonPropertyName("isIndexOption")] - public bool? IsIndexOption { get; set; } - - [JsonPropertyName("pennyPilot")] - public bool? IsPennyPilot { get; set; } - - [JsonPropertyName("percentChange")] - public double? PercentChange { get; set; } - - [JsonPropertyName("markChange")] - public double? MarkChange { get; set; } - - [JsonPropertyName("markPercentChange")] - public double? MarkPercentChange { get; set; } - } - - public struct OptionDeliverables - { - [JsonPropertyName("symbol")] - public string Symbol { get; set; } - - [JsonPropertyName("assetType")] - public string AssetType { get; set; } - - [JsonPropertyName("deliverableUnits")] - public string DeliverableUnits { get; set; } - - [JsonPropertyName("currencyType")] - public string CurrencyType { get; set; } - } - - public struct OptionChain - { - [JsonPropertyName("symbol")] - public string Symbol { get; set; } - - [JsonPropertyName("status")] - public string Status { get; set; } - - [JsonPropertyName("underlying")] - public Underlying? Underlying { get; set; } - - [JsonPropertyName("strategy")] - public string Strategy { get; set; } - - [JsonPropertyName("interval")] - public double? Interval { get; set; } - - [JsonPropertyName("isDelayed")] - public bool? IsDelayed { get; set; } - - [JsonPropertyName("isIndex")] - public bool? IsIndex { get; set; } - - [JsonPropertyName("daysToExpiration")] - public double? DaysToExpiration { get; set; } - - [JsonPropertyName("interestRate")] - public double? InterestRate { get; set; } - - [JsonPropertyName("underlyingPrice")] - public double? UnderlyingPrice { get; set; } - - [JsonPropertyName("volatility")] - public double? Volatility { get; set; } - - [JsonPropertyName("callExpDateMap")] - public Dictionary>> CallExpDateMap { get; set; } - - [JsonPropertyName("putExpDateMap")] - public Dictionary>> PutExpDateMap { get; set; } - } - - public struct Underlying - { - [JsonPropertyName("ask")] - public double? Ask { get; set; } - - [JsonPropertyName("askSize")] - public double? AskSize { get; set; } - - [JsonPropertyName("bid")] - public double? Bid { get; set; } - - [JsonPropertyName("bidSize")] - public double? BidSize { get; set; } - - [JsonPropertyName("change")] - public double? Change { get; set; } - - [JsonPropertyName("close")] - public double? Close { get; set; } - - [JsonPropertyName("delayed")] - public bool? Delayed { get; set; } - - [JsonPropertyName("description")] - public string Description { get; set; } - - [JsonPropertyName("exchangeName")] - public string ExchangeName { get; set; } - - [JsonPropertyName("fiftyTwoWeekHigh")] - public double? FiftyTwoWeekHigh { get; set; } - - [JsonPropertyName("fiftyTwoWeekLow")] - public double? FiftyTwoWeekLow { get; set; } - - [JsonPropertyName("highPrice")] - public double? HighPrice { get; set; } - - [JsonPropertyName("last")] - public double? Last { get; set; } - - [JsonPropertyName("lowPrice")] - public double? LowPrice { get; set; } - - [JsonPropertyName("mark")] - public double? Mark { get; set; } - - [JsonPropertyName("markChange")] - public double? MarkChange { get; set; } - - [JsonPropertyName("markPercentChange")] - public double? MarkPercentChange { get; set; } - - [JsonPropertyName("openPrice")] - public double? OpenPrice { get; set; } - - [JsonPropertyName("percentChange")] - public double? PercentChange { get; set; } - - [JsonPropertyName("quoteTime")] - public double? QuoteTime { get; set; } - - [JsonPropertyName("symbol")] - public string Symbol { get; set; } - - [JsonPropertyName("totalVolume")] - public double? TotalVolume { get; set; } - - [JsonPropertyName("tradeTime")] - public double? TradeTime { get; set; } - } -} diff --git a/Gateways/Schwab/Libs/Models/UserModels.cs b/Gateways/Schwab/Libs/Models/UserModels.cs deleted file mode 100644 index d19eb67cf..000000000 --- a/Gateways/Schwab/Libs/Models/UserModels.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Text.Json.Serialization; - -namespace Terminal.Gateway.Ameritrade.Models -{ - public struct UserModel - { - [JsonPropertyName("redirect_url")] - public string RedirectUrl { get; set; } - - [JsonPropertyName("consumer_key")] - public string ConsumerKey { get; set; } - - [JsonPropertyName("security_code")] - public string SecurityCode { get; set; } - - [JsonPropertyName("access_token")] - public string AccessToken { get; set; } - - [JsonPropertyName("refresh_token")] - public string RefreshToken { get; set; } - - [JsonPropertyName("scope")] - public string Scope { get; set; } - - [JsonPropertyName("expires_in")] - public int ExpiresIn { get; set; } - - [JsonPropertyName("expiration_date")] - public long ExpirationDate { get; set; } - - [JsonPropertyName("refresh_token_expires_in")] - public int RefreshTokenExpiresIn { get; set; } - - [JsonPropertyName("token_type")] - public string TokenType { get; set; } - } -} diff --git a/Gateways/Schwab/Libs/Schwab.csproj b/Gateways/Schwab/Libs/Schwab.csproj index 904abfd12..d61770efa 100644 --- a/Gateways/Schwab/Libs/Schwab.csproj +++ b/Gateways/Schwab/Libs/Schwab.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/Gateways/Schwab/Tests/Tests.csproj b/Gateways/Schwab/Tests/Tests.csproj index 1429be5bf..65f604f25 100644 --- a/Gateways/Schwab/Tests/Tests.csproj +++ b/Gateways/Schwab/Tests/Tests.csproj @@ -8,10 +8,10 @@ - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Gateways/Simulation/Libs/Adapter.cs b/Gateways/Simulation/Libs/Adapter.cs index 5a5d1b302..3d7291d59 100644 --- a/Gateways/Simulation/Libs/Adapter.cs +++ b/Gateways/Simulation/Libs/Adapter.cs @@ -1,5 +1,4 @@ using Distribution.Services; -using Mapper; using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -41,8 +40,6 @@ public class Adapter : Gateway, IDisposable /// public virtual string Source { get; set; } - public virtual ScheduleService Scheduler { get; set; } = new(); - /// /// Constructor /// @@ -123,7 +120,7 @@ public override Task> Disconnect() Account.Instruments.ForEach(async o => await Unsubscribe(o.Key)); Account.Positions.CollectionChanged -= OnPositionUpdate; - _connections?.ForEach(o => o.Dispose()); + _connections?.ForEach(o => o?.Dispose()); _connections?.Clear(); return Task.FromResult>(null); @@ -145,23 +142,11 @@ public override Task> Unsubscribe(string name) return Task.FromResult>(null); } - /// - /// Get quote - /// - /// - public override Task> GetPoint(PointMessageModel message) - { - return Task.FromResult(new ResponseItemModel - { - Data = Account.Instruments[message.Name].Points.LastOrDefault() - }); - } - /// /// Create order and depending on the account, send it to the processing queue /// /// - public override Task> SendOrders(params OrderModel[] orders) + public override Task> CreateOrders(params OrderModel[] orders) { var response = ValidateOrders([.. CorrectOrders(orders)]); @@ -188,7 +173,7 @@ public override Task> SendOrders(params OrderModel[ /// Recursively cancel orders /// /// - public override Task> CancelOrders(params OrderModel[] orders) + public override Task> DeleteOrders(params OrderModel[] orders) { var response = new ResponseMapModel(); @@ -209,8 +194,8 @@ protected virtual void OnOrderUpdate(StateModel message) { switch (message.Action) { - case ActionEnum.Create: SendOrders(message.Next); break; - case ActionEnum.Delete: CancelOrders(message.Next); break; + case ActionEnum.Create: CreateOrders(message.Next); break; + case ActionEnum.Delete: DeleteOrders(message.Next); break; } } diff --git a/Gateways/Simulation/Libs/Simulation.csproj b/Gateways/Simulation/Libs/Simulation.csproj index 9a42cb168..3978e0c03 100644 --- a/Gateways/Simulation/Libs/Simulation.csproj +++ b/Gateways/Simulation/Libs/Simulation.csproj @@ -2,7 +2,6 @@ net8.0 - True disable disable diff --git a/Gateways/Simulation/Tests/CreateOrders.cs b/Gateways/Simulation/Tests/CreateOrders.cs index e0e0e0404..6afb51377 100644 --- a/Gateways/Simulation/Tests/CreateOrders.cs +++ b/Gateways/Simulation/Tests/CreateOrders.cs @@ -23,7 +23,7 @@ public void CreateOrdersWithEmptyOrder() { var order = new OrderModel(); - base.SendOrders(order); + base.CreateOrders(order); Assert.Empty(Account.Orders); Assert.Empty(Account.Positions); @@ -71,7 +71,7 @@ public void CreateBasicOrders( } }; - base.SendOrders(order); + base.CreateOrders(order); Assert.Equal(orders, Account.Orders.Count); Assert.Equal(activeOrders, Account.ActiveOrders.Count); diff --git a/Gateways/Simulation/Tests/DecreasePosition.cs b/Gateways/Simulation/Tests/DecreasePosition.cs index 43430e2f8..1c508e57f 100644 --- a/Gateways/Simulation/Tests/DecreasePosition.cs +++ b/Gateways/Simulation/Tests/DecreasePosition.cs @@ -209,8 +209,8 @@ public void Inverse() Transaction = new() { Volume = 2, Instrument = instrumentY } }; - base.SendOrders(orderX); - base.SendOrders(orderY); + base.CreateOrders(orderX); + base.CreateOrders(orderY); // Price diff --git a/Gateways/Simulation/Tests/IncreasePosition.cs b/Gateways/Simulation/Tests/IncreasePosition.cs index 2f5ef6db3..44f828d62 100644 --- a/Gateways/Simulation/Tests/IncreasePosition.cs +++ b/Gateways/Simulation/Tests/IncreasePosition.cs @@ -116,8 +116,8 @@ public void Increase() Transaction = new() { Volume = 1, Instrument = instrumentY } }; - base.SendOrders(orderX); - base.SendOrders(orderY); + base.CreateOrders(orderX); + base.CreateOrders(orderY); // Price diff --git a/Gateways/Simulation/Tests/Tests.csproj b/Gateways/Simulation/Tests/Tests.csproj index 1fb0d08be..3ae1ed95c 100644 --- a/Gateways/Simulation/Tests/Tests.csproj +++ b/Gateways/Simulation/Tests/Tests.csproj @@ -8,10 +8,10 @@ - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all