using Discord; using Discord.Commands; using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Trading.Commands; using Managing.Common; using Managing.Core; using Managing.Domain.MoneyManagements; using Managing.Domain.Trades; using Managing.Domain.Users; using static Managing.Common.Enums; namespace Managing.Infrastructure.Messengers.Discord { public class DiscordCommands : ModuleBase { private readonly DiscordSettings _settings; private readonly IBacktester _backtester; private readonly string[] _separator = new[] { " " }; private readonly string _messagePrefix = "Bro, "; private readonly ICommandHandler _openTradeCommandHandler; public DiscordCommands(DiscordSettings settings, IBacktester backtester, ICommandHandler openTradeCommandHandler) { _settings = settings; _backtester = backtester; _openTradeCommandHandler = openTradeCommandHandler; } [Command("openposition")] public async Task OpenPosition([Remainder] string rest) { Typing(); var parameters = rest.Split(_separator, StringSplitOptions.None); var exchange = MiscExtensions.ParseEnum(parameters[0]); var ticker = parameters[1]; var direction = MiscExtensions.ParseEnum(parameters[2]); var timeframe = MiscExtensions.ParseEnum(parameters[3]); var expirationDate = DateTime.Now.AddMinutes(_settings.ButtonExpirationMinutes).ToString("G"); var builder = new ComponentBuilder().WithButton("Open Position", $"{Constants.DiscordButtonAction.OpenPosition}-{exchange}-{ticker}-{direction}-{timeframe}-{expirationDate}"); await Context.Channel.SendMessageAsync( _messagePrefix + $"you can now click on this button to open a position on {ticker}" , components: builder.Build()); } [Command("open")] public async Task Open([Remainder] string rest) { await Context.Channel.SendMessageAsync("Let met few seconds to open a position"); Typing(); try { var parameters = rest.Split(_separator, StringSplitOptions.None); var accountName = parameters[0]; var ticker = MiscExtensions.ParseEnum(parameters[1]); var direction = MiscExtensions.ParseEnum(parameters[2]); var riskLevel = MiscExtensions.ParseEnum(parameters[3]); var timeframe = MiscExtensions.ParseEnum(parameters[4]); decimal? stopLoss = parameters[5] != null ? Convert.ToDecimal(parameters[5]) : null; decimal? takeProfit = parameters[6] != null ? Convert.ToDecimal(parameters[6]) : null; var moneymanagement = new MoneyManagement { BalanceAtRisk = 5, StopLoss = stopLoss.GetValueOrDefault(), TakeProfit = takeProfit.GetValueOrDefault(), }; var tradeCommand = new OpenPositionRequest(accountName, moneymanagement, direction, ticker, PositionInitiator.User, DateTime.UtcNow, new User()); var result = await _openTradeCommandHandler.Handle(tradeCommand); var builder = new ComponentBuilder().WithButton("Close Position", $"{Constants.DiscordButtonAction.ClosePosition}|{result.Open.ExchangeOrderId}"); await Context.Channel.SendMessageAsync(MessengerHelpers.GetPositionMessage(result), components: builder.Build()); } catch (Exception ex) { await Context.Channel.SendMessageAsync($"Something weird happen bro, {ex.Message}"); } } [Command("bot")] public async Task Bot([Remainder] string rest) { Typing(); if (string.Equals(rest, "enable", StringComparison.OrdinalIgnoreCase)) { _settings.BotEnabled = true; } if (string.Equals(rest, "disable", StringComparison.OrdinalIgnoreCase)) { _settings.BotEnabled = false; } await Context.Channel.SendMessageAsync("Bot is " + (_settings.BotEnabled ? "enabled" : "disabled")); } //[Command("backtest")] //public async Task Backtest([Remainder] string rest) //{ // Typing(); // var parameters = rest.Split(_separator, StringSplitOptions.None); // var ticker = MiscExtensions.ParseEnum(parameters[0]); // var exchange = MiscExtensions.ParseEnum(parameters[1]); // var timeframe = MiscExtensions.ParseEnum(parameters[2]); // var days = parameters[3]; // var scenario = new Scenario("ScalpingScenario"); // var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 14); // scenario.AddStrategy(strategy); // var account = new Account() { Exchange = exchange }; // var backtestResult = _backtester.RunScalpingBotBacktest(account, ticker, scenario, timeframe, Convert.ToDouble(days), 1000); // await Context.Channel.SendMessageAsync(backtestResult.GetStringReport()); //} [Command("run")] public async Task Run([Remainder] string rest) { Typing(); var parameters = rest.Split(_separator, StringSplitOptions.None); var botType = MiscExtensions.ParseEnum(parameters[0]); var accountName = MiscExtensions.ParseEnum(parameters[1]); var botName = parameters[2]; var ticker = MiscExtensions.ParseEnum(parameters[3]); var timeframe = MiscExtensions.ParseEnum(parameters[4]); var message = _messagePrefix; // TODO : Fix remove mediator //var result = await _mediator.Send(new StartBotCommand(botType, // botName, // ticker, // "scenario", // timeframe, // accountName, // true)); var result = "down"; message += $"I tried to start the bot called {botName}, his status is now {result}. "; if (result == "Up") { await Context.Message.AddReactionAsync(new Emoji("👌")); message += $"this bot gonna watch {ticker} on {timeframe} timeframe."; } else { await Context.Message.AddReactionAsync(new Emoji("😒")); message += $"something wrong happen, the bot status is down"; } await Context.Channel.SendMessageAsync(message); } [Command("stop")] public async Task Stop([Remainder] string rest) { Typing(); var parameters = rest.Split(_separator, StringSplitOptions.None); var botType = MiscExtensions.ParseEnum(parameters[0]); var botName = parameters[1]; var result = "down"; //var result = await _mediator.Send(new StopBotCommand(botType, botName)); await Context.Channel.SendMessageAsync(_messagePrefix + $"the {botType} called {botName} is now {result}"); } [Command("hi")] public async Task Hi([Remainder] string rest) { Typing(); await Context.Channel.SendMessageAsync("I don't understand yet : " + rest); } [Command("help")] public async Task Help([Remainder] string rest) { Typing(); var message = _messagePrefix; switch (rest) { case "backtest": message += "to run a backtest you should use this pattern : !trader backtest ticker exchange timeframe startFromDays"; break; case "run": message += "to run a bot you should use this pattern : !trader run botType botName ticker timeframe"; break; case "stop": message += "to stop a bot you should use this pattern : !trader stop botType botName"; break; case "botType": message += $"the bot type available are : {BotType.FlippingBot}, {BotType.ScalpingBot}"; break; case "timeframe": message += $"the bot can currently handle only those timeframes : " + $"{Timeframe.FifteenMinutes}, {Timeframe.ThirtyMinutes}, {Timeframe.OneDay}"; break; case "risklevel": message += $"the bot can currently handle only those riskLevel : " + $"{RiskLevel.High}"; break; default: message += "I don't no the command"; break; } await Context.Channel.SendMessageAsync(message); } private async void Typing() { await Context.Channel.TriggerTypingAsync(); } } }