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"); }
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"); }
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)); } }