diff --git a/src/Managing.Application.Tests/BotsTests.cs b/src/Managing.Application.Tests/BotsTests.cs index 7d5b4ab..80882f6 100644 --- a/src/Managing.Application.Tests/BotsTests.cs +++ b/src/Managing.Application.Tests/BotsTests.cs @@ -129,7 +129,7 @@ namespace Managing.Application.Tests } [Theory] - [InlineData(Timeframe.FifteenMinutes, -6, StrategyType.RsiDivergenceConfirm, BotType.ScalpingBot)] + [InlineData(Timeframe.FifteenMinutes, -6, StrategyType.Stc, BotType.ScalpingBot)] //[InlineData(Timeframe.FifteenMinutes, -6, Enums.StrategyType.RsiDivergenceConfirm, Enums.BotType.FlippingBot)] public void GetBestPeriodRsiForDivergenceFlippingBot(Timeframe timeframe, int days, StrategyType strategyType, BotType botType) diff --git a/src/Managing.Application/Abstractions/ITradingBot.cs b/src/Managing.Application/Abstractions/ITradingBot.cs index 902f853..4afa9e9 100644 --- a/src/Managing.Application/Abstractions/ITradingBot.cs +++ b/src/Managing.Application/Abstractions/ITradingBot.cs @@ -3,6 +3,7 @@ using Managing.Domain.Bots; using Managing.Domain.Candles; using Managing.Domain.MoneyManagements; using Managing.Domain.Strategies; +using Managing.Domain.Strategies.Base; using Managing.Domain.Trades; using static Managing.Common.Enums; @@ -23,7 +24,7 @@ namespace Managing.Application.Abstractions MoneyManagement MoneyManagement { get; set; } BotType BotType { get; set; } Dictionary WalletBalances { get; set; } - + Dictionary StrategiesValues { get; set; } Task Run(); Task ToggleIsForWatchOnly(); @@ -32,5 +33,6 @@ namespace Managing.Application.Abstractions decimal GetTotalFees(); void LoadStrategies(IEnumerable strategies); void LoadScenario(string scenarioName); + void UpdateStrategiesValues(); } } \ No newline at end of file diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs index 674a7cb..f0f3594 100644 --- a/src/Managing.Application/Backtesting/Backtester.cs +++ b/src/Managing.Application/Backtesting/Backtester.cs @@ -2,12 +2,15 @@ using Managing.Application.Abstractions.Repositories; using Managing.Application.Abstractions.Services; using Managing.Core; +using Managing.Core.FixedSizedQueue; using Managing.Domain.Accounts; using Managing.Domain.Backtests; using Managing.Domain.Candles; using Managing.Domain.MoneyManagements; using Managing.Domain.Scenarios; using Managing.Domain.Shared.Helpers; +using Managing.Domain.Strategies; +using Managing.Domain.Strategies.Base; using Managing.Domain.Workflows; using Microsoft.Extensions.Logging; using static Managing.Common.Enums; @@ -20,17 +23,19 @@ namespace Managing.Application.Backtesting private readonly ILogger _logger; private readonly IExchangeService _exchangeService; private readonly IBotFactory _botFactory; + private readonly IScenarioService _scenarioService; public Backtester( IExchangeService exchangeService, IBotFactory botFactory, IBacktestRepository backtestRepository, - ILogger logger) + ILogger logger, IScenarioService scenarioService) { _exchangeService = exchangeService; _botFactory = botFactory; _backtestRepository = backtestRepository; _logger = logger; + _scenarioService = scenarioService; } public Backtest RunSimpleBotBacktest(Workflow workflow, bool save = false) @@ -124,7 +129,7 @@ namespace Managing.Application.Backtesting return result; } - private static Backtest GetBacktestingResult( + private Backtest GetBacktestingResult( Ticker ticker, Scenario scenario, Timeframe timeframe, @@ -143,10 +148,15 @@ namespace Managing.Application.Backtesting foreach (var candle in candles) { bot.OptimizedCandles.Enqueue(candle); + bot.Candles.Add(candle); bot.Run(); } bot.Candles = new HashSet(candles); + // bot.UpdateStrategiesValues(); + + var strategies = _scenarioService.GetStrategies(); + var strategiesValues = GetStrategiesValues(strategies, candles); var finalPnl = bot.GetProfitAndLoss(); var winRate = bot.GetWinRate(); @@ -165,12 +175,39 @@ namespace Managing.Application.Backtesting WalletBalances = bot.WalletBalances.ToList(), Statistics = stats, OptimizedMoneyManagement = optimizedMoneyManagement, - MoneyManagement = moneyManagement + MoneyManagement = moneyManagement, + StrategiesValues = strategiesValues }; return result; } + private Dictionary GetStrategiesValues(IEnumerable strategies, + List candles) + { + var strategiesValues = new Dictionary(); + var fixedCandles = new FixedSizeQueue(10000); + foreach (var candle in candles) + { + fixedCandles.Enqueue(candle); + } + + foreach (var strategy in strategies) + { + try + { + var s = ScenarioHelpers.BuildStrategy(strategy, 10000); + s.Candles = fixedCandles; + strategiesValues[strategy.Type] = s.GetStrategyValues(); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + return strategiesValues; + } public IEnumerable GetBacktests() { diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index fbb02af..ebca3f4 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -10,6 +10,7 @@ using Managing.Domain.MoneyManagements; using Managing.Domain.Scenarios; using Managing.Domain.Shared.Helpers; using Managing.Domain.Strategies; +using Managing.Domain.Strategies.Base; using Managing.Domain.Trades; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -46,6 +47,7 @@ public class TradingBot : Bot, ITradingBot public decimal Fee { get; set; } public Scenario Scenario { get; set; } public Dictionary WalletBalances { get; set; } + public Dictionary StrategiesValues { get; set; } public TradingBot( string accountName, @@ -87,6 +89,7 @@ public class TradingBot : Bot, ITradingBot Candles = new HashSet(); Positions = new List(); WalletBalances = new Dictionary(); + StrategiesValues = new Dictionary(); if (!isForBacktest) { @@ -184,7 +187,10 @@ public class TradingBot : Bot, ITradingBot await ManagePositions(); if (!IsForBacktest) + { SaveBackup(); + UpdateStrategiesValues(); + } await UpdateWalletBalances(); if (OptimizedCandles.Count % 100 == 0) // Log every 10th execution @@ -197,6 +203,14 @@ public class TradingBot : Bot, ITradingBot } } + public void UpdateStrategiesValues() + { + foreach (var strategy in Strategies) + { + StrategiesValues[strategy.Type] = ((Strategy)strategy).GetStrategyValues(); + } + } + private async Task PreloadCandles() { if (OptimizedCandles.Any()) diff --git a/src/Managing.Domain/Backtests/Backtest.cs b/src/Managing.Domain/Backtests/Backtest.cs index f981ba5..a1af0e2 100644 --- a/src/Managing.Domain/Backtests/Backtest.cs +++ b/src/Managing.Domain/Backtests/Backtest.cs @@ -4,6 +4,7 @@ using Managing.Domain.MoneyManagements; using Managing.Domain.Strategies; using Managing.Domain.Trades; using System.ComponentModel.DataAnnotations; +using Managing.Domain.Strategies.Base; using static Managing.Common.Enums; namespace Managing.Domain.Backtests; @@ -30,45 +31,30 @@ public class Backtest AccountName = accountName; } - [Required] - public string Id { get; set; } - [Required] - public decimal FinalPnl { get; set; } - [Required] - public int WinRate { get; set; } - [Required] - public decimal GrowthPercentage { get; set; } - [Required] - public decimal HodlPercentage { get; set; } - [Required] - public Ticker Ticker { get; } - [Required] - public string Scenario { get; set; } - [Required] - public List Positions { get; } - [Required] - public List Signals { get; } - [Required] - public Timeframe Timeframe { get; } - [Required] - public BotType BotType { get; } - [Required] - public string AccountName { get; } - [Required] - public List Candles { get; } - [Required] - public PerformanceMetrics Statistics { get; set; } - [Required] - public decimal Fees { get; set; } - [Required] - public List> WalletBalances { get; set; } - [Required] - public MoneyManagement OptimizedMoneyManagement { get; set; } - [Required] - public MoneyManagement MoneyManagement { get; set; } + [Required] public string Id { get; set; } + [Required] public decimal FinalPnl { get; set; } + [Required] public int WinRate { get; set; } + [Required] public decimal GrowthPercentage { get; set; } + [Required] public decimal HodlPercentage { get; set; } + [Required] public Ticker Ticker { get; } + [Required] public string Scenario { get; set; } + [Required] public List Positions { get; } + [Required] public List Signals { get; } + [Required] public Timeframe Timeframe { get; } + [Required] public BotType BotType { get; } + [Required] public string AccountName { get; } + [Required] public List Candles { get; } + [Required] public PerformanceMetrics Statistics { get; set; } + [Required] public decimal Fees { get; set; } + [Required] public List> WalletBalances { get; set; } + [Required] public MoneyManagement OptimizedMoneyManagement { get; set; } + [Required] public MoneyManagement MoneyManagement { get; set; } + + public Dictionary StrategiesValues { get; set; } public string GetStringReport() { - return $"{Ticker} | {Timeframe} | Positions: {Positions.Count} | Winrate: {WinRate}% | Pnl: {FinalPnl:#.##}$ | %Pnl: {GrowthPercentage:#.##}% | %Hodl: {HodlPercentage:#.##}%"; + return + $"{Ticker} | {Timeframe} | Positions: {Positions.Count} | Winrate: {WinRate}% | Pnl: {FinalPnl:#.##}$ | %Pnl: {GrowthPercentage:#.##}% | %Hodl: {HodlPercentage:#.##}%"; } } \ No newline at end of file diff --git a/src/Managing.Domain/Scenarios/ScenarioHelpers.cs b/src/Managing.Domain/Scenarios/ScenarioHelpers.cs index d590050..1ae1412 100644 --- a/src/Managing.Domain/Scenarios/ScenarioHelpers.cs +++ b/src/Managing.Domain/Scenarios/ScenarioHelpers.cs @@ -7,43 +7,51 @@ namespace Managing.Domain.Scenarios; public static class ScenarioHelpers { + + public static IEnumerable GetStrategiesFromScenario(Scenario scenario) { var strategies = new List(); foreach (var strategy in scenario.Strategies) { - IStrategy result = strategy.Type switch - { - 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.Period.Value), - StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, - strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value), - 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.Period.Value, strategy.Multiplier.Value), - StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, - strategy.Period.Value, strategy.Multiplier.Value), - 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.CyclePeriods.Value, - strategy.FastPeriods.Value, strategy.SlowPeriods.Value), - _ => throw new NotImplementedException(), - }; - - result.Candles = new FixedSizeQueue(600); + var result = BuildStrategy(strategy); strategies.Add(result); } return strategies; } + public static IStrategy BuildStrategy(Strategy strategy, int size = 600) + { + IStrategy result = strategy.Type switch + { + 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.Period.Value), + StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, + strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value), + 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.Period.Value, strategy.Multiplier.Value), + StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, + strategy.Period.Value, strategy.Multiplier.Value), + 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.CyclePeriods.Value, + strategy.FastPeriods.Value, strategy.SlowPeriods.Value), + _ => throw new NotImplementedException(), + }; + + result.Candles = new FixedSizeQueue(size); + return result; + } + public static Strategy BuildStrategy( StrategyType type, string name, diff --git a/src/Managing.Domain/Strategies/Base/StrategiesResultBase.cs b/src/Managing.Domain/Strategies/Base/StrategiesResultBase.cs new file mode 100644 index 0000000..b6ce7ba --- /dev/null +++ b/src/Managing.Domain/Strategies/Base/StrategiesResultBase.cs @@ -0,0 +1,18 @@ +using Skender.Stock.Indicators; + +namespace Managing.Domain.Strategies.Base; + +public class StrategiesResultBase +{ + public List Ema { get; set; } + public List Macd { get; set; } + public List Rsi { get; set; } + public List Stoch { get; set; } + public List StochRsi { get; set; } + public List BollingerBands { get; set; } + public List ChandelierShort { get; set; } + public List Stc { get; set; } + public List StdDev { get; set; } + public List SuperTrend { get; set; } + public List ChandelierLong { 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 888f5c0..e111996 100644 --- a/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs +++ b/src/Managing.Domain/Strategies/ChandelierExitStrategy.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -38,6 +39,15 @@ public class ChandelierExitStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + ChandelierLong = Candles.GetChandelier(Period.Value, Multiplier.Value, ChandelierType.Long).ToList(), + ChandelierShort = Candles.GetChandelier(Period.Value, Multiplier.Value, ChandelierType.Short).ToList() + }; + } + private void GetSignals(ChandelierType chandelierType) { var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType) diff --git a/src/Managing.Domain/Strategies/EmaCrossStrategy.cs b/src/Managing.Domain/Strategies/EmaCrossStrategy.cs index 62bde01..21516d9 100644 --- a/src/Managing.Domain/Strategies/EmaCrossStrategy.cs +++ b/src/Managing.Domain/Strategies/EmaCrossStrategy.cs @@ -16,6 +16,14 @@ public class EmaCrossStrategy : EmaBaseStrategy Period = period; } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + Ema = Candles.GetEma(Period.Value).ToList() + }; + } + public override List Run() { if (Candles.Count <= Period) diff --git a/src/Managing.Domain/Strategies/EmaTrendStrategy.cs b/src/Managing.Domain/Strategies/EmaTrendStrategy.cs index b52a4e2..073474e 100644 --- a/src/Managing.Domain/Strategies/EmaTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/EmaTrendStrategy.cs @@ -54,6 +54,14 @@ public class EmaTrendStrategy : EmaBaseStrategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + Ema = Candles.GetEma(Period.Value).ToList() + }; + } + public void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal(MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, diff --git a/src/Managing.Domain/Strategies/IStrategy.cs b/src/Managing.Domain/Strategies/IStrategy.cs index e842f3f..4440c40 100644 --- a/src/Managing.Domain/Strategies/IStrategy.cs +++ b/src/Managing.Domain/Strategies/IStrategy.cs @@ -1,5 +1,6 @@ using Managing.Core.FixedSizedQueue; using Managing.Domain.Candles; +using Managing.Domain.Strategies.Base; using static Managing.Common.Enums; namespace Managing.Domain.Strategies @@ -16,6 +17,7 @@ namespace Managing.Domain.Strategies FixedSizeQueue Candles { get; set; } List Run(); + StrategiesResultBase GetStrategyValues(); void UpdateCandles(HashSet newCandles); string GetName(); } diff --git a/src/Managing.Domain/Strategies/MACDCrossStrategy.cs b/src/Managing.Domain/Strategies/MACDCrossStrategy.cs index 00c32b9..6df2f53 100644 --- a/src/Managing.Domain/Strategies/MACDCrossStrategy.cs +++ b/src/Managing.Domain/Strategies/MACDCrossStrategy.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -58,6 +59,15 @@ public class MacdCrossStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + Macd = Candles.GetMacd(FastPeriods.Value, SlowPeriods.Value, SignalPeriods.Value).ToList() + }; + } + + private List MapMacdToCandle(List macd, IEnumerable candles) { var macdList = new List(); diff --git a/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs b/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs index 48939d3..7b4dd1d 100644 --- a/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs +++ b/src/Managing.Domain/Strategies/RSIDivergenceConfirmStrategy.cs @@ -1,5 +1,6 @@ using Managing.Core; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; using Candle = Managing.Domain.Candles.Candle; @@ -48,6 +49,14 @@ public class RSIDivergenceConfirmStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + Rsi = Candles.GetRsi(Period.Value).ToList() + }; + } + private void GetLongSignals(List candlesRsi) { // Set the low and high for first candle diff --git a/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs b/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs index dc9bb2a..0dfb42f 100644 --- a/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs +++ b/src/Managing.Domain/Strategies/RSIDivergenceStrategy.cs @@ -1,5 +1,6 @@ using Managing.Core; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; using Candle = Managing.Domain.Candles.Candle; @@ -51,6 +52,14 @@ public class RSIDivergenceStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + Rsi = Candles.GetRsi(Period.Value).ToList() + }; + } + private void GetLongSignals(List candlesRsi) { // Set the low and high for first candle diff --git a/src/Managing.Domain/Strategies/STCStrategy.cs b/src/Managing.Domain/Strategies/STCStrategy.cs index 59d69be..d7666be 100644 --- a/src/Managing.Domain/Strategies/STCStrategy.cs +++ b/src/Managing.Domain/Strategies/STCStrategy.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -57,6 +58,15 @@ public class STCStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList(); + return new StrategiesResultBase + { + Stc = stc + }; + } + private List MapStcToCandle(List stc, IEnumerable candles) { var sctList = new List(); diff --git a/src/Managing.Domain/Strategies/StDevContext.cs b/src/Managing.Domain/Strategies/StDevContext.cs index 7577b13..23a3a3a 100644 --- a/src/Managing.Domain/Strategies/StDevContext.cs +++ b/src/Managing.Domain/Strategies/StDevContext.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -50,6 +51,16 @@ public class StDevContext : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + var test = new StrategiesResultBase() + { + StdDev = Candles.GetStdDev(Period.Value).ToList() + }; + + return test; + } + private List MapStDev(List stDev, IEnumerable candles) { var sctList = new List(); diff --git a/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs b/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs index 10da0db..d975138 100644 --- a/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/StochRsiTrendStrategy.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -64,6 +65,15 @@ public class StochRsiTrendStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + StochRsi = Candles.GetStochRsi(Period.Value, StochPeriods.Value, SignalPeriods.Value, SmoothPeriods.Value) + .ToList() + }; + } + private List MapStochRsiToCandle(List ema, IEnumerable candles) { var emaList = new List(); diff --git a/src/Managing.Domain/Strategies/Strategy.cs b/src/Managing.Domain/Strategies/Strategy.cs index f8a46db..77dc0a3 100644 --- a/src/Managing.Domain/Strategies/Strategy.cs +++ b/src/Managing.Domain/Strategies/Strategy.cs @@ -2,6 +2,7 @@ using Managing.Core.FixedSizedQueue; using Managing.Domain.Candles; using Managing.Domain.Scenarios; +using Managing.Domain.Strategies.Base; using static Managing.Common.Enums; namespace Managing.Domain.Strategies @@ -34,6 +35,11 @@ namespace Managing.Domain.Strategies return new List(); } + public virtual StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase(); + } + public void UpdateCandles(HashSet newCandles) { if (newCandles == null || newCandles.Count == 0) diff --git a/src/Managing.Domain/Strategies/SuperTrendStrategy.cs b/src/Managing.Domain/Strategies/SuperTrendStrategy.cs index f2e2785..773973d 100644 --- a/src/Managing.Domain/Strategies/SuperTrendStrategy.cs +++ b/src/Managing.Domain/Strategies/SuperTrendStrategy.cs @@ -1,6 +1,7 @@ using Managing.Core; using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Skender.Stock.Indicators; using static Managing.Common.Enums; @@ -60,6 +61,15 @@ public class SuperTrendStrategy : Strategy } } + public override StrategiesResultBase GetStrategyValues() + { + return new StrategiesResultBase() + { + SuperTrend = Candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue) + .ToList() + }; + } + private List MapSuperTrendToCandle(List superTrend, IEnumerable candles) { var superTrends = new List(); diff --git a/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs b/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs index 24d4527..464f4c1 100644 --- a/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs +++ b/src/Managing.Domain/Strategies/ThreeWhiteSoldiersStrategy.cs @@ -1,5 +1,6 @@ using Managing.Domain.Candles; using Managing.Domain.Shared.Rules; +using Managing.Domain.Strategies.Base; using Managing.Domain.Strategies.Rules; using static Managing.Common.Enums; @@ -50,5 +51,10 @@ namespace Managing.Domain.Strategies return null; } } + + public override StrategiesResultBase GetStrategyValues() + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/Managing.Infrastructure.Tests/EvmManagerTests.cs b/src/Managing.Infrastructure.Tests/EvmManagerTests.cs index bc6f17f..25631ba 100644 --- a/src/Managing.Infrastructure.Tests/EvmManagerTests.cs +++ b/src/Managing.Infrastructure.Tests/EvmManagerTests.cs @@ -275,7 +275,7 @@ public class EvmManagerTests var manager = new EvmManager(Subgraphs); var account = PrivateKeys.GetAccount(); - var allowance = await manager.GetAllowance(account.Key, Ticker.BTC); + var allowance = await manager.GetAllowance(account.Key, Ticker.USDC); Assert.IsType(allowance); } diff --git a/src/Managing.WebApp/src/components/mollecules/ThemeSelector/ThemeSelector.tsx b/src/Managing.WebApp/src/components/mollecules/ThemeSelector/ThemeSelector.tsx index a526acf..cbfd5bd 100644 --- a/src/Managing.WebApp/src/components/mollecules/ThemeSelector/ThemeSelector.tsx +++ b/src/Managing.WebApp/src/components/mollecules/ThemeSelector/ThemeSelector.tsx @@ -1,5 +1,5 @@ import useTheme from '../../../hooks/useTheme' -const themes = ['black', 'coffee', 'cyberpunk', 'lofi', 'retro'] +const themes = ['black', 'coffee', 'cyberpunk', 'lofi', 'retro', 'kaigen'] const ThemeSelector = (): JSX.Element => { const { setTheme } = useTheme() diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx index f1c3038..e994dfa 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx @@ -139,6 +139,7 @@ const BacktestCards: React.FC = ({ list, setBacktests }) => { positions={backtest.positions} walletBalances={backtest.walletBalances} signals={backtest.signals} + strategiesValues={backtest.strategiesValues} width={720} height={512} > diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx index 1ce93dd..0262d48 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx @@ -1,11 +1,12 @@ import { TradeChart, CardPositionItem } from '..' -import type { IBotRowDetails } from '../../../global/interface' +import { IBotRowDetails } from '../../../global/type' import { CardPosition } from '../../mollecules' const BacktestRowDetails: React.FC = ({ candles, positions, walletBalances, + strategiesValues, }) => { return ( <> @@ -30,11 +31,12 @@ const BacktestRowDetails: React.FC = ({
diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx index 9f06c57..6866da5 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx @@ -247,6 +247,7 @@ const BacktestTable: React.FC = ({ list, isFetching }) => { candles={row.original.candles} positions={row.original.positions} walletBalances={row.original.walletBalances} + strategiesValues={row.original.strategiesValues} > ), diff --git a/src/Managing.WebApp/src/components/organism/Trading/TradeChart/TradeChart.tsx b/src/Managing.WebApp/src/components/organism/Trading/TradeChart/TradeChart.tsx index 10c92c3..98e02d2 100644 --- a/src/Managing.WebApp/src/components/organism/Trading/TradeChart/TradeChart.tsx +++ b/src/Managing.WebApp/src/components/organism/Trading/TradeChart/TradeChart.tsx @@ -1,4 +1,5 @@ import type { + BaselineSeriesOptions, CandlestickData, IChartApi, ISeriesApi, @@ -18,6 +19,8 @@ import type { KeyValuePairOfDateTimeAndDecimal, Position, Signal, + StrategiesResultBase, + StrategyType, } from '../../../../generated/ManagingApi' import { PositionStatus, @@ -25,11 +28,27 @@ import { } from '../../../../generated/ManagingApi' import useTheme from '../../../../hooks/useTheme' +// var customTheme = { +// background: '#0B0B0B', +// neutral: '#151515', +// primary: '#54B5F9', +// secondary: '#C492B1', +// third: '#B0DB43', +// fourth: '#F2D398', +// fifth: '#99EDCC', +// red: '#FF5340', +// green: '#08C25F', +// orange: '#EB6F22', +// } + + + type ITradeChartProps = { candles: Candle[] positions: Position[] signals: Signal[] walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null + strategiesValues?: { [key in keyof typeof StrategyType]?: StrategiesResultBase; } | null; stream?: Candle | null width: number height: number @@ -40,6 +59,7 @@ const TradeChart = ({ positions, signals, walletBalances, + strategiesValues, stream, width, height, @@ -68,6 +88,12 @@ const TradeChart = ({ } } + const baselineOptions: BaselineSeriesOptions = { + bottomLineColor: theme.secondary, + topLineColor: theme.primary, + lineWidth: 1, + } as BaselineSeriesOptions + function buildMarker( shape: SeriesMarkerShape, color: string, @@ -142,7 +168,7 @@ const TradeChart = ({ useEffect(() => { if (chartRef.current) { - const lineColor = theme.secondary + const lineColor = theme['base-100'] chart.current = createChart(chartRef.current, { crosshair: { mode: CrosshairMode.Normal, @@ -159,8 +185,8 @@ const TradeChart = ({ }, height: height, layout: { - background: {color: '#121212'}, - textColor: theme.secondary, + background: {color: theme['base-300']}, + textColor: theme.accent, }, localization: { dateFormat: 'yyyy-MM-dd', @@ -198,11 +224,11 @@ const TradeChart = ({ if (!chart.current) return series1.current = chart.current.addCandlestickSeries({ - borderDownColor: theme.secondary, + borderDownColor: theme.accent, borderUpColor: theme.primary, - downColor: theme.secondary, + downColor: theme.accent, upColor: theme.primary, - wickDownColor: theme.secondary, + wickDownColor: theme.accent, wickUpColor: theme.primary, }) @@ -230,7 +256,6 @@ const TradeChart = ({ }, }) - const markers: SeriesMarker