Exemplo n.º 1
0
 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));
 }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
0
        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);
            }
        }
Exemplo n.º 5
0
        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);
            }
        }
Exemplo n.º 6
0
 /// <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);
        }
Exemplo n.º 8
0
 public static IAsyncEnumerable <IReadOnlyList <IBar> > GetHistoricalBarsPagesAsAsyncEnumerable(
     this IAlpacaDataClient client,
     HistoricalBarsRequest request) =>
 GetHistoricalBarsPagesAsAsyncEnumerable(client, request, CancellationToken.None);
Exemplo n.º 9
0
 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);
Exemplo n.º 10
0
 public static IReadOnlyDictionary <String, IAsyncEnumerable <IBar> > GetHistoricalBarsDictionaryOfAsyncEnumerable(
     this IAlpacaDataClient client,
     HistoricalBarsRequest request) =>
 GetHistoricalBarsDictionaryOfAsyncEnumerable(client, request, CancellationToken.None);
Exemplo n.º 11
0
 public AlpacaDataClientTest(PaperEnvironmentClientsFactoryFixture clientsFactory)
 {
     _clientsFactory   = clientsFactory;
     _alpacaDataClient = clientsFactory.GetAlpacaDataClient();
 }
Exemplo n.º 12
0
 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);
Exemplo n.º 13
0
 public static IAsyncEnumerable <IReadOnlyDictionary <String, IReadOnlyList <ITrade> > > GetHistoricalTradesMultiPagesAsAsyncEnumerable(
     this IAlpacaDataClient client,
     HistoricalTradesRequest request) =>
 GetHistoricalTradesMultiPagesAsAsyncEnumerable(client, request, CancellationToken.None);
Exemplo n.º 14
0
 public static IAsyncEnumerable <ITrade> GetHistoricalTradesAsAsyncEnumerable(
     this IAlpacaDataClient client,
     HistoricalTradesRequest request,
     CancellationToken cancellationToken) =>
 getValidatedRequestWithoutPageToken(request.EnsureNotNull(nameof(request)))
 .GetResponsesByItems(client.EnsureNotNull(nameof(client)).ListHistoricalTradesAsync, cancellationToken);
Exemplo n.º 15
0
 public static IAsyncEnumerable <ITrade> GetHistoricalTradesAsAsyncEnumerable(
     this IAlpacaDataClient client,
     HistoricalTradesRequest request) =>
 GetHistoricalTradesAsAsyncEnumerable(client, request, CancellationToken.None);
Exemplo n.º 16
0
 public static Task <(Decimal, UInt32)> GetAverageDailyTradeVolumeAsync(
     this IAlpacaDataClient client,
     String symbol,
     DateTime from,
     DateTime into) =>
Exemplo n.º 17
0
 public static IAsyncEnumerable <IReadOnlyList <INewsArticle> > GetNewsArticlesPagesAsAsyncEnumerable(
     this IAlpacaDataClient client,
     NewsArticlesRequest request) =>
 GetNewsArticlesPagesAsAsyncEnumerable(client, request, CancellationToken.None);
Exemplo n.º 18
0
        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();
        }
Exemplo n.º 19
0
 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);