From 4302bb8435cf376ee1ac37617ff2b981e71f207e Mon Sep 17 00:00:00 2001 From: Oda <102867384+CryptoOda@users.noreply.github.com> Date: Wed, 26 Feb 2025 17:24:59 +0700 Subject: [PATCH] Remove timeframe from strategy (#13) --- src/Managing.Api/Controllers/BotController.cs | 2 +- .../Controllers/ScenarioController.cs | 6 +-- src/Managing.Application.Tests/BotsTests.cs | 10 ++-- .../StrategyTests.cs | 14 ++--- .../Abstractions/IScenarioService.cs | 25 ++++----- .../Abstractions/ITradingBot.cs | 3 +- .../Backtesting/Backtester.cs | 8 +-- src/Managing.Application/Bots/FlippingBot.cs | 8 +-- src/Managing.Application/Bots/ScalpingBot.cs | 34 ++++++------- src/Managing.Application/Bots/TradingBot.cs | 41 ++++++++------- .../ManageBot/BotService.cs | 4 +- .../Scenarios/ScenarioService.cs | 12 ++--- .../Shared/SettingsService.cs | 51 ++++++++----------- .../Workflows/Flows/Strategies/RsiDiv.cs | 2 +- src/Managing.Domain/Scenarios/Scenario.cs | 7 ++- .../Scenarios/ScenarioHelpers.cs | 25 +++++---- .../Shared/Helpers/TradingBox.cs | 8 +-- .../Strategies/Base/EmaBaseStrategy.cs | 5 +- .../Strategies/ChandelierExitStrategy.cs | 20 ++++---- .../Strategies/EmaCrossStrategy.cs | 10 ++-- .../Strategies/EmaTrendStrategy.cs | 13 ++--- .../Strategies/MACDCrossStrategy.cs | 12 ++--- .../RSIDivergenceConfirmStrategy.cs | 28 +++++----- .../Strategies/RSIDivergenceStrategy.cs | 14 ++--- src/Managing.Domain/Strategies/STCStrategy.cs | 12 ++--- src/Managing.Domain/Strategies/Signal.cs | 44 ++++++---------- .../Strategies/StDevContext.cs | 11 ++-- .../Strategies/StochRsiTrendStrategy.cs | 17 ++++--- src/Managing.Domain/Strategies/Strategy.cs | 4 +- .../Strategies/SuperTrendStrategy.cs | 18 ++++--- .../Strategies/ThreeWhiteSoldiersStrategy.cs | 4 +- .../MongoDb/Collections/ScenarioDto.cs | 3 +- .../MongoDb/MongoMappers.cs | 9 ++-- .../TradingRepository.cs | 8 ++- .../Collections/StrategyDto.cs | 1 - .../src/generated/ManagingApi.ts | 14 +++-- src/Managing.WebApp/src/global/type.tsx | 36 +++++++++---- .../src/pages/scenarioPage/scenarioList.tsx | 27 +++++++--- .../src/pages/scenarioPage/strategyList.tsx | 17 +++---- 39 files changed, 299 insertions(+), 288 deletions(-) diff --git a/src/Managing.Api/Controllers/BotController.cs b/src/Managing.Api/Controllers/BotController.cs index 0e630ce..46afbcf 100644 --- a/src/Managing.Api/Controllers/BotController.cs +++ b/src/Managing.Api/Controllers/BotController.cs @@ -206,7 +206,7 @@ public class BotController : ControllerBase Timeframe = item.Timeframe, Ticker = item.Ticker, AccountName = item.AccountName, - Scenario = item.Scenario, + Scenario = item.ScenarioName, IsForWatchingOnly = item.IsForWatchingOnly, BotType = item.BotType, MoneyManagement = item.MoneyManagement diff --git a/src/Managing.Api/Controllers/ScenarioController.cs b/src/Managing.Api/Controllers/ScenarioController.cs index b2f89ed..07b380e 100644 --- a/src/Managing.Api/Controllers/ScenarioController.cs +++ b/src/Managing.Api/Controllers/ScenarioController.cs @@ -46,9 +46,9 @@ public class ScenarioController : ControllerBase /// A list of strategy names to include in the scenario. /// The created scenario. [HttpPost] - public ActionResult CreateScenario(string name, List strategies) + public ActionResult CreateScenario(string name, List strategies, int? loopbackPeriod = null) { - return Ok(_scenarioService.CreateScenario(name, strategies)); + return Ok(_scenarioService.CreateScenario(name, strategies, loopbackPeriod)); } /// @@ -92,7 +92,6 @@ public class ScenarioController : ControllerBase [Route("strategy")] public ActionResult CreateStrategy( StrategyType strategyType, - Timeframe timeframe, string name, int? period = null, int? fastPeriods = null, @@ -105,7 +104,6 @@ public class ScenarioController : ControllerBase { return Ok(_scenarioService.CreateStrategy( strategyType, - timeframe, name, period, fastPeriods, diff --git a/src/Managing.Application.Tests/BotsTests.cs b/src/Managing.Application.Tests/BotsTests.cs index 1917958..7d5b4ab 100644 --- a/src/Managing.Application.Tests/BotsTests.cs +++ b/src/Managing.Application.Tests/BotsTests.cs @@ -51,7 +51,7 @@ namespace Managing.Application.Tests { // Arrange var scenario = new Scenario("FlippingScenario"); - var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 14); + var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, "RsiDiv", period: 14); scenario.AddStrategy(strategy); var localCandles = FileHelpers.ReadJson>($"{ticker.ToString()}-{timeframe.ToString()}-candles.json"); @@ -83,7 +83,7 @@ namespace Managing.Application.Tests { // Arrange var scenario = new Scenario("ScalpingScenario"); - var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 5); + var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, "RsiDiv", period: 5); scenario.AddStrategy(strategy); // Act @@ -104,7 +104,7 @@ namespace Managing.Application.Tests { // Arrange var scenario = new Scenario("ScalpingScenario"); - var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, timeframe, "RsiDiv", fastPeriods: 12, + var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, "RsiDiv", fastPeriods: 12, slowPeriods: 26, signalPeriods: 9); scenario.AddStrategy(strategy); @@ -163,7 +163,7 @@ namespace Managing.Application.Tests Parallel.For(periodRange[0], periodRange[1], options, i => { var scenario = new Scenario("ScalpingScenario"); - var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", period: i); + var strategy = ScenarioHelpers.BuildStrategy(strategyType, "RsiDiv", period: i); scenario.AddStrategy(strategy); // -0.5 to -5 @@ -272,7 +272,7 @@ namespace Managing.Application.Tests return; var scenario = new Scenario("ScalpingScenario"); - var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", fastPeriods: 12, + var strategy = ScenarioHelpers.BuildStrategy(strategyType, "RsiDiv", fastPeriods: 12, slowPeriods: 26, signalPeriods: 9); scenario.AddStrategy(strategy); diff --git a/src/Managing.Application.Tests/StrategyTests.cs b/src/Managing.Application.Tests/StrategyTests.cs index b9af446..467534e 100644 --- a/src/Managing.Application.Tests/StrategyTests.cs +++ b/src/Managing.Application.Tests/StrategyTests.cs @@ -22,7 +22,7 @@ namespace Managing.Application.Tests { var account = GetAccount(exchange); // Arrange - var rsiStrategy = new RSIDivergenceStrategy("unittest", timeframe, 5); + var rsiStrategy = new RSIDivergenceStrategy("unittest", 5); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe).Result; var resultSignal = new List(); @@ -56,7 +56,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var rsiStrategy = new RSIDivergenceStrategy("unittest", timeframe, 5); + var rsiStrategy = new RSIDivergenceStrategy("unittest", 5); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe).Result; var resultSignal = new List(); @@ -83,7 +83,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var rsiStrategy = new MacdCrossStrategy("unittest", timeframe, 12, 26, 9); + var rsiStrategy = new MacdCrossStrategy("unittest", 12, 26, 9); var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe); var resultSignal = new List(); @@ -110,7 +110,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var superTrendStrategy = new SuperTrendStrategy("unittest", timeframe, 10, 3); + var superTrendStrategy = new SuperTrendStrategy("unittest", 10, 3); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result; var resultSignal = new List(); @@ -137,7 +137,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var chandelierExitStrategy = new ChandelierExitStrategy("unittest", timeframe, 22, 3); + var chandelierExitStrategy = new ChandelierExitStrategy("unittest", 22, 3); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result; var resultSignal = new List(); @@ -164,7 +164,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var emaTrendSrategy = new EmaTrendStrategy("unittest", timeframe, 200); + var emaTrendSrategy = new EmaTrendStrategy("unittest", 200); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result; var resultSignal = new List(); @@ -192,7 +192,7 @@ namespace Managing.Application.Tests { // Arrange var account = GetAccount(exchange); - var stochRsiStrategy = new StochRsiTrendStrategy("unittest", timeframe, 14, 14, 3, 1); + var stochRsiStrategy = new StochRsiTrendStrategy("unittest", 14, 14, 3, 1); var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result; var resultSignal = new List(); diff --git a/src/Managing.Application/Abstractions/IScenarioService.cs b/src/Managing.Application/Abstractions/IScenarioService.cs index d9cbd1b..0152c7e 100644 --- a/src/Managing.Application/Abstractions/IScenarioService.cs +++ b/src/Managing.Application/Abstractions/IScenarioService.cs @@ -7,23 +7,24 @@ namespace Managing.Application.Abstractions public interface IScenarioService { IEnumerable GetScenarios(); - Scenario CreateScenario(string name, List strategies); + Scenario CreateScenario(string name, List strategies, int? loopbackPeriod = 1); IEnumerable GetStrategies(); bool DeleteStrategy(string name); bool DeleteScenario(string name); Scenario GetScenario(string name); + Strategy CreateStrategy(StrategyType type, - Timeframe timeframe, - string name, - int? period = null, - int? fastPeriods = null, - int? slowPeriods = null, - int? signalPeriods = null, - double? multiplier = null, - int? stochPeriods = null, - int? smoothPeriods = null, - int? cyclePeriods = null); + string name, + int? period = null, + int? fastPeriods = null, + int? slowPeriods = null, + int? signalPeriods = null, + double? multiplier = null, + int? stochPeriods = null, + int? smoothPeriods = null, + int? cyclePeriods = null); + bool DeleteStrategies(); bool DeleteScenarios(); } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Abstractions/ITradingBot.cs b/src/Managing.Application/Abstractions/ITradingBot.cs index 0bc76ad..902f853 100644 --- a/src/Managing.Application/Abstractions/ITradingBot.cs +++ b/src/Managing.Application/Abstractions/ITradingBot.cs @@ -17,7 +17,7 @@ namespace Managing.Application.Abstractions Timeframe Timeframe { get; set; } HashSet Strategies { get; set; } Ticker Ticker { get; } - string Scenario { get; } + string ScenarioName { get; } string AccountName { get; } bool IsForWatchingOnly { get; set; } MoneyManagement MoneyManagement { get; set; } @@ -31,5 +31,6 @@ namespace Managing.Application.Abstractions decimal GetProfitAndLoss(); decimal GetTotalFees(); void LoadStrategies(IEnumerable strategies); + void LoadScenario(string scenarioName); } } \ No newline at end of file diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs index 201764b..674a7cb 100644 --- a/src/Managing.Application/Backtesting/Backtester.cs +++ b/src/Managing.Application/Backtesting/Backtester.cs @@ -58,7 +58,7 @@ namespace Managing.Application.Backtesting { var scalpingBot = _botFactory.CreateBacktestScalpingBot(account.Name, moneyManagement, ticker, "scenario", timeframe, isForWatchingOnly); - scalpingBot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario)); + scalpingBot.LoadScenario(scenario.Name); var candles = initialCandles ?? GetCandles(account, ticker, timeframe, days); var result = GetBacktestingResult(ticker, scenario, timeframe, scalpingBot, candles, balance, account, moneyManagement); @@ -88,8 +88,7 @@ namespace Managing.Application.Backtesting { var flippingBot = _botFactory.CreateBacktestFlippingBot(account.Name, moneyManagement, ticker, "scenario", timeframe, false); - var strategy = ScenarioHelpers.GetStrategiesFromScenario(scenario); - flippingBot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario)); + flippingBot.LoadScenario(scenario.Name); var candles = initialCandles ?? GetCandles(account, ticker, timeframe, days); var result = GetBacktestingResult(ticker, scenario, timeframe, flippingBot, candles, balance, account, moneyManagement); @@ -107,7 +106,7 @@ namespace Managing.Application.Backtesting var ticker = MiscExtensions.ParseEnum(candles.FirstOrDefault().Ticker); var bot = _botFactory.CreateBacktestScalpingBot(account.Name, moneyManagement, ticker, "scenario", timeframe, false); - bot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario)); + bot.LoadScenario(scenario.Name); var result = GetBacktestingResult(ticker, scenario, timeframe, bot, candles, balance, account, moneyManagement); return result; @@ -119,6 +118,7 @@ namespace Managing.Application.Backtesting var ticker = MiscExtensions.ParseEnum(candles.FirstOrDefault().Ticker); var bot = _botFactory.CreateBacktestFlippingBot(account.Name, moneyManagement, ticker, "scenario", timeframe, false); + bot.LoadScenario(scenario.Name); var result = GetBacktestingResult(ticker, scenario, timeframe, bot, candles, balance, account, moneyManagement); return result; diff --git a/src/Managing.Application/Bots/FlippingBot.cs b/src/Managing.Application/Bots/FlippingBot.cs index 9bf2270..956a130 100644 --- a/src/Managing.Application/Bots/FlippingBot.cs +++ b/src/Managing.Application/Bots/FlippingBot.cs @@ -1,8 +1,8 @@ using Managing.Application.Abstractions; -using Microsoft.Extensions.Logging; -using static Managing.Common.Enums; using Managing.Application.Abstractions.Services; using Managing.Domain.MoneyManagements; +using Microsoft.Extensions.Logging; +using static Managing.Common.Enums; namespace Managing.Application.Bots { @@ -11,7 +11,7 @@ namespace Managing.Application.Bots public FlippingBot(string accountName, MoneyManagement moneyManagement, string name, - string scenario, + string scenarioName, IExchangeService exchangeService, Ticker ticker, ITradingService tradingService, @@ -26,7 +26,7 @@ namespace Managing.Application.Bots moneyManagement, name, ticker, - scenario, + scenarioName, exchangeService, logger, tradingService, diff --git a/src/Managing.Application/Bots/ScalpingBot.cs b/src/Managing.Application/Bots/ScalpingBot.cs index f69c336..37e3d1b 100644 --- a/src/Managing.Application/Bots/ScalpingBot.cs +++ b/src/Managing.Application/Bots/ScalpingBot.cs @@ -1,8 +1,8 @@ using Managing.Application.Abstractions; -using Microsoft.Extensions.Logging; -using static Managing.Common.Enums; using Managing.Application.Abstractions.Services; using Managing.Domain.MoneyManagements; +using Microsoft.Extensions.Logging; +using static Managing.Common.Enums; namespace Managing.Application.Bots { @@ -11,7 +11,7 @@ namespace Managing.Application.Bots public ScalpingBot(string accountName, MoneyManagement moneyManagement, string name, - string scenario, + string scenarioName, IExchangeService exchangeService, Ticker ticker, ITradingService tradingService, @@ -23,19 +23,19 @@ namespace Managing.Application.Bots bool isForBacktest = false, bool isForWatchingOnly = false) : base(accountName, - moneyManagement, - name, - ticker, - scenario, - exchangeService, - logger, - tradingService, - timeframe, - accountService, - messengerService, - botService, - isForBacktest, - isForWatchingOnly) + moneyManagement, + name, + ticker, + scenarioName, + exchangeService, + logger, + tradingService, + timeframe, + accountService, + messengerService, + botService, + isForBacktest, + isForWatchingOnly) { BotType = BotType.ScalpingBot; } @@ -47,4 +47,4 @@ namespace Managing.Application.Bots Logger.LogInformation($"Starting {Name} bot - Status : {Status}"); } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 3b38fc3..fbb02af 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -33,7 +33,7 @@ public class TradingBot : Bot, ITradingBot public HashSet Signals { get; set; } public List Positions { get; set; } public Ticker Ticker { get; set; } - public string Scenario { get; set; } + public string ScenarioName { get; set; } public string AccountName { get; set; } public MoneyManagement MoneyManagement { get; set; } public Timeframe Timeframe { get; set; } @@ -44,6 +44,7 @@ public class TradingBot : Bot, ITradingBot public int PreloadedCandlesCount { get; set; } public BotType BotType { get; set; } public decimal Fee { get; set; } + public Scenario Scenario { get; set; } public Dictionary WalletBalances { get; set; } public TradingBot( @@ -51,7 +52,7 @@ public class TradingBot : Bot, ITradingBot MoneyManagement moneyManagement, string name, Ticker ticker, - string scenario, + string scenarioName, IExchangeService exchangeService, ILogger logger, ITradingService tradingService, @@ -75,7 +76,7 @@ public class TradingBot : Bot, ITradingBot AccountName = accountName; MoneyManagement = moneyManagement; Ticker = ticker; - Scenario = scenario; + ScenarioName = scenarioName; Timeframe = timeframe; IsForBacktest = isForBacktest; Logger = logger; @@ -101,7 +102,7 @@ public class TradingBot : Bot, ITradingBot if (!IsForBacktest) { - LoadScenario(); + LoadScenario(ScenarioName); await PreloadCandles(); await CancelAllOrders(); @@ -135,9 +136,9 @@ public class TradingBot : Bot, ITradingBot } } - public void LoadScenario() + public void LoadScenario(string scenarioName) { - var scenario = TradingService.GetScenarioByName(Scenario); + var scenario = TradingService.GetScenarioByName(scenarioName); if (scenario == null) { Logger.LogWarning("No scenario found for this scenario name"); @@ -145,6 +146,7 @@ public class TradingBot : Bot, ITradingBot } else { + Scenario = scenario; LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario)); } } @@ -159,22 +161,25 @@ public class TradingBot : Bot, ITradingBot public async Task Run() { - Logger.LogInformation($"____________________{Name}____________________"); - Logger.LogInformation( - $"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}"); + if (!IsForBacktest) + { + Logger.LogInformation($"____________________{Name}____________________"); + Logger.LogInformation( + $"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}"); + } var previousLastCandle = OptimizedCandles.LastOrDefault(); - + if (!IsForBacktest) await UpdateCandles(); - + var currentLastCandle = OptimizedCandles.LastOrDefault(); - + if (currentLastCandle != previousLastCandle || IsForBacktest) await UpdateSignals(OptimizedCandles); else Logger.LogInformation($"No need to update signals for {Ticker}"); - + if (!IsForWatchingOnly) await ManagePositions(); @@ -213,7 +218,7 @@ public class TradingBot : Bot, ITradingBot private async Task UpdateSignals(FixedSizeQueue candles) { - var signal = TradingBox.GetSignal(candles.ToHashSet(), Strategies, Signals); + var signal = TradingBox.GetSignal(candles.ToHashSet(), Strategies, Signals, Scenario.LoopbackPeriod); if (signal == null) return; @@ -231,7 +236,7 @@ public class TradingBot : Bot, ITradingBot if (IsForWatchingOnly || (ExecutionCount < 1 && !IsForBacktest)) signal.Status = SignalStatus.Expired; - var signalText = $"{Scenario} trigger a signal. Signal told you " + + var signalText = $"{ScenarioName} trigger a signal. Signal told you " + $"to {signal.Direction} {Ticker} on {Timeframe}. The confidence in this signal is {signal.Confidence}. Identifier : {signal.Identifier}"; Logger.LogInformation(signalText); @@ -726,7 +731,7 @@ public class TradingBot : Bot, ITradingBot Positions = Positions, Timeframe = Timeframe, Ticker = Ticker, - Scenario = Scenario, + ScenarioName = ScenarioName, AccountName = AccountName, IsForWatchingOnly = IsForWatchingOnly, WalletBalances = WalletBalances, @@ -744,7 +749,7 @@ public class TradingBot : Bot, ITradingBot MoneyManagement = data.MoneyManagement; Timeframe = data.Timeframe; Ticker = data.Ticker; - Scenario = data.Scenario; + ScenarioName = data.ScenarioName; AccountName = data.AccountName; IsForWatchingOnly = data.IsForWatchingOnly; } @@ -758,7 +763,7 @@ public class TradingBotBackup public List Positions { get; set; } public Timeframe Timeframe { get; set; } public Ticker Ticker { get; set; } - public string Scenario { get; set; } + public string ScenarioName { get; set; } public string AccountName { get; set; } public bool IsForWatchingOnly { get; set; } public Dictionary WalletBalances { get; set; } diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 8920637..bd266eb 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -128,7 +128,7 @@ namespace Managing.Application.ManageBot scalpingBotData.MoneyManagement, backupBot.Name, scalpingBotData.Ticker, - scalpingBotData.Scenario, + scalpingBotData.ScenarioName, scalpingBotData.Timeframe, scalpingBotData.IsForWatchingOnly); botTask = Task.Run(() => ((ITradingBot)bot).Start()); @@ -140,7 +140,7 @@ namespace Managing.Application.ManageBot flippingBotData.MoneyManagement, backupBot.Name, flippingBotData.Ticker, - flippingBotData.Scenario, + flippingBotData.ScenarioName, flippingBotData.Timeframe, flippingBotData.IsForWatchingOnly); botTask = Task.Run(() => ((ITradingBot)bot).Start()); diff --git a/src/Managing.Application/Scenarios/ScenarioService.cs b/src/Managing.Application/Scenarios/ScenarioService.cs index a00ed09..cd82b9d 100644 --- a/src/Managing.Application/Scenarios/ScenarioService.cs +++ b/src/Managing.Application/Scenarios/ScenarioService.cs @@ -19,9 +19,9 @@ namespace Managing.Application.Scenarios _tradingService = tradingService; } - public Scenario CreateScenario(string name, List strategies) + public Scenario CreateScenario(string name, List strategies, int? loopbackPeriod = 1) { - var scenario = new Scenario(name); + var scenario = new Scenario(name, loopbackPeriod); foreach (var strategy in strategies) { @@ -43,20 +43,18 @@ namespace Managing.Application.Scenarios public Strategy CreateStrategy( StrategyType type, - Timeframe timeframe, - string name, + string name, int? period = null, int? fastPeriods = null, int? slowPeriods = null, int? signalPeriods = null, double? multiplier = null, int? stochPeriods = null, - int? smoothPeriods = null, + int? smoothPeriods = null, int? cyclePeriods = null) { var strategy = ScenarioHelpers.BuildStrategy( type, - timeframe, name, period, fastPeriods, @@ -141,4 +139,4 @@ namespace Managing.Application.Scenarios return true; } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Shared/SettingsService.cs b/src/Managing.Application/Shared/SettingsService.cs index eb79147..9edc0ce 100644 --- a/src/Managing.Application/Shared/SettingsService.cs +++ b/src/Managing.Application/Shared/SettingsService.cs @@ -62,7 +62,7 @@ public class SettingsService : ISettingsService SetupMoneyManagementsSeed(Timeframe.FifteenMinutes); SetupMoneyManagementsSeed(Timeframe.OneHour); SetupMoneyManagementsSeed(Timeframe.OneDay); - SetupScenariosSeed(Timeframe.FifteenMinutes); + SetupScenariosSeed(); } catch (Exception ex) { @@ -82,30 +82,29 @@ public class SettingsService : ISettingsService Leverage = 1, StopLoss = 0.021m, TakeProfit = 0.042m, - Name = $"{timeframe} Money Management" + Name = $"{timeframe}-MediumRisk", }; await _moneyManagementService.CreateOrUpdateMoneyManagement(moneyManagement); } - private void SetupScenariosSeed(Timeframe timeframe) + private void SetupScenariosSeed() { - SetupMacd(timeframe); - SetupRsiDiv(timeframe); - SetupRsiDivConfirm(timeframe); - SetupSuperTrend(timeframe); - SetupChandelierExit(timeframe); - SetupStochRsiTrend(timeframe); - SetupStochSTCTrend(timeframe); - SetupEmaTrend(timeframe); - SetupEmaCross(timeframe); + SetupMacd(); + SetupRsiDiv(); + SetupRsiDivConfirm(); + SetupSuperTrend(); + SetupChandelierExit(); + SetupStochRsiTrend(); + SetupStochSTCTrend(); + SetupEmaTrend(); + SetupEmaCross(); } - private void SetupStochSTCTrend(Timeframe timeframe) + private void SetupStochSTCTrend() { var name = "STCTrend"; var strategy = _scenarioService.CreateStrategy(StrategyType.Stc, - timeframe, name, fastPeriods: 23, slowPeriods: 50, @@ -113,11 +112,10 @@ public class SettingsService : ISettingsService _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupMacd(Timeframe timeframe) + private void SetupMacd() { var name = "MacdCross"; var strategy = _scenarioService.CreateStrategy(StrategyType.MacdCross, - timeframe, name, fastPeriods: 12, slowPeriods: 26, @@ -125,53 +123,48 @@ public class SettingsService : ISettingsService _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupRsiDiv(Timeframe timeframe) + private void SetupRsiDiv() { var name = "RsiDiv6"; var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergence, - timeframe, name, period: 6); _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupRsiDivConfirm(Timeframe timeframe) + private void SetupRsiDivConfirm() { var name = "RsiDivConfirm6"; var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergenceConfirm, - timeframe, name, period: 6); _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupSuperTrend(Timeframe timeframe) + private void SetupSuperTrend() { var name = "SuperTrend"; var strategy = _scenarioService.CreateStrategy(StrategyType.SuperTrend, - timeframe, name, period: 10, multiplier: 3); _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupChandelierExit(Timeframe timeframe) + private void SetupChandelierExit() { var name = "ChandelierExit"; var strategy = _scenarioService.CreateStrategy(StrategyType.ChandelierExit, - timeframe, name, period: 22, multiplier: 3); _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupStochRsiTrend(Timeframe timeframe) + private void SetupStochRsiTrend() { var name = "StochRsiTrend"; var strategy = _scenarioService.CreateStrategy(StrategyType.StochRsiTrend, - timeframe, name, period: 14, stochPeriods: 14, @@ -180,21 +173,19 @@ public class SettingsService : ISettingsService _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupEmaTrend(Timeframe timeframe) + private void SetupEmaTrend() { var name = "Ema200Trend"; var strategy = _scenarioService.CreateStrategy(StrategyType.EmaTrend, - timeframe, name, period: 200); _scenarioService.CreateScenario(name, new List { strategy.Name }); } - private void SetupEmaCross(Timeframe timeframe) + private void SetupEmaCross() { var name = "Ema200Cross"; var strategy = _scenarioService.CreateStrategy(StrategyType.EmaCross, - timeframe, name, period: 200); _scenarioService.CreateScenario(name, new List { strategy.Name }); diff --git a/src/Managing.Application/Workflows/Flows/Strategies/RsiDiv.cs b/src/Managing.Application/Workflows/Flows/Strategies/RsiDiv.cs index c15b251..7925eaf 100644 --- a/src/Managing.Application/Workflows/Flows/Strategies/RsiDiv.cs +++ b/src/Managing.Application/Workflows/Flows/Strategies/RsiDiv.cs @@ -30,7 +30,7 @@ public class RsiDiv : FlowBase MapParameters(); var candles = JsonConvert.DeserializeObject>(input); - var strategy = new RSIDivergenceStrategy(Name, RsiDivParameters.Timeframe, RsiDivParameters.Period); + var strategy = new RSIDivergenceStrategy(Name, RsiDivParameters.Period); strategy.UpdateCandles(candles); strategy.Run(); diff --git a/src/Managing.Domain/Scenarios/Scenario.cs b/src/Managing.Domain/Scenarios/Scenario.cs index bd9cfee..9f795db 100644 --- a/src/Managing.Domain/Scenarios/Scenario.cs +++ b/src/Managing.Domain/Scenarios/Scenario.cs @@ -4,17 +4,20 @@ namespace Managing.Domain.Scenarios { public class Scenario { - public Scenario(string name) + public Scenario(string name, int? loopbackPeriod = 1) { Name = name; Strategies = new List(); + LoopbackPeriod = loopbackPeriod; } public string Name { get; set; } public List Strategies { get; set; } + public int? LoopbackPeriod { get; set; } + public void AddStrategy(Strategy strategy) { Strategies.Add(strategy); } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Scenarios/ScenarioHelpers.cs b/src/Managing.Domain/Scenarios/ScenarioHelpers.cs index a5a98c5..d590050 100644 --- a/src/Managing.Domain/Scenarios/ScenarioHelpers.cs +++ b/src/Managing.Domain/Scenarios/ScenarioHelpers.cs @@ -14,25 +14,25 @@ public static class ScenarioHelpers { IStrategy result = strategy.Type switch { - StrategyType.StDev => new StDevContext(strategy.Name, strategy.Timeframe, strategy.Period.Value), - StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name, strategy.Timeframe, + StrategyType.StDev => new StDevContext(strategy.Name, strategy.Period.Value), + StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name, strategy.Period.Value), - StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe, + StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Period.Value), - StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, strategy.Timeframe, + StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value), - StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value), - StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe, + StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Period.Value), + StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Period.Value), - StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name, strategy.Timeframe, + StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name, strategy.Period.Value, strategy.Multiplier.Value), - StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, strategy.Timeframe, + StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, strategy.Period.Value, strategy.Multiplier.Value), - StrategyType.EmaTrend => new EmaTrendStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value), - StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name, strategy.Timeframe, + StrategyType.EmaTrend => new EmaTrendStrategy(strategy.Name, strategy.Period.Value), + StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name, strategy.Period.Value, strategy.StochPeriods.Value, strategy.SignalPeriods.Value, strategy.SmoothPeriods.Value), - StrategyType.Stc => new STCStrategy(strategy.Name, strategy.Timeframe, strategy.CyclePeriods.Value, + StrategyType.Stc => new STCStrategy(strategy.Name, strategy.CyclePeriods.Value, strategy.FastPeriods.Value, strategy.SlowPeriods.Value), _ => throw new NotImplementedException(), }; @@ -46,7 +46,6 @@ public static class ScenarioHelpers public static Strategy BuildStrategy( StrategyType type, - Timeframe timeframe, string name, int? period = null, int? fastPeriods = null, @@ -57,7 +56,7 @@ public static class ScenarioHelpers int? smoothPeriods = null, int? cyclePeriods = null) { - var strategy = new Strategy(name, timeframe, type); + var strategy = new Strategy(name, type); switch (type) { diff --git a/src/Managing.Domain/Shared/Helpers/TradingBox.cs b/src/Managing.Domain/Shared/Helpers/TradingBox.cs index b405bf1..8a5011d 100644 --- a/src/Managing.Domain/Shared/Helpers/TradingBox.cs +++ b/src/Managing.Domain/Shared/Helpers/TradingBox.cs @@ -10,7 +10,7 @@ namespace Managing.Domain.Shared.Helpers; public static class TradingBox { public static Signal GetSignal(HashSet newCandles, HashSet strategies, - HashSet previousSignal) + HashSet previousSignal, int? loopbackPeriod = 1) { var signalOnCandles = new HashSet(); var limitedCandles = newCandles.ToList().TakeLast(600).ToList(); @@ -21,7 +21,9 @@ public static class TradingBox if (signals == null || signals.Count == 0) continue; - foreach (var signal in signals.Where(s => s.Date == newCandles.Last().Date)) + var candleLoopback = limitedCandles.TakeLast(loopbackPeriod ?? 1).ToList(); + + foreach (var signal in signals.Where(s => s.Date >= candleLoopback.FirstOrDefault()?.Date)) { if (previousSignal.SingleOrDefault(s => s.Identifier == signal.Identifier) == null) { @@ -68,7 +70,6 @@ public static class TradingBox signals.Last().Candle, signals.Last().Date, signals.Last().Exchange, - timeframe, StrategyType.Composite, SignalType.Signal); } else if (signals.All(s => s.Direction == TradeDirection.Short) && @@ -81,7 +82,6 @@ public static class TradingBox signals.Last().Candle, signals.Last().Date, signals.Last().Exchange, - timeframe, StrategyType.Composite, SignalType.Signal); } } diff --git a/src/Managing.Domain/Strategies/Base/EmaBaseStrategy.cs b/src/Managing.Domain/Strategies/Base/EmaBaseStrategy.cs index 609472d..25fae6f 100644 --- a/src/Managing.Domain/Strategies/Base/EmaBaseStrategy.cs +++ b/src/Managing.Domain/Strategies/Base/EmaBaseStrategy.cs @@ -6,7 +6,7 @@ namespace Managing.Domain.Strategies.Base; public abstract class EmaBaseStrategy : Strategy { - protected EmaBaseStrategy(string name, Enums.Timeframe timeframe, Enums.StrategyType type) : base(name, timeframe, type) + protected EmaBaseStrategy(string name, Enums.StrategyType type) : base(name, type) { } @@ -29,6 +29,7 @@ public abstract class EmaBaseStrategy : Strategy }); } } + return emaList; } @@ -36,4 +37,4 @@ public abstract class EmaBaseStrategy : Strategy { public double Ema { get; set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs b/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs index 822e411..888f5c0 100644 --- a/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs +++ b/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs @@ -9,7 +9,8 @@ namespace Managing.Domain.Strategies; public class ChandelierExitStrategy : Strategy { public List Signals { get; set; } - public ChandelierExitStrategy(string name, Timeframe timeframe, int period, double multiplier) : base(name, timeframe, StrategyType.ChandelierExit) + + public ChandelierExitStrategy(string name, int period, double multiplier) : base(name, StrategyType.ChandelierExit) { Signals = new List(); Period = period; @@ -39,28 +40,29 @@ public class ChandelierExitStrategy : Strategy private void GetSignals(ChandelierType chandelierType) { - var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType).Where(s => s.ChandelierExit.HasValue).ToList(); + var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType) + .Where(s => s.ChandelierExit.HasValue).ToList(); var chandelierCandle = MapChandelierToCandle(chandelier, Candles.TakeLast(MinimumHistory)); var previousCandle = chandelierCandle[0]; foreach (var currentCandle in chandelierCandle.Skip(1)) { // Short - if (currentCandle.Close < previousCandle.ChandelierExit && + if (currentCandle.Close < previousCandle.ChandelierExit && previousCandle.Close > previousCandle.ChandelierExit && currentCandle.Close < previousCandle.Open && chandelierType == ChandelierType.Short) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } // Long - if (currentCandle.Close > previousCandle.ChandelierExit && + if (currentCandle.Close > previousCandle.ChandelierExit && previousCandle.Close < previousCandle.ChandelierExit && currentCandle.Close > currentCandle.Open && chandelierType == ChandelierType.Long) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; @@ -90,7 +92,8 @@ public class ChandelierExitStrategy : Strategy return superTrends; } - private void AddSignal(CandleChandelier candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleChandelier candleSignal, TradeDirection direction, + Confidence confidence) { var signal = new Signal( MiscExtensions.ParseEnum(candleSignal.Ticker), @@ -99,7 +102,6 @@ public class ChandelierExitStrategy : Strategy candleSignal, candleSignal.Date, candleSignal.Exchange, - timeframe, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { @@ -112,4 +114,4 @@ public class ChandelierExitStrategy : Strategy { public decimal ChandelierExit { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/EmaCrossStrategy.cs b/src/Managing.Domain/Strategies/EmaCrossStrategy.cs index 4338689..62bde01 100644 --- a/src/Managing.Domain/Strategies/EmaCrossStrategy.cs +++ b/src/Managing.Domain/Strategies/EmaCrossStrategy.cs @@ -10,7 +10,7 @@ public class EmaCrossStrategy : EmaBaseStrategy { public List Signals { get; set; } - public EmaCrossStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.EmaCross) + public EmaCrossStrategy(string name, int period) : base(name, StrategyType.EmaCross) { Signals = new List(); Period = period; @@ -37,13 +37,13 @@ public class EmaCrossStrategy : EmaBaseStrategy if (previousCandle.Close > (decimal)currentCandle.Ema && currentCandle.Close < (decimal)currentCandle.Ema) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } if (previousCandle.Close < (decimal)currentCandle.Ema && currentCandle.Close > (decimal)currentCandle.Ema) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; @@ -57,10 +57,10 @@ public class EmaCrossStrategy : EmaBaseStrategy } } - private void AddSignal(CandleEma candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, - candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); + candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); diff --git a/src/Managing.Domain/Strategies/EmaTrendStrategy.cs b/src/Managing.Domain/Strategies/EmaTrendStrategy.cs index c9e6052..b52a4e2 100644 --- a/src/Managing.Domain/Strategies/EmaTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/EmaTrendStrategy.cs @@ -10,7 +10,7 @@ public class EmaTrendStrategy : EmaBaseStrategy { public List Signals { get; set; } - public EmaTrendStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.EmaTrend) + public EmaTrendStrategy(string name, int period) : base(name, StrategyType.EmaTrend) { Signals = new List(); Period = period; @@ -36,11 +36,11 @@ public class EmaTrendStrategy : EmaBaseStrategy { if (currentCandle.Close > (decimal)currentCandle.Ema) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None); + AddSignal(currentCandle, TradeDirection.Long, Confidence.None); } else { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None); + AddSignal(currentCandle, TradeDirection.Short, Confidence.None); } previousCandle = currentCandle; @@ -54,12 +54,13 @@ public class EmaTrendStrategy : EmaBaseStrategy } } - public void AddSignal(CandleEma candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + public void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence) { - var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); + var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, + candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/MACDCrossStrategy.cs b/src/Managing.Domain/Strategies/MACDCrossStrategy.cs index 25ac6f1..00c32b9 100644 --- a/src/Managing.Domain/Strategies/MACDCrossStrategy.cs +++ b/src/Managing.Domain/Strategies/MACDCrossStrategy.cs @@ -10,8 +10,8 @@ public class MacdCrossStrategy : Strategy { public List Signals { get; set; } - public MacdCrossStrategy(string name, Timeframe timeframe, int fastPeriods, int slowPeriods, int signalPeriods) : - base(name, timeframe, StrategyType.MacdCross) + public MacdCrossStrategy(string name, int fastPeriods, int slowPeriods, int signalPeriods) : + base(name, StrategyType.MacdCross) { Signals = new List(); FastPeriods = fastPeriods; @@ -39,12 +39,12 @@ public class MacdCrossStrategy : Strategy { if (previousCandle.Histogram > 0 && currentCandle.Histogram < 0 && currentCandle.Macd < 0) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } if (previousCandle.Histogram < 0 && currentCandle.Histogram > 0 && currentCandle.Macd > 0) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; @@ -82,11 +82,11 @@ public class MacdCrossStrategy : Strategy return macdList; } - private void AddSignal(CandleMacd candleSignal, Timeframe timeframe, TradeDirection direction, + private void AddSignal(CandleMacd candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, - candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); + candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); diff --git a/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs b/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs index 523abb8..48939d3 100644 --- a/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs +++ b/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs @@ -10,7 +10,7 @@ public class RSIDivergenceConfirmStrategy : Strategy { public List Signals { get; set; } - public RSIDivergenceConfirmStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.RsiDivergenceConfirm) + public RSIDivergenceConfirmStrategy(string name, int period) : base(name, StrategyType.RsiDivergenceConfirm) { Period = period; Signals = new List(); @@ -88,7 +88,7 @@ public class RSIDivergenceConfirmStrategy : Strategy // Price go down but RSI go up if (currentCandle.Close < lowPrices.TakeLast(Period.Value).Min(p => p.Close)) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None); + AddSignal(currentCandle, TradeDirection.Long, Confidence.None); } } else @@ -163,7 +163,7 @@ public class RSIDivergenceConfirmStrategy : Strategy // Price go up but RSI go down if (currentCandle.Close > highPrices.TakeLast(Period.Value).Max(p => p.Close)) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None); + AddSignal(currentCandle, TradeDirection.Short, Confidence.None); } } else @@ -199,31 +199,32 @@ public class RSIDivergenceConfirmStrategy : Strategy { var lastCandleOnPeriod = Candles.TakeLast(Period.Value).ToList(); var signalsOnPeriod = Signals.Where(s => s.Date >= lastCandleOnPeriod[0].Date - && s.Date < currentCandle.Date - && s.Direction == direction - && s.Confidence == Confidence.None - && s.Status != SignalStatus.Expired - && s.Status != SignalStatus.PositionOpen).ToList(); + && s.Date < currentCandle.Date + && s.Direction == direction + && s.Confidence == Confidence.None + && s.Status != SignalStatus.Expired + && s.Status != SignalStatus.PositionOpen).ToList(); foreach (var signal in signalsOnPeriod) { if (direction == TradeDirection.Short && currentCandle.Close < signal.Candle.Open) { - AddSignal(currentCandle, Timeframe, direction, Confidence.High); + AddSignal(currentCandle, direction, Confidence.High); Signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.Expired; } if (direction == TradeDirection.Long && currentCandle.Close > signal.Candle.Open) { - AddSignal(currentCandle, Timeframe, direction, Confidence.High); + AddSignal(currentCandle, direction, Confidence.High); Signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.Expired; } } } - private void AddSignal(CandleRsi candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleRsi candleSignal, TradeDirection direction, Confidence confidence) { - var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); + var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, + candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); @@ -233,7 +234,6 @@ public class RSIDivergenceConfirmStrategy : Strategy private List MapRsiToCandle(IReadOnlyCollection rsiResult, IEnumerable candles) { - return candles.Select(c => new CandleRsi() { Close = c.Close, @@ -249,4 +249,4 @@ public class RSIDivergenceConfirmStrategy : Strategy { public double Rsi { get; set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs b/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs index 4644d1b..dc9bb2a 100644 --- a/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs +++ b/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs @@ -13,7 +13,7 @@ public class RSIDivergenceStrategy : Strategy private const int UpperBand = 70; private const int LowerBand = 30; - public RSIDivergenceStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.RsiDivergence) + public RSIDivergenceStrategy(string name, int period) : base(name, StrategyType.RsiDivergence) { Period = period; Signals = new List(); @@ -91,7 +91,7 @@ public class RSIDivergenceStrategy : Strategy // Price go down but RSI go up if (currentCandle.Close < lowPrices.TakeLast(Period.Value).Min(p => p.Close)) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long); + AddSignal(currentCandle, TradeDirection.Long); } } else @@ -164,7 +164,7 @@ public class RSIDivergenceStrategy : Strategy // Price go up but RSI go down if (currentCandle.Close > highPrices.TakeLast(Period.Value).Max(p => p.Close)) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short); + AddSignal(currentCandle, TradeDirection.Short); } } else @@ -194,9 +194,10 @@ public class RSIDivergenceStrategy : Strategy } } - private void AddSignal(CandleRsi candleSignal, Timeframe timeframe, TradeDirection direction) + private void AddSignal(CandleRsi candleSignal, TradeDirection direction) { - var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, Confidence.Low, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); + var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, Confidence.Low, + candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType); if (Signals.Count(s => s.Identifier == signal.Identifier) < 1) { @@ -216,7 +217,6 @@ public class RSIDivergenceStrategy : Strategy private List MapRsiToCandle(IReadOnlyCollection rsiResult, IEnumerable candles) { - return candles.Select(c => new CandleRsi() { Close = c.Close, @@ -231,4 +231,4 @@ public class RSIDivergenceStrategy : Strategy { public double Rsi { get; set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/STCStrategy.cs b/src/Managing.Domain/Strategies/STCStrategy.cs index 348e6a6..59d69be 100644 --- a/src/Managing.Domain/Strategies/STCStrategy.cs +++ b/src/Managing.Domain/Strategies/STCStrategy.cs @@ -10,7 +10,7 @@ public class STCStrategy : Strategy { public List Signals { get; set; } - public STCStrategy(string name, Timeframe timeframe, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, timeframe, StrategyType.Stc) + public STCStrategy(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, StrategyType.Stc) { Signals = new List(); FastPeriods = fastPeriods; @@ -38,12 +38,12 @@ public class STCStrategy : Strategy { if (previousCandle.Stc > 75 && currentCandle.Stc <= 75) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } if (previousCandle.Stc < 25 && currentCandle.Stc >= 25) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; @@ -76,10 +76,11 @@ public class STCStrategy : Strategy }); } } + return sctList; } - private void AddSignal(CandleSct candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleSct candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal( MiscExtensions.ParseEnum(candleSignal.Ticker), @@ -88,7 +89,6 @@ public class STCStrategy : Strategy candleSignal, candleSignal.Date, candleSignal.Exchange, - timeframe, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { @@ -100,4 +100,4 @@ public class STCStrategy : Strategy { public double? Stc { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/Signal.cs b/src/Managing.Domain/Strategies/Signal.cs index 8414cb9..61f57b2 100644 --- a/src/Managing.Domain/Strategies/Signal.cs +++ b/src/Managing.Domain/Strategies/Signal.cs @@ -1,37 +1,26 @@ -using Managing.Core; +using System.ComponentModel.DataAnnotations; +using Managing.Core; using Managing.Domain.Candles; -using System.ComponentModel.DataAnnotations; using static Managing.Common.Enums; namespace Managing.Domain.Strategies { public class Signal : ValueObject { - [Required] - public SignalStatus Status { get; set; } - [Required] - public TradeDirection Direction { get; } - [Required] - public Confidence Confidence { get; private set; } - [Required] - public Timeframe Timeframe { get; } - [Required] - public DateTime Date { get; private set; } - [Required] - public Candle Candle { get; } - [Required] - public string Identifier { get; } - [Required] - public Ticker Ticker { get; } - [Required] - public TradingExchanges Exchange { get; set; } - [Required] - public StrategyType StrategyType { get; set; } - [Required] - public SignalType SignalType { get; set; } + [Required] public SignalStatus Status { get; set; } + [Required] public TradeDirection Direction { get; } + [Required] public Confidence Confidence { get; private set; } + [Required] public Timeframe Timeframe { get; } + [Required] public DateTime Date { get; private set; } + [Required] public Candle Candle { get; } + [Required] public string Identifier { get; } + [Required] public Ticker Ticker { get; } + [Required] public TradingExchanges Exchange { get; set; } + [Required] public StrategyType StrategyType { get; set; } + [Required] public SignalType SignalType { get; set; } public Signal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date, - TradingExchanges exchange, Timeframe timeframe, StrategyType strategyType, SignalType signalType) + TradingExchanges exchange, StrategyType strategyType, SignalType signalType) { Direction = direction; Confidence = confidence; @@ -40,10 +29,9 @@ namespace Managing.Domain.Strategies Ticker = ticker; Exchange = exchange; Status = SignalStatus.WaitingForPosition; - Timeframe = timeframe; StrategyType = strategyType; - Identifier = $"{StrategyType}-{direction}-{ticker}-{Timeframe}-{candle?.Close}-{date:yyyyMMdd-HHmmss}"; + Identifier = $"{StrategyType}-{direction}-{ticker}-{candle?.Close}-{date:yyyyMMdd-HHmmss}"; SignalType = signalType; } @@ -59,4 +47,4 @@ namespace Managing.Domain.Strategies yield return Date; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/StDevContext.cs b/src/Managing.Domain/Strategies/StDevContext.cs index 6ea8af7..7577b13 100644 --- a/src/Managing.Domain/Strategies/StDevContext.cs +++ b/src/Managing.Domain/Strategies/StDevContext.cs @@ -10,7 +10,7 @@ public class StDevContext : Strategy { public List Signals { get; set; } - public StDevContext(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.StDev) + public StDevContext(string name, int period) : base(name, StrategyType.StDev) { Signals = new List(); Period = period; @@ -35,7 +35,7 @@ public class StDevContext : Strategy if (lastCandle.ZScore is < 1.2 and > (-1.2)) { - AddSignal(lastCandle, Timeframe, TradeDirection.None, Confidence.Medium); + AddSignal(lastCandle, TradeDirection.None, Confidence.Medium); } else { @@ -72,10 +72,12 @@ public class StDevContext : Strategy }); } } + return sctList; } - private void AddSignal(CandleStDev candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleStDev candleSignal, TradeDirection direction, + Confidence confidence) { var signal = new Signal( MiscExtensions.ParseEnum(candleSignal.Ticker), @@ -84,7 +86,6 @@ public class StDevContext : Strategy candleSignal, candleSignal.Date, candleSignal.Exchange, - timeframe, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { @@ -99,4 +100,4 @@ public class StDevContext : Strategy public double? StdDevSma { get; internal set; } public double? Mean { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs b/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs index bc591fe..10da0db 100644 --- a/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs @@ -12,11 +12,10 @@ public class StochRsiTrendStrategy : Strategy public StochRsiTrendStrategy( string name, - Timeframe timeframe, int period, int stochPeriod, int signalPeriod, - int smoothPeriods) : base(name, timeframe, StrategyType.StochRsiTrend) + int smoothPeriods) : base(name, StrategyType.StochRsiTrend) { Signals = new List(); StochPeriods = stochPeriod; @@ -34,7 +33,9 @@ public class StochRsiTrendStrategy : Strategy try { - var stochRsi = Candles.GetStochRsi(Period.Value, StochPeriods.Value, SignalPeriods.Value, SmoothPeriods.Value).RemoveWarmupPeriods().ToList(); + var stochRsi = Candles + .GetStochRsi(Period.Value, StochPeriods.Value, SignalPeriods.Value, SmoothPeriods.Value) + .RemoveWarmupPeriods().ToList(); var stochRsiCandles = MapStochRsiToCandle(stochRsi, Candles.TakeLast(Period.Value)); if (stochRsi.Count == 0) @@ -45,11 +46,11 @@ public class StochRsiTrendStrategy : Strategy { if (currentCandle.Signal < 20) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None); + AddSignal(currentCandle, TradeDirection.Long, Confidence.None); } else if (currentCandle.Signal > 80) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None); + AddSignal(currentCandle, TradeDirection.Short, Confidence.None); } previousCandle = currentCandle; @@ -83,10 +84,11 @@ public class StochRsiTrendStrategy : Strategy }); } } + return emaList; } - private void AddSignal(CandleStochRsi candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleStochRsi candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal( MiscExtensions.ParseEnum(candleSignal.Ticker), @@ -95,7 +97,6 @@ public class StochRsiTrendStrategy : Strategy candleSignal, candleSignal.Date, candleSignal.Exchange, - timeframe, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) @@ -109,4 +110,4 @@ public class StochRsiTrendStrategy : Strategy public double Signal { get; internal set; } public double StochRsi { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/Strategy.cs b/src/Managing.Domain/Strategies/Strategy.cs index 49952ec..f8a46db 100644 --- a/src/Managing.Domain/Strategies/Strategy.cs +++ b/src/Managing.Domain/Strategies/Strategy.cs @@ -8,16 +8,14 @@ namespace Managing.Domain.Strategies { public class Strategy : IStrategy { - public Strategy(string name, Timeframe timeframe, StrategyType type) + public Strategy(string name, StrategyType type) { Name = name; - Timeframe = timeframe; Type = type; SignalType = ScenarioHelpers.GetSignalType(type); } public string Name { get; set; } - public Timeframe Timeframe { get; set; } [JsonIgnore] public FixedSizeQueue Candles { get; set; } public StrategyType Type { get; set; } public SignalType SignalType { get; set; } diff --git a/src/Managing.Domain/Strategies/SuperTrendStrategy.cs b/src/Managing.Domain/Strategies/SuperTrendStrategy.cs index bab8f21..f2e2785 100644 --- a/src/Managing.Domain/Strategies/SuperTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/SuperTrendStrategy.cs @@ -10,7 +10,7 @@ public class SuperTrendStrategy : Strategy { public List Signals { get; set; } - public SuperTrendStrategy(string name, Timeframe timeframe, int period, double multiplier) : base(name, timeframe, StrategyType.SuperTrend) + public SuperTrendStrategy(string name, int period, double multiplier) : base(name, StrategyType.SuperTrend) { Signals = new List(); Period = period; @@ -27,7 +27,8 @@ public class SuperTrendStrategy : Strategy try { - var superTrend = Candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue).ToList(); + var superTrend = Candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue) + .ToList(); var superTrendCandle = MapSuperTrendToCandle(superTrend, Candles.TakeLast(MinimumHistory)); if (superTrendCandle.Count == 0) @@ -39,13 +40,13 @@ public class SuperTrendStrategy : Strategy // Short if (currentCandle.Close < previousCandle.SuperTrend && previousCandle.Close > previousCandle.SuperTrend) { - AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } // Long if (currentCandle.Close > previousCandle.SuperTrend && previousCandle.Close < previousCandle.SuperTrend) { - AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium); + AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; @@ -84,10 +85,11 @@ public class SuperTrendStrategy : Strategy return superTrends; } - private void AddSignal(CandleSuperTrend candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) + private void AddSignal(CandleSuperTrend candleSignal, TradeDirection direction, Confidence confidence) { - var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, - candleSignal.Exchange, timeframe, Type, SignalType); + var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, + candleSignal, candleSignal.Date, + candleSignal.Exchange, Type, SignalType); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); @@ -101,4 +103,4 @@ public class SuperTrendStrategy : Strategy public decimal? LowerBand { get; internal set; } public decimal? UpperBand { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs b/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs index f7f532a..24d4527 100644 --- a/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs +++ b/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs @@ -7,8 +7,8 @@ namespace Managing.Domain.Strategies { public class ThreeWhiteSoldiersStrategy : Strategy { - public ThreeWhiteSoldiersStrategy(string name, Timeframe timeframe, int period) - : base(name, timeframe, StrategyType.ThreeWhiteSoldiers) + public ThreeWhiteSoldiersStrategy(string name, int period) + : base(name, StrategyType.ThreeWhiteSoldiers) { Period = period; } diff --git a/src/Managing.Infrastructure.Database/MongoDb/Collections/ScenarioDto.cs b/src/Managing.Infrastructure.Database/MongoDb/Collections/ScenarioDto.cs index efafcd8..2593d2d 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/Collections/ScenarioDto.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/Collections/ScenarioDto.cs @@ -8,5 +8,6 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections { public string Name { get; set; } public List Strategies { get; set; } + public int LoopbackPeriod { get; set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index 865c3ff..91b5856 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -342,7 +342,7 @@ public static class MongoMappers internal static Signal Map(SignalDto bSignal) { return new Signal(ticker: bSignal.Ticker, direction: bSignal.Direction, confidence: bSignal.Confidence, - candle: Map(bSignal.Candle), date: bSignal.Date, exchange: default, timeframe: bSignal.Timeframe, + candle: Map(bSignal.Candle), date: bSignal.Date, exchange: default, strategyType: bSignal.Type, signalType: bSignal.SignalType) { Status = bSignal.Status @@ -359,6 +359,7 @@ public static class MongoMappers { Name = scenario.Name, Strategies = Map(scenario.Strategies), + LoopbackPeriod = scenario.LoopbackPeriod ?? 1 }; } @@ -372,7 +373,8 @@ public static class MongoMappers return new Scenario(d.Name) { Name = d.Name, - Strategies = Map(d.Strategies).ToList() + Strategies = Map(d.Strategies).ToList(), + LoopbackPeriod = d.LoopbackPeriod > 0 ? d.LoopbackPeriod : 1 }; } @@ -383,7 +385,7 @@ public static class MongoMappers internal static Strategy Map(StrategyDto strategyDto) { - return new Strategy(name: strategyDto.Name, timeframe: strategyDto.Timeframe, type: strategyDto.Type) + return new Strategy(name: strategyDto.Name, type: strategyDto.Type) { Period = strategyDto.Period, FastPeriods = strategyDto.FastPeriods, @@ -401,7 +403,6 @@ public static class MongoMappers var dto = new StrategyDto { Type = strategy.Type, - Timeframe = strategy.Timeframe, Name = strategy.Name, SignalType = strategy.SignalType }; diff --git a/src/Managing.Infrastructure.Database/TradingRepository.cs b/src/Managing.Infrastructure.Database/TradingRepository.cs index 71006b4..337f5ca 100644 --- a/src/Managing.Infrastructure.Database/TradingRepository.cs +++ b/src/Managing.Infrastructure.Database/TradingRepository.cs @@ -1,5 +1,4 @@ using Managing.Application.Abstractions.Repositories; -using Managing.Common; using Managing.Domain.Scenarios; using Managing.Domain.Strategies; using Managing.Domain.Trades; @@ -19,7 +18,6 @@ public class TradingRepository : ITradingRepository private readonly IMongoRepository _strategyRepository; private readonly IMongoRepository _feeRepository; - public TradingRepository( IMongoRepository scenarioRepository, IMongoRepository signalRepository, @@ -69,7 +67,7 @@ public class TradingRepository : ITradingRepository return positions.Select(MongoMappers.Map); } - public IEnumerable GetPositionsByStatus(Enums.PositionStatus positionStatus) + public IEnumerable GetPositionsByStatus(PositionStatus positionStatus) { var filter = Builders.Filter.Eq(p => p.Status, positionStatus); var positions = _positionRepository.FilterBy(filter); @@ -97,7 +95,7 @@ public class TradingRepository : ITradingRepository public Strategy GetStrategyByName(string name) { var strategy = _strategyRepository.FindOne(s => s.Name == name); - return MongoMappers.Map(strategy); + return MongoMappers.Map(strategy); } public void InsertPosition(Position position) @@ -147,4 +145,4 @@ public class TradingRepository : ITradingRepository dto.Id = f.Id; _feeRepository.Update(dto); } -} +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.MongoDb/Collections/StrategyDto.cs b/src/Managing.Infrastructure.MongoDb/Collections/StrategyDto.cs index f438eb0..3335df6 100644 --- a/src/Managing.Infrastructure.MongoDb/Collections/StrategyDto.cs +++ b/src/Managing.Infrastructure.MongoDb/Collections/StrategyDto.cs @@ -8,7 +8,6 @@ namespace Managing.Infrastructure.MongoDb.Collections public class StrategyDto : Document { public StrategyType Type { get; set; } - public Timeframe Timeframe { get; set; } public string Name { get; set; } public int? Period { get; set; } public int? FastPeriods { get; set; } diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts index 27e521c..634639c 100644 --- a/src/Managing.WebApp/src/generated/ManagingApi.ts +++ b/src/Managing.WebApp/src/generated/ManagingApi.ts @@ -1073,10 +1073,12 @@ export class ScenarioClient extends AuthorizedApiBase { return Promise.resolve(null as any); } - scenario_CreateScenario(name: string | null | undefined, strategies: string[]): Promise { + scenario_CreateScenario(name: string | null | undefined, loopbackPeriod: number | null | undefined, strategies: string[]): Promise { let url_ = this.baseUrl + "/Scenario?"; if (name !== undefined && name !== null) url_ += "name=" + encodeURIComponent("" + name) + "&"; + if (loopbackPeriod !== undefined && loopbackPeriod !== null) + url_ += "loopbackPeriod=" + encodeURIComponent("" + loopbackPeriod) + "&"; url_ = url_.replace(/[?&]$/, ""); const content_ = JSON.stringify(strategies); @@ -1191,16 +1193,12 @@ export class ScenarioClient extends AuthorizedApiBase { return Promise.resolve(null as any); } - scenario_CreateStrategy(strategyType: StrategyType | undefined, timeframe: Timeframe | undefined, name: string | null | undefined, period: number | null | undefined, fastPeriods: number | null | undefined, slowPeriods: number | null | undefined, signalPeriods: number | null | undefined, multiplier: number | null | undefined, stochPeriods: number | null | undefined, smoothPeriods: number | null | undefined, cyclePeriods: number | null | undefined): Promise { + scenario_CreateStrategy(strategyType: StrategyType | undefined, name: string | null | undefined, period: number | null | undefined, fastPeriods: number | null | undefined, slowPeriods: number | null | undefined, signalPeriods: number | null | undefined, multiplier: number | null | undefined, stochPeriods: number | null | undefined, smoothPeriods: number | null | undefined, cyclePeriods: number | null | undefined): Promise { let url_ = this.baseUrl + "/Scenario/strategy?"; if (strategyType === null) throw new Error("The parameter 'strategyType' cannot be null."); else if (strategyType !== undefined) url_ += "strategyType=" + encodeURIComponent("" + strategyType) + "&"; - if (timeframe === null) - throw new Error("The parameter 'timeframe' cannot be null."); - else if (timeframe !== undefined) - url_ += "timeframe=" + encodeURIComponent("" + timeframe) + "&"; if (name !== undefined && name !== null) url_ += "name=" + encodeURIComponent("" + name) + "&"; if (period !== undefined && period !== null) @@ -1583,7 +1581,7 @@ export class TradingClient extends AuthorizedApiBase { let options_: RequestInit = { body: content_, - method: "GET", + method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" @@ -2206,11 +2204,11 @@ export interface Spotlight { export interface Scenario { name?: string | null; strategies?: Strategy[] | null; + loopbackPeriod?: number | null; } export interface Strategy { name?: string | null; - timeframe?: Timeframe; type?: StrategyType; signalType?: SignalType; minimumHistory?: number; diff --git a/src/Managing.WebApp/src/global/type.tsx b/src/Managing.WebApp/src/global/type.tsx index fb60a7e..f63569d 100644 --- a/src/Managing.WebApp/src/global/type.tsx +++ b/src/Managing.WebApp/src/global/type.tsx @@ -1,13 +1,30 @@ -import type { - TableInstance, - UsePaginationInstanceProps, - UsePaginationState, - UseSortByInstanceProps, -} from 'react-table' -import type { Edge, Node } from 'reactflow' +import type {TableInstance, UsePaginationInstanceProps, UsePaginationState, UseSortByInstanceProps,} from 'react-table' +import type {Edge, Node} from 'reactflow' + +import type { + Account, + AccountType, + Backtest, + Balance, + BotType, + Candle, + FlowOutput, + FlowType, + IFlow, + KeyValuePairOfDateTimeAndDecimal, + MoneyManagement, + Position, + RiskLevel, + Scenario, + Signal, + Ticker, + Timeframe, + TradeDirection, + TradingBot, + TradingExchanges +} from '../generated/ManagingApi' +import {FC, ReactNode} from 'react' -import type { Account, AccountType, Backtest, Balance, BotType, Candle, FlowOutput, FlowType, IFlow, KeyValuePairOfDateTimeAndDecimal, MoneyManagement, Position, RiskLevel, Scenario, Signal, Ticker, Timeframe, TradeDirection, TradingBot, TradingExchanges } from '../generated/ManagingApi' -import { ReactNode, FC } from 'react' export type TabsType = { label: string index: number @@ -156,6 +173,7 @@ export type IBotList = { export type IScenarioFormInput = { name: string strategies: string[] + loopbackPeriod: number | undefined } export type IScenarioList = { list: Scenario[] diff --git a/src/Managing.WebApp/src/pages/scenarioPage/scenarioList.tsx b/src/Managing.WebApp/src/pages/scenarioPage/scenarioList.tsx index 436a9bf..3bc8ef0 100644 --- a/src/Managing.WebApp/src/pages/scenarioPage/scenarioList.tsx +++ b/src/Managing.WebApp/src/pages/scenarioPage/scenarioList.tsx @@ -1,13 +1,13 @@ -import React, { useEffect, useState } from 'react' -import type { SubmitHandler } from 'react-hook-form' -import { useForm } from 'react-hook-form' +import React, {useEffect, useState} from 'react' +import type {SubmitHandler} from 'react-hook-form' +import {useForm} from 'react-hook-form' import 'react-toastify/dist/ReactToastify.css' import useApiUrlStore from '../../app/store/apiStore' -import { Modal, Toast } from '../../components/mollecules' -import type { Scenario, Strategy } from '../../generated/ManagingApi' -import { ScenarioClient } from '../../generated/ManagingApi' -import type { IScenarioFormInput } from '../../global/type' +import {Modal, Toast} from '../../components/mollecules' +import type {Scenario, Strategy} from '../../generated/ManagingApi' +import {ScenarioClient} from '../../generated/ManagingApi' +import type {IScenarioFormInput} from '../../global/type' import ScenarioTable from './scenarioTable' @@ -22,7 +22,7 @@ const ScenarioList: React.FC = () => { async function createScenario(form: IScenarioFormInput) { const t = new Toast('Creating scenario') await client - .scenario_CreateScenario(form.name, form.strategies) + .scenario_CreateScenario(form.name, form.loopbackPeriod, form.strategies) .then((data: Scenario) => { t.update('success', 'Scenario created') setScenarios((arr) => [...arr, data]) @@ -97,6 +97,17 @@ const ScenarioList: React.FC = () => { +
+
+ + +
+