private async Task TestStrategyOnStock(Strategy strategy, string stock, bool useHistoricaData)
        {
            var data = (await _alpacaClient.GetStockData(stock)).OrderByDescending(x => x.Time).ToList();

            var sizeOfTestSet = useHistoricaData ? data.Count / 5 : data.Count;
            var testData      = data.Take(sizeOfTestSet);

            strategy.HistoricalData = data.Skip(sizeOfTestSet).ToList();

            var ownTheStock = false;

            foreach (var min in testData)
            {
                bool?calledBuy = null;
                //Mock out client so if we want to buy or sell, we are buying or selling only one share
                _mockAlpacaClient
                .Setup(x => x.EnsurePositionExists(min.StockSymbol, min.ClosingPrice))
                .Callback(() => calledBuy = true)
                .ReturnsAsync(ownTheStock ? 0 : min.ClosingPrice);
                _mockAlpacaClient
                .Setup(x => x.EnsurePostionCleared(min.StockSymbol))
                .Callback(() => calledBuy = false)
                .ReturnsAsync(ownTheStock ? min.ClosingPrice : 0);

                await strategy.HandleMinuteAgg(min);

                ownTheStock = calledBuy ?? ownTheStock;
            }
        }
        public async Task Execute(IJobExecutionContext context)
        {
            _logger.LogInformation($"Starting {GetType().Name} job");

            foreach (var strategy in _strategies)
            {
                var stockData = await _alpacaClient.GetStockData(strategy.StockStrategy.StockSymbol, strategy.StockStrategy.TradingFrequency);

                if ((stockData?.Count ?? 0) == 0)
                {
                    throw new ArgumentException($"You stock symbol {strategy.StockStrategy.StockSymbol} is not valid.");
                }

                //TODO: Check if pattern day trader is true. If so do the below
                //If not, pull the last order time for a stock from alpaca directly to ensure we do not intra day trade.
                var orders = _trackingRepository.GetCompletedOrders(strategy.StockStrategy);

                if (orders.Any())
                {
                    var lastCompletedOrder = orders.Max(x => x.OrderPlacedTime);
                    var waitTime           = lastCompletedOrder.AddDays(1).AddMinutes(1) - DateTime.UtcNow;

                    if (waitTime.TotalMilliseconds > 0)
                    {
                        await Task.Delay((int)Math.Ceiling(waitTime.TotalMilliseconds));
                    }
                }

                await strategy.RunStrategy(stockData);
            }

            _logger.LogInformation($"Finished {GetType().Name} job");
        }
        public async Task Execute(IJobExecutionContext context)
        {
            _logger.LogInformation($"Starting {GetType().Name} job");

            if (!_strategies.Any())
            {
                //TODO: Move this somewhere better
                throw new ArgumentException($"No strategies given. You must provide at least on strategy.");
            }

            if (!await _alpacaClient.ConnectStreamApis())
            {
                throw new UnauthorizedAccessException("Failed to connect to streaming API. Authorization failed.");
            }

            _alpacaClient.SubscribeToTradeUpdates(async order => await _trackingRepository.CompleteOrder(order));

            foreach (var strategy in _strategies.Where(x => x.StockStrategy.TradingFrequency == Domain.TradingFrequency.Minute))
            {
                var stockData = await _alpacaClient.GetStockData(strategy.StockStrategy.StockSymbol, strategy.StockStrategy.TradingFrequency);

                if ((stockData?.Count ?? 0) == 0)
                {
                    throw new ArgumentException($"You stock symbol {strategy.StockStrategy.StockSymbol} is not valid.");
                }

                strategy.HistoricalData.AddRange(stockData);
                _alpacaClient.AddPendingMinuteAggSubscription(strategy.StockStrategy.StockSymbol, async y => await strategy.HandleNewData(y));
            }

            _alpacaClient.SubscribeToMinuteAgg();

            _logger.LogInformation($"Finished {GetType().Name} job");
        }
Exemplo n.º 4
0
        public async Task Execute(IJobExecutionContext context)
        {
            _logger.LogInformation($"Starting {GetType().Name} job");

            await _alpacaClient.DisconnectStreamApis();

            foreach (var strategy in _strategies.Where(x => x.StockStrategy.TradingFrequency == Domain.TradingFrequency.Minute))
            {
                var position = await _trackingRepository.GetOrCreateEmptyPosition(strategy.StockStrategy);

                if (position.NumberOfShares > 0)
                {
                    var marketPriceTask = _alpacaClient.GetStockData(position.StockSymbol, strategy.StockStrategy.TradingFrequency, 1);
                    await _alpacaClient.PlaceOrder(new Domain.Order
                    {
                        StockSymbol     = strategy.StockStrategy.StockSymbol,
                        MarketPrice     = (await marketPriceTask).FirstOrDefault()?.ClosingPrice ?? 0,
                        OrderPlacedTime = DateTime.UtcNow,
                        SharesBought    = position.NumberOfShares * (-1)
                    });
                }
            }

            _logger.LogInformation($"Finished {GetType().Name} job");
        }
Exemplo n.º 5
0
    private static async Task AutoTradeStocks(IAlpacaClient alpacaClient, StockConfig stockConfig, MLConfig mlConfig)
    {
        if ((stockConfig.Stock_List?.Count ?? 0) == 0)
        {
            throw new ArgumentException("You must pass an least one valid stock symbol", nameof(stockConfig));
        }

        var strategies = new List <Strategy>()
        {
            new MeanReversionStrategy(alpacaClient),
            new MLStrategy(alpacaClient, mlConfig),
            new MicrotrendStrategy(alpacaClient),
            //new NewsStrategy(alpacaClient, config.Get<NewsSearchConfig>()),
        };

        var strategy = strategies
                       .SingleOrDefault(x => string.Equals(x.GetType().Name, stockConfig.Stock_Strategy, StringComparison.OrdinalIgnoreCase));

        if (strategy == null)
        {
            throw new ArgumentException($"Could not find any strategies with the name '{stockConfig.Stock_Strategy}'", nameof(stockConfig));
        }

        if (!await alpacaClient.ConnectStreamApi())
        {
            throw new UnauthorizedAccessException("Failed to connect to streaming API. Authorization failed.");
        }

        foreach (var stockSymbol in stockConfig.Stock_List)
        {
            var stockData = await alpacaClient.GetStockData(stockSymbol);

            if ((stockData?.Count ?? 0) == 0)
            {
                throw new ArgumentException($"You stock symbol {stockSymbol} is not valid.", nameof(stockConfig));
            }

            strategy.HistoricalData = stockData;
            alpacaClient.SubscribeMinuteAgg(stockSymbol, async y => await strategy.HandleMinuteAgg(y));
        }
    }