internal void Start(StrategyContext strategyContext) { _strategy = _strategyFactory.GetStrategy( strategyContext.StrategyName, async(trades, candle) => { //TODO: move messages to on sell event await _telegram.SendMessageAsync($"{strategyContext.Market.ToUpperInvariant()} Buy signal @ {candle.Close} Will buy? {!trades.Any() || trades[trades.Count - 1].Direction == TradeDirection.Sell}"); return(!trades.Any() || trades[trades.Count - 1].Direction == TradeDirection.Sell); }, async(trades, candle) => { await _telegram.SendMessageAsync($"{strategyContext.Market.ToUpperInvariant()} Sell Signal @ {candle.Close} Will sell? {trades.Any() && trades[trades.Count - 1].Direction == TradeDirection.Buy}"); return(trades.Any() && trades[trades.Count - 1].Direction == TradeDirection.Buy); }); var cancellationToken = _cancellationTokenSource.Token; Task.Run(() => ExecuteStrategy(strategyContext, cancellationToken), cancellationToken); // For now I dont use websockts because too fast updates, maybe I should only take into consideration closed candles for signals? // Maybe add 2 modes and test how they perform in the market //candles.ForEach(c => _candles.Add(c.OpenTime, c)); //var subscription = new BinanceKLineSubscription() //{ // Symbol = strategyContext.Market.ToLowerInvariant(), // Interval = "1h" //}; //await _binanceApi.ConnectToWebSockets(subscription, OnCandleUpdate, cancellationToken); }
public async Task SendMessageToTelegramAsync(Update[] updates, TelegramApi api) { foreach (var update in updates) { if (update?.CallbackQuery != null) { if (update.CallbackQuery.Data == "старт") { await api.SendMessageAsync("Поехали!", update.CallbackQuery.Message.Chat.Id, GetKeyboard("")); } } else { var question = update?.Message?.Text; var answer = await AnswerQuestionAsync(question); await api.SendMessageAsync(answer, update.Message.Chat.Id, GetKeyboard(question?.ToLowerInvariant())); } } }
private async Task RunTestAsync(string market, string candleSize, string strategyName) { var candles = (await _api.GetCandles(market, candleSize, 1000)).ToList(); var strategy = _strategyFactory.GetStrategy(strategyName); await strategy.Execute(candles); var sb = new StringBuilder(); if (strategy.Trades.Any()) { decimal totalProfit = strategy.Trades.Last(t => t.Direction == TradeDirection.Sell).VolumeEur; sb.AppendLine($"Start-End Date:{candles.First().OpenDate} - {candles.Last().OpenDate} {(candles.First().OpenDate - candles.Last().OpenDate).Days} days"); sb.AppendLine($"InitialInvestment: {strategy.InitialInvestment}"); sb.AppendLine($"Pnl: {totalProfit.Round(2)} ({MathExtensions.PercentageDifference(strategy.InitialInvestment, totalProfit)}%)"); sb.AppendLine($"Trades: "); for (int i = 0; i < strategy.Trades.Count; i++) { var p = strategy.Trades[i]; if (p.Direction == TradeDirection.Buy) { var percentage = i > 0 ? MathExtensions.PercentageDifference(strategy.Trades[i - 1].Volume, p.Volume) : 0; sb.AppendLine($"{p.TradeDate}: {p.Direction} >> {Math.Round(p.VolumeEur, 2)}EUR * {p.Price.Round(2)} = {p.Volume.Round(2)}??? ({percentage.Round(2)}%)"); } if (p.Direction == TradeDirection.Sell) { var percentage = i > 0 ? MathExtensions.PercentageDifference(strategy.Trades[i - 1].VolumeEur, p.VolumeEur) : 0; sb.AppendLine($"{p.TradeDate}: {p.Direction} >> {strategy.Trades[i - 1].Volume.Round(2)}??? @ {p.Price.Round(2)} = {Math.Round(p.VolumeEur, 2)}EUR ({percentage.Round(2)}%)"); } } } else { sb.AppendLine("No trades executed"); } await _telegram.SendMessageAsync(sb.ToString()); }
protected override async Task ExecuteAsync(CancellationToken token) { _logger.LogInformation("Signals Service Executing.."); _telegram.StartReceivingMessages(token, Telegram_OnMessageReceived); await _telegram.SendMessageAsync("Creepto signals bot started.."); }