public AlpacaClient(AlpacaConfig config) { _config = config; _alpacaTradingClient = config.Alpaca_Use_Live_Api ? Environments.Live.GetAlpacaTradingClient(new SecretKey(_config.Alpaca_Live_App_Id, _config.Alpaca_Live_Secret_Key)) : Environments.Paper.GetAlpacaTradingClient(new SecretKey(_config.Alpaca_Paper_App_Id, _config.Alpaca_Paper_Secret_Key)); _alpacaDataClient = config.Alpaca_Use_Live_Api ? Environments.Live.GetAlpacaDataClient(new SecretKey(_config.Alpaca_Live_App_Id, _config.Alpaca_Live_Secret_Key)) : Environments.Paper.GetAlpacaDataClient(new SecretKey(_config.Alpaca_Paper_App_Id, _config.Alpaca_Paper_Secret_Key)); _alpacaStreamingClient = config.Alpaca_Use_Live_Api ? Environments.Live.GetAlpacaDataStreamingClient(new SecretKey(_config.Alpaca_Live_App_Id, _config.Alpaca_Live_Secret_Key)) : Environments.Paper.GetAlpacaDataStreamingClient(new SecretKey(_config.Alpaca_Paper_App_Id, _config.Alpaca_Paper_Secret_Key)); }
public AlpacaClient( IAlpacaTradingClient alpacaTradingClient, IAlpacaStreamingClient alpacaTradingStreamingClient, IAlpacaDataClient alpacaDataClient, IAlpacaDataStreamingClient alpacaDataStreamingClient ) { _alpacaTradingClient = alpacaTradingClient ?? throw new ArgumentNullException(nameof(alpacaTradingClient)); _alpacaTradingStreamingClient = alpacaTradingStreamingClient ?? throw new ArgumentNullException(nameof(alpacaTradingStreamingClient)); _alpacaDataClient = alpacaDataClient ?? throw new ArgumentNullException(nameof(alpacaDataClient)); _alpacaDataStreamingClient = alpacaDataStreamingClient ?? throw new ArgumentNullException(nameof(alpacaDataStreamingClient)); _stockActions = new Dictionary <string, List <Action <StockInput> > >(StringComparer.OrdinalIgnoreCase); }
public async Task <object> GetData_Daily(Data.Asset asset, int limit = 500) { try { IAlpacaDataClient data = null; if (!String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Key) && !String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Secret)) { data = Environments.Live.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret)); } else if (!String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Key) && !String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Secret)) { data = Environments.Paper.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret)); } else { return(new ArgumentNullException()); } // Maximum 1000 bars per API call var bars = await data.GetBarSetAsync(new BarSetRequest(asset.Symbol, TimeFrame.Day) { Limit = limit }); Data.Daily ds = new Data.Daily(); foreach (var bar in bars[asset.Symbol]) { if (bar.TimeUtc != null) { ds.Prices.Add(new Data.Daily.Price() { Date = bar.TimeUtc ?? new DateTime(), Open = bar.Open, High = bar.High, Low = bar.Low, Close = bar.Close, Volume = bar.Volume }); } } return(ds); } catch (Exception ex) { if (ex.Message != "Too Many Requests") // This is handled elsewhere- does not need to be error logged { await Log.Error($"{MethodBase.GetCurrentMethod().DeclaringType}: {MethodBase.GetCurrentMethod().Name}", ex); } return(ex.Message); } }
public async Task <object> GetOrders_Open(Data.Format format) { IAlpacaTradingClient trading = null; IAlpacaDataClient data = null; try { if (format == Data.Format.Live) { if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Secret)) { return(null); } trading = Environments.Live.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret)); data = Environments.Live.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret)); } else if (format == Data.Format.Paper) { if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Secret)) { return(null); } trading = Environments.Paper.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret)); data = Environments.Paper.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret)); } return((await trading.ListOrdersAsync( new ListOrdersRequest() { OrderStatusFilter = OrderStatusFilter.Open, LimitOrderNumber = 1000 })) .Select <IOrder, Data.Order>((q) => { return new Data.Order() { Symbol = q.Symbol, Transaction = q.OrderSide == OrderSide.Buy ? Data.Order.Direction.Buy : Data.Order.Direction.Sell, Quantity = (int)q.Quantity }; }) .ToList()); } catch (Exception ex) { await Log.Error($"{MethodBase.GetCurrentMethod().DeclaringType}: {MethodBase.GetCurrentMethod().Name}", ex); return(ex.Message); } }
public async Task <Trading.OrderResult> PlaceOrder_BuyMarket( Data.Format format, string symbol, int shares, TimeInForce timeInForce = TimeInForce.Gtc, bool useMargin = false) { IAlpacaTradingClient trading = null; IAlpacaDataClient data = null; try { if (format == Data.Format.Live) { if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Secret)) { return(Trading.OrderResult.Fail); } trading = Environments.Live.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret)); data = Environments.Live.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret)); } else if (format == Data.Format.Paper) { if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Secret)) { return(Trading.OrderResult.Fail); } trading = Environments.Paper.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret)); data = Environments.Paper.GetAlpacaDataClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret)); } var account = await trading.GetAccountAsync(); if (trading == null || account == null || account.IsAccountBlocked || account.IsTradingBlocked || account.TradeSuspendedByUser) { return(Trading.OrderResult.Fail); } var order = await trading.PostOrderAsync(MarketOrder.Buy(symbol, shares).WithDuration(timeInForce)); return(Trading.OrderResult.Success); } catch (Exception ex) { await Log.Error($"{MethodBase.GetCurrentMethod().DeclaringType}: {MethodBase.GetCurrentMethod().Name}", ex); return(Trading.OrderResult.Fail); } }
/// <summary> /// Gets all items provided by <see cref="IAlpacaDataClient.ListHistoricalBarsAsync"/> in pagination /// mode as single stream of items (in form of <see cref="IAsyncEnumerable{IAgg}"/> interface) so they /// can be consumed by the <c>await foreach</c> statement on the caller side. /// </summary> /// <param name="client">Target instance of the <see cref="IAlpacaDataClient"/> interface.</param> /// <param name="request">Original historical minute bars request (with empty next page token).</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> /// <returns></returns> public static IAsyncEnumerable <IAgg> GetHistoricalBarsAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalBarsRequest request, CancellationToken cancellationToken = default) => getPaginatedResponsesAsAsyncEnumerable(
public async Task Run() { alpacaTradingClient = Environments.Paper.GetAlpacaTradingClient(new SecretKey(API_KEY, API_SECRET)); alpacaDataClient = Environments.Paper.GetAlpacaDataClient(new SecretKey(API_KEY, API_SECRET)); // Connect to Alpaca's websocket and listen for updates on our orders. alpacaStreamingClient = Environments.Paper.GetAlpacaStreamingClient(new SecretKey(API_KEY, API_SECRET)); alpacaStreamingClient.ConnectAndAuthenticateAsync().Wait(); alpacaStreamingClient.OnTradeUpdate += HandleTradeUpdate; // First, cancel any existing orders so they don't impact our buying power. var orders = await alpacaTradingClient.ListOrdersAsync(new ListOrdersRequest()); foreach (var order in orders) { await alpacaTradingClient.DeleteOrderAsync(order.OrderId); } // Figure out when the market will close so we can prepare to sell beforehand. var calendars = (await alpacaTradingClient .ListCalendarAsync(new CalendarRequest().SetTimeInterval(DateTime.Today.GetInclusiveIntervalFromThat()))) .ToList(); var calendarDate = calendars.First().TradingDateUtc; var closingTime = calendars.First().TradingCloseTimeUtc; closingTime = new DateTime(calendarDate.Year, calendarDate.Month, calendarDate.Day, closingTime.Hour, closingTime.Minute, closingTime.Second); var today = DateTime.Today; // TODO: olegra - temporary disable for the transition period // Get the first group of bars from today if the market has already been open. //var bars = await alpacaDataClient.ListAggregatesAsync( // new AggregatesRequest(symbol, new AggregationPeriod(1, AggregationPeriodUnit.Minute)) // .SetInclusiveTimeInterval(today, today.AddDays(1))); //var lastBars = bars.Items.Skip(Math.Max(0, bars.Items.Count() - 20)); //foreach (var bar in lastBars) //{ // if (bar.TimeUtc?.Date == today) // { // closingPrices.Add(bar.Close); // } //} Console.WriteLine("Waiting for market open..."); await AwaitMarketOpen(); Console.WriteLine("Market opened."); // Connect to Polygon's websocket and listen for price updates. alpacaDataStreamingClient = Environments.Live.GetAlpacaDataStreamingClient(new SecretKey(API_KEY, API_SECRET)); alpacaDataStreamingClient.ConnectAndAuthenticateAsync().Wait(); Console.WriteLine("Polygon client opened."); var subscription = alpacaDataStreamingClient.GetMinuteAggSubscription(symbol); subscription.Received += async(agg) => { // If the market's close to closing, exit position and stop trading. TimeSpan minutesUntilClose = closingTime - DateTime.UtcNow; if (minutesUntilClose.TotalMinutes < 15) { Console.WriteLine("Reached the end of trading window."); await ClosePositionAtMarket(); await alpacaDataStreamingClient.DisconnectAsync(); } else { // Decide whether to buy or sell and submit orders. await HandleMinuteAgg(agg); } }; alpacaDataStreamingClient.Subscribe(subscription); }
public static IAsyncEnumerable <IReadOnlyList <IBar> > GetHistoricalBarsPagesAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalBarsRequest request) => GetHistoricalBarsPagesAsAsyncEnumerable(client, request, CancellationToken.None);
public static IReadOnlyDictionary <String, IAsyncEnumerable <IBar> > GetHistoricalBarsDictionaryOfAsyncEnumerable( this IAlpacaDataClient client, HistoricalBarsRequest request, CancellationToken cancellationToken) => getValidatedRequestWithoutPageToken(request.EnsureNotNull(nameof(request))) .GetResponsesByItems(client.EnsureNotNull(nameof(client)).GetHistoricalBarsAsync, cancellationToken);
public static IReadOnlyDictionary <String, IAsyncEnumerable <IBar> > GetHistoricalBarsDictionaryOfAsyncEnumerable( this IAlpacaDataClient client, HistoricalBarsRequest request) => GetHistoricalBarsDictionaryOfAsyncEnumerable(client, request, CancellationToken.None);
public AlpacaDataClientTest(PaperEnvironmentClientsFactoryFixture clientsFactory) { _clientsFactory = clientsFactory; _alpacaDataClient = clientsFactory.GetAlpacaDataClient(); }
public static IAsyncEnumerable <IReadOnlyDictionary <String, IReadOnlyList <ITrade> > > GetHistoricalTradesMultiPagesAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalTradesRequest request, CancellationToken cancellationToken) => getValidatedRequestWithoutPageToken(request.EnsureNotNull(nameof(request))) .GetResponsesByPages(client.EnsureNotNull(nameof(client)).GetHistoricalTradesAsync, cancellationToken);
public static IAsyncEnumerable <IReadOnlyDictionary <String, IReadOnlyList <ITrade> > > GetHistoricalTradesMultiPagesAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalTradesRequest request) => GetHistoricalTradesMultiPagesAsAsyncEnumerable(client, request, CancellationToken.None);
public static IAsyncEnumerable <ITrade> GetHistoricalTradesAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalTradesRequest request, CancellationToken cancellationToken) => getValidatedRequestWithoutPageToken(request.EnsureNotNull(nameof(request))) .GetResponsesByItems(client.EnsureNotNull(nameof(client)).ListHistoricalTradesAsync, cancellationToken);
public static IAsyncEnumerable <ITrade> GetHistoricalTradesAsAsyncEnumerable( this IAlpacaDataClient client, HistoricalTradesRequest request) => GetHistoricalTradesAsAsyncEnumerable(client, request, CancellationToken.None);
public static Task <(Decimal, UInt32)> GetAverageDailyTradeVolumeAsync( this IAlpacaDataClient client, String symbol, DateTime from, DateTime into) =>
public static IAsyncEnumerable <IReadOnlyList <INewsArticle> > GetNewsArticlesPagesAsAsyncEnumerable( this IAlpacaDataClient client, NewsArticlesRequest request) => GetNewsArticlesPagesAsAsyncEnumerable(client, request, CancellationToken.None);
public async Task Run() { alpacaTradingClient = Environments.Paper.GetAlpacaTradingClient(new SecretKey(API_KEY, API_SECRET)); alpacaDataClient = Environments.Paper.GetAlpacaDataClient(new SecretKey(API_KEY, API_SECRET)); // First, cancel any existing orders so they don't impact our buying power. var orders = await alpacaTradingClient.ListOrdersAsync(new ListOrdersRequest()); foreach (var order in orders) { await alpacaTradingClient.DeleteOrderAsync(order.OrderId); } // Figure out when the market will close so we can prepare to sell beforehand. var calendars = (await alpacaTradingClient .ListCalendarAsync(new CalendarRequest().SetTimeInterval(DateTime.Today.GetInclusiveIntervalFromThat()))) .ToList(); var calendarDate = calendars.First().TradingDateUtc; var closingTime = calendars.First().TradingCloseTimeUtc; closingTime = new DateTime(calendarDate.Year, calendarDate.Month, calendarDate.Day, closingTime.Hour, closingTime.Minute, closingTime.Second); Console.WriteLine("Waiting for market open..."); await AwaitMarketOpen(); Console.WriteLine("Market opened."); // Check every minute for price updates. TimeSpan timeUntilClose = closingTime - DateTime.UtcNow; while (timeUntilClose.TotalMinutes > 15) { // Cancel old order if it's not already been filled. await alpacaTradingClient.DeleteOrderAsync(lastTradeId); // Get information about current account value. var account = await alpacaTradingClient.GetAccountAsync(); Decimal buyingPower = account.BuyingPower; Decimal portfolioValue = account.Equity; // Get information about our existing position. Int32 positionQuantity = 0; Decimal positionValue = 0; try { var currentPosition = await alpacaTradingClient.GetPositionAsync(symbol); positionQuantity = currentPosition.Quantity; positionValue = currentPosition.MarketValue; } catch (Exception) { // No position exists. This exception can be safely ignored. } var barSet = await alpacaDataClient.GetBarSetAsync( new BarSetRequest(symbol, TimeFrame.Minute) { Limit = 20 }); var bars = barSet[symbol].ToList(); Decimal avg = bars.Average(item => item.Close); Decimal currentPrice = bars.Last().Close; Decimal diff = avg - currentPrice; if (diff <= 0) { // Above the 20 minute average - exit any existing long position. if (positionQuantity > 0) { Console.WriteLine("Setting position to zero."); await SubmitOrder(positionQuantity, currentPrice, OrderSide.Sell); } else { Console.WriteLine("No position to exit."); } } else { // Allocate a percent of our portfolio to this position. Decimal portfolioShare = diff / currentPrice * scale; Decimal targetPositionValue = portfolioValue * portfolioShare; Decimal amountToAdd = targetPositionValue - positionValue; if (amountToAdd > 0) { // Buy as many shares as we can without going over amountToAdd. // Make sure we're not trying to buy more than we can. if (amountToAdd > buyingPower) { amountToAdd = buyingPower; } Int32 qtyToBuy = (Int32)(amountToAdd / currentPrice); await SubmitOrder(qtyToBuy, currentPrice, OrderSide.Buy); } else { // Sell as many shares as we can without going under amountToAdd. // Make sure we're not trying to sell more than we have. amountToAdd *= -1; Int32 qtyToSell = (Int32)(amountToAdd / currentPrice); if (qtyToSell > positionQuantity) { qtyToSell = positionQuantity; } await SubmitOrder(qtyToSell, currentPrice, OrderSide.Sell); } } // Wait another minute. Thread.Sleep(60000); timeUntilClose = closingTime - DateTime.UtcNow; } Console.WriteLine("Market nearing close; closing position."); await ClosePositionAtMarket(); }
public static IAsyncEnumerable <IReadOnlyList <INewsArticle> > GetNewsArticlesPagesAsAsyncEnumerable( this IAlpacaDataClient client, NewsArticlesRequest request, CancellationToken cancellationToken) => getValidatedRequestWithoutPageToken(request.EnsureNotNull(nameof(request))) .GetResponsesByPages(client.EnsureNotNull(nameof(client)).ListNewsArticlesAsync, cancellationToken);