Add indicators to backtest and bot (#14)
* Add indicators to backtest and bot * Remove
This commit is contained in:
@@ -129,7 +129,7 @@ namespace Managing.Application.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[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)]
|
//[InlineData(Timeframe.FifteenMinutes, -6, Enums.StrategyType.RsiDivergenceConfirm, Enums.BotType.FlippingBot)]
|
||||||
public void GetBestPeriodRsiForDivergenceFlippingBot(Timeframe timeframe, int days, StrategyType strategyType,
|
public void GetBestPeriodRsiForDivergenceFlippingBot(Timeframe timeframe, int days, StrategyType strategyType,
|
||||||
BotType botType)
|
BotType botType)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Managing.Domain.Bots;
|
|||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.MoneyManagements;
|
using Managing.Domain.MoneyManagements;
|
||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ namespace Managing.Application.Abstractions
|
|||||||
MoneyManagement MoneyManagement { get; set; }
|
MoneyManagement MoneyManagement { get; set; }
|
||||||
BotType BotType { get; set; }
|
BotType BotType { get; set; }
|
||||||
Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
||||||
|
Dictionary<StrategyType, StrategiesResultBase> StrategiesValues { get; set; }
|
||||||
|
|
||||||
Task Run();
|
Task Run();
|
||||||
Task ToggleIsForWatchOnly();
|
Task ToggleIsForWatchOnly();
|
||||||
@@ -32,5 +33,6 @@ namespace Managing.Application.Abstractions
|
|||||||
decimal GetTotalFees();
|
decimal GetTotalFees();
|
||||||
void LoadStrategies(IEnumerable<IStrategy> strategies);
|
void LoadStrategies(IEnumerable<IStrategy> strategies);
|
||||||
void LoadScenario(string scenarioName);
|
void LoadScenario(string scenarioName);
|
||||||
|
void UpdateStrategiesValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,15 @@
|
|||||||
using Managing.Application.Abstractions.Repositories;
|
using Managing.Application.Abstractions.Repositories;
|
||||||
using Managing.Application.Abstractions.Services;
|
using Managing.Application.Abstractions.Services;
|
||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
|
using Managing.Core.FixedSizedQueue;
|
||||||
using Managing.Domain.Accounts;
|
using Managing.Domain.Accounts;
|
||||||
using Managing.Domain.Backtests;
|
using Managing.Domain.Backtests;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.MoneyManagements;
|
using Managing.Domain.MoneyManagements;
|
||||||
using Managing.Domain.Scenarios;
|
using Managing.Domain.Scenarios;
|
||||||
using Managing.Domain.Shared.Helpers;
|
using Managing.Domain.Shared.Helpers;
|
||||||
|
using Managing.Domain.Strategies;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Managing.Domain.Workflows;
|
using Managing.Domain.Workflows;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
@@ -20,17 +23,19 @@ namespace Managing.Application.Backtesting
|
|||||||
private readonly ILogger<Backtester> _logger;
|
private readonly ILogger<Backtester> _logger;
|
||||||
private readonly IExchangeService _exchangeService;
|
private readonly IExchangeService _exchangeService;
|
||||||
private readonly IBotFactory _botFactory;
|
private readonly IBotFactory _botFactory;
|
||||||
|
private readonly IScenarioService _scenarioService;
|
||||||
|
|
||||||
public Backtester(
|
public Backtester(
|
||||||
IExchangeService exchangeService,
|
IExchangeService exchangeService,
|
||||||
IBotFactory botFactory,
|
IBotFactory botFactory,
|
||||||
IBacktestRepository backtestRepository,
|
IBacktestRepository backtestRepository,
|
||||||
ILogger<Backtester> logger)
|
ILogger<Backtester> logger, IScenarioService scenarioService)
|
||||||
{
|
{
|
||||||
_exchangeService = exchangeService;
|
_exchangeService = exchangeService;
|
||||||
_botFactory = botFactory;
|
_botFactory = botFactory;
|
||||||
_backtestRepository = backtestRepository;
|
_backtestRepository = backtestRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_scenarioService = scenarioService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Backtest RunSimpleBotBacktest(Workflow workflow, bool save = false)
|
public Backtest RunSimpleBotBacktest(Workflow workflow, bool save = false)
|
||||||
@@ -124,7 +129,7 @@ namespace Managing.Application.Backtesting
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Backtest GetBacktestingResult(
|
private Backtest GetBacktestingResult(
|
||||||
Ticker ticker,
|
Ticker ticker,
|
||||||
Scenario scenario,
|
Scenario scenario,
|
||||||
Timeframe timeframe,
|
Timeframe timeframe,
|
||||||
@@ -143,10 +148,15 @@ namespace Managing.Application.Backtesting
|
|||||||
foreach (var candle in candles)
|
foreach (var candle in candles)
|
||||||
{
|
{
|
||||||
bot.OptimizedCandles.Enqueue(candle);
|
bot.OptimizedCandles.Enqueue(candle);
|
||||||
|
bot.Candles.Add(candle);
|
||||||
bot.Run();
|
bot.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
bot.Candles = new HashSet<Candle>(candles);
|
bot.Candles = new HashSet<Candle>(candles);
|
||||||
|
// bot.UpdateStrategiesValues();
|
||||||
|
|
||||||
|
var strategies = _scenarioService.GetStrategies();
|
||||||
|
var strategiesValues = GetStrategiesValues(strategies, candles);
|
||||||
|
|
||||||
var finalPnl = bot.GetProfitAndLoss();
|
var finalPnl = bot.GetProfitAndLoss();
|
||||||
var winRate = bot.GetWinRate();
|
var winRate = bot.GetWinRate();
|
||||||
@@ -165,12 +175,39 @@ namespace Managing.Application.Backtesting
|
|||||||
WalletBalances = bot.WalletBalances.ToList(),
|
WalletBalances = bot.WalletBalances.ToList(),
|
||||||
Statistics = stats,
|
Statistics = stats,
|
||||||
OptimizedMoneyManagement = optimizedMoneyManagement,
|
OptimizedMoneyManagement = optimizedMoneyManagement,
|
||||||
MoneyManagement = moneyManagement
|
MoneyManagement = moneyManagement,
|
||||||
|
StrategiesValues = strategiesValues
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dictionary<StrategyType, StrategiesResultBase> GetStrategiesValues(IEnumerable<Strategy> strategies,
|
||||||
|
List<Candle> candles)
|
||||||
|
{
|
||||||
|
var strategiesValues = new Dictionary<StrategyType, StrategiesResultBase>();
|
||||||
|
var fixedCandles = new FixedSizeQueue<Candle>(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<Backtest> GetBacktests()
|
public IEnumerable<Backtest> GetBacktests()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Managing.Domain.MoneyManagements;
|
|||||||
using Managing.Domain.Scenarios;
|
using Managing.Domain.Scenarios;
|
||||||
using Managing.Domain.Shared.Helpers;
|
using Managing.Domain.Shared.Helpers;
|
||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -46,6 +47,7 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
public decimal Fee { get; set; }
|
public decimal Fee { get; set; }
|
||||||
public Scenario Scenario { get; set; }
|
public Scenario Scenario { get; set; }
|
||||||
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
|
||||||
|
public Dictionary<StrategyType, StrategiesResultBase> StrategiesValues { get; set; }
|
||||||
|
|
||||||
public TradingBot(
|
public TradingBot(
|
||||||
string accountName,
|
string accountName,
|
||||||
@@ -87,6 +89,7 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
Candles = new HashSet<Candle>();
|
Candles = new HashSet<Candle>();
|
||||||
Positions = new List<Position>();
|
Positions = new List<Position>();
|
||||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||||
|
StrategiesValues = new Dictionary<StrategyType, StrategiesResultBase>();
|
||||||
|
|
||||||
if (!isForBacktest)
|
if (!isForBacktest)
|
||||||
{
|
{
|
||||||
@@ -184,7 +187,10 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
await ManagePositions();
|
await ManagePositions();
|
||||||
|
|
||||||
if (!IsForBacktest)
|
if (!IsForBacktest)
|
||||||
|
{
|
||||||
SaveBackup();
|
SaveBackup();
|
||||||
|
UpdateStrategiesValues();
|
||||||
|
}
|
||||||
|
|
||||||
await UpdateWalletBalances();
|
await UpdateWalletBalances();
|
||||||
if (OptimizedCandles.Count % 100 == 0) // Log every 10th execution
|
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()
|
private async Task PreloadCandles()
|
||||||
{
|
{
|
||||||
if (OptimizedCandles.Any())
|
if (OptimizedCandles.Any())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Managing.Domain.MoneyManagements;
|
|||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Domain.Backtests;
|
namespace Managing.Domain.Backtests;
|
||||||
@@ -30,45 +31,30 @@ public class Backtest
|
|||||||
AccountName = accountName;
|
AccountName = accountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Required]
|
[Required] public string Id { get; set; }
|
||||||
public string Id { get; set; }
|
[Required] public decimal FinalPnl { get; set; }
|
||||||
[Required]
|
[Required] public int WinRate { get; set; }
|
||||||
public decimal FinalPnl { get; set; }
|
[Required] public decimal GrowthPercentage { get; set; }
|
||||||
[Required]
|
[Required] public decimal HodlPercentage { get; set; }
|
||||||
public int WinRate { get; set; }
|
[Required] public Ticker Ticker { get; }
|
||||||
[Required]
|
[Required] public string Scenario { get; set; }
|
||||||
public decimal GrowthPercentage { get; set; }
|
[Required] public List<Position> Positions { get; }
|
||||||
[Required]
|
[Required] public List<Signal> Signals { get; }
|
||||||
public decimal HodlPercentage { get; set; }
|
[Required] public Timeframe Timeframe { get; }
|
||||||
[Required]
|
[Required] public BotType BotType { get; }
|
||||||
public Ticker Ticker { get; }
|
[Required] public string AccountName { get; }
|
||||||
[Required]
|
[Required] public List<Candle> Candles { get; }
|
||||||
public string Scenario { get; set; }
|
[Required] public PerformanceMetrics Statistics { get; set; }
|
||||||
[Required]
|
[Required] public decimal Fees { get; set; }
|
||||||
public List<Position> Positions { get; }
|
[Required] public List<KeyValuePair<DateTime, decimal>> WalletBalances { get; set; }
|
||||||
[Required]
|
[Required] public MoneyManagement OptimizedMoneyManagement { get; set; }
|
||||||
public List<Signal> Signals { get; }
|
[Required] public MoneyManagement MoneyManagement { get; set; }
|
||||||
[Required]
|
|
||||||
public Timeframe Timeframe { get; }
|
public Dictionary<StrategyType, StrategiesResultBase> StrategiesValues { get; set; }
|
||||||
[Required]
|
|
||||||
public BotType BotType { get; }
|
|
||||||
[Required]
|
|
||||||
public string AccountName { get; }
|
|
||||||
[Required]
|
|
||||||
public List<Candle> Candles { get; }
|
|
||||||
[Required]
|
|
||||||
public PerformanceMetrics Statistics { get; set; }
|
|
||||||
[Required]
|
|
||||||
public decimal Fees { get; set; }
|
|
||||||
[Required]
|
|
||||||
public List<KeyValuePair<DateTime, decimal>> WalletBalances { get; set; }
|
|
||||||
[Required]
|
|
||||||
public MoneyManagement OptimizedMoneyManagement { get; set; }
|
|
||||||
[Required]
|
|
||||||
public MoneyManagement MoneyManagement { get; set; }
|
|
||||||
|
|
||||||
public string GetStringReport()
|
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:#.##}%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,43 +7,51 @@ namespace Managing.Domain.Scenarios;
|
|||||||
|
|
||||||
public static class ScenarioHelpers
|
public static class ScenarioHelpers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static IEnumerable<IStrategy> GetStrategiesFromScenario(Scenario scenario)
|
public static IEnumerable<IStrategy> GetStrategiesFromScenario(Scenario scenario)
|
||||||
{
|
{
|
||||||
var strategies = new List<IStrategy>();
|
var strategies = new List<IStrategy>();
|
||||||
foreach (var strategy in scenario.Strategies)
|
foreach (var strategy in scenario.Strategies)
|
||||||
{
|
{
|
||||||
IStrategy result = strategy.Type switch
|
var result = BuildStrategy(strategy);
|
||||||
{
|
|
||||||
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<Candle>(600);
|
|
||||||
strategies.Add(result);
|
strategies.Add(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return strategies;
|
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<Candle>(size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static Strategy BuildStrategy(
|
public static Strategy BuildStrategy(
|
||||||
StrategyType type,
|
StrategyType type,
|
||||||
string name,
|
string name,
|
||||||
|
|||||||
18
src/Managing.Domain/Strategies/Base/StrategiesResultBase.cs
Normal file
18
src/Managing.Domain/Strategies/Base/StrategiesResultBase.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Skender.Stock.Indicators;
|
||||||
|
|
||||||
|
namespace Managing.Domain.Strategies.Base;
|
||||||
|
|
||||||
|
public class StrategiesResultBase
|
||||||
|
{
|
||||||
|
public List<EmaResult> Ema { get; set; }
|
||||||
|
public List<MacdResult> Macd { get; set; }
|
||||||
|
public List<RsiResult> Rsi { get; set; }
|
||||||
|
public List<StochResult> Stoch { get; set; }
|
||||||
|
public List<StochRsiResult> StochRsi { get; set; }
|
||||||
|
public List<BollingerBandsResult> BollingerBands { get; set; }
|
||||||
|
public List<ChandelierResult> ChandelierShort { get; set; }
|
||||||
|
public List<StcResult> Stc { get; set; }
|
||||||
|
public List<StdDevResult> StdDev { get; set; }
|
||||||
|
public List<SuperTrendResult> SuperTrend { get; set; }
|
||||||
|
public List<ChandelierResult> ChandelierLong { get; set; }
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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)
|
private void GetSignals(ChandelierType chandelierType)
|
||||||
{
|
{
|
||||||
var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType)
|
var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType)
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ public class EmaCrossStrategy : EmaBaseStrategy
|
|||||||
Period = period;
|
Period = period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override StrategiesResultBase GetStrategyValues()
|
||||||
|
{
|
||||||
|
return new StrategiesResultBase()
|
||||||
|
{
|
||||||
|
Ema = Candles.GetEma(Period.Value).ToList()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public override List<Signal> Run()
|
public override List<Signal> Run()
|
||||||
{
|
{
|
||||||
if (Candles.Count <= Period)
|
if (Candles.Count <= Period)
|
||||||
|
|||||||
@@ -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)
|
public void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence)
|
||||||
{
|
{
|
||||||
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
|
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Managing.Core.FixedSizedQueue;
|
using Managing.Core.FixedSizedQueue;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Domain.Strategies
|
namespace Managing.Domain.Strategies
|
||||||
@@ -16,6 +17,7 @@ namespace Managing.Domain.Strategies
|
|||||||
FixedSizeQueue<Candle> Candles { get; set; }
|
FixedSizeQueue<Candle> Candles { get; set; }
|
||||||
|
|
||||||
List<Signal> Run();
|
List<Signal> Run();
|
||||||
|
StrategiesResultBase GetStrategyValues();
|
||||||
void UpdateCandles(HashSet<Candle> newCandles);
|
void UpdateCandles(HashSet<Candle> newCandles);
|
||||||
string GetName();
|
string GetName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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<CandleMacd> MapMacdToCandle(List<MacdResult> macd, IEnumerable<Candle> candles)
|
private List<CandleMacd> MapMacdToCandle(List<MacdResult> macd, IEnumerable<Candle> candles)
|
||||||
{
|
{
|
||||||
var macdList = new List<CandleMacd>();
|
var macdList = new List<CandleMacd>();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
using Candle = Managing.Domain.Candles.Candle;
|
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<CandleRsi> candlesRsi)
|
private void GetLongSignals(List<CandleRsi> candlesRsi)
|
||||||
{
|
{
|
||||||
// Set the low and high for first candle
|
// Set the low and high for first candle
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
using Candle = Managing.Domain.Candles.Candle;
|
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<CandleRsi> candlesRsi)
|
private void GetLongSignals(List<CandleRsi> candlesRsi)
|
||||||
{
|
{
|
||||||
// Set the low and high for first candle
|
// Set the low and high for first candle
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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<CandleSct> MapStcToCandle(List<StcResult> stc, IEnumerable<Candle> candles)
|
private List<CandleSct> MapStcToCandle(List<StcResult> stc, IEnumerable<Candle> candles)
|
||||||
{
|
{
|
||||||
var sctList = new List<CandleSct>();
|
var sctList = new List<CandleSct>();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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<CandleStDev> MapStDev(List<StdDevResult> stDev, IEnumerable<Candle> candles)
|
private List<CandleStDev> MapStDev(List<StdDevResult> stDev, IEnumerable<Candle> candles)
|
||||||
{
|
{
|
||||||
var sctList = new List<CandleStDev>();
|
var sctList = new List<CandleStDev>();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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<CandleStochRsi> MapStochRsiToCandle(List<StochRsiResult> ema, IEnumerable<Candle> candles)
|
private List<CandleStochRsi> MapStochRsiToCandle(List<StochRsiResult> ema, IEnumerable<Candle> candles)
|
||||||
{
|
{
|
||||||
var emaList = new List<CandleStochRsi>();
|
var emaList = new List<CandleStochRsi>();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Managing.Core.FixedSizedQueue;
|
using Managing.Core.FixedSizedQueue;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Scenarios;
|
using Managing.Domain.Scenarios;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Domain.Strategies
|
namespace Managing.Domain.Strategies
|
||||||
@@ -34,6 +35,11 @@ namespace Managing.Domain.Strategies
|
|||||||
return new List<Signal>();
|
return new List<Signal>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual StrategiesResultBase GetStrategyValues()
|
||||||
|
{
|
||||||
|
return new StrategiesResultBase();
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateCandles(HashSet<Candle> newCandles)
|
public void UpdateCandles(HashSet<Candle> newCandles)
|
||||||
{
|
{
|
||||||
if (newCandles == null || newCandles.Count == 0)
|
if (newCandles == null || newCandles.Count == 0)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Managing.Core;
|
using Managing.Core;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using static Managing.Common.Enums;
|
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<CandleSuperTrend> MapSuperTrendToCandle(List<SuperTrendResult> superTrend, IEnumerable<Candle> candles)
|
private List<CandleSuperTrend> MapSuperTrendToCandle(List<SuperTrendResult> superTrend, IEnumerable<Candle> candles)
|
||||||
{
|
{
|
||||||
var superTrends = new List<CandleSuperTrend>();
|
var superTrends = new List<CandleSuperTrend>();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Shared.Rules;
|
using Managing.Domain.Shared.Rules;
|
||||||
|
using Managing.Domain.Strategies.Base;
|
||||||
using Managing.Domain.Strategies.Rules;
|
using Managing.Domain.Strategies.Rules;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
@@ -50,5 +51,10 @@ namespace Managing.Domain.Strategies
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override StrategiesResultBase GetStrategyValues()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ public class EvmManagerTests
|
|||||||
var manager = new EvmManager(Subgraphs);
|
var manager = new EvmManager(Subgraphs);
|
||||||
var account = PrivateKeys.GetAccount();
|
var account = PrivateKeys.GetAccount();
|
||||||
|
|
||||||
var allowance = await manager.GetAllowance(account.Key, Ticker.BTC);
|
var allowance = await manager.GetAllowance(account.Key, Ticker.USDC);
|
||||||
Assert.IsType<decimal>(allowance);
|
Assert.IsType<decimal>(allowance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import useTheme from '../../../hooks/useTheme'
|
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 ThemeSelector = (): JSX.Element => {
|
||||||
const { setTheme } = useTheme()
|
const { setTheme } = useTheme()
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ const BacktestCards: React.FC<IBacktestCards> = ({ list, setBacktests }) => {
|
|||||||
positions={backtest.positions}
|
positions={backtest.positions}
|
||||||
walletBalances={backtest.walletBalances}
|
walletBalances={backtest.walletBalances}
|
||||||
signals={backtest.signals}
|
signals={backtest.signals}
|
||||||
|
strategiesValues={backtest.strategiesValues}
|
||||||
width={720}
|
width={720}
|
||||||
height={512}
|
height={512}
|
||||||
></TradeChart>
|
></TradeChart>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { TradeChart, CardPositionItem } from '..'
|
import { TradeChart, CardPositionItem } from '..'
|
||||||
import type { IBotRowDetails } from '../../../global/interface'
|
import { IBotRowDetails } from '../../../global/type'
|
||||||
import { CardPosition } from '../../mollecules'
|
import { CardPosition } from '../../mollecules'
|
||||||
|
|
||||||
const BacktestRowDetails: React.FC<IBotRowDetails> = ({
|
const BacktestRowDetails: React.FC<IBotRowDetails> = ({
|
||||||
candles,
|
candles,
|
||||||
positions,
|
positions,
|
||||||
walletBalances,
|
walletBalances,
|
||||||
|
strategiesValues,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -30,11 +31,12 @@ const BacktestRowDetails: React.FC<IBotRowDetails> = ({
|
|||||||
<div>
|
<div>
|
||||||
<figure>
|
<figure>
|
||||||
<TradeChart
|
<TradeChart
|
||||||
width={1000}
|
width={1400}
|
||||||
height={500}
|
height={1400}
|
||||||
candles={candles}
|
candles={candles}
|
||||||
positions={positions}
|
positions={positions}
|
||||||
walletBalances={walletBalances}
|
walletBalances={walletBalances}
|
||||||
|
strategiesValues={strategiesValues}
|
||||||
signals={[]}
|
signals={[]}
|
||||||
></TradeChart>
|
></TradeChart>
|
||||||
</figure>
|
</figure>
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ const BacktestTable: React.FC<IBacktestCards> = ({ list, isFetching }) => {
|
|||||||
candles={row.original.candles}
|
candles={row.original.candles}
|
||||||
positions={row.original.positions}
|
positions={row.original.positions}
|
||||||
walletBalances={row.original.walletBalances}
|
walletBalances={row.original.walletBalances}
|
||||||
|
strategiesValues={row.original.strategiesValues}
|
||||||
></BacktestRowDetails>
|
></BacktestRowDetails>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
|
BaselineSeriesOptions,
|
||||||
CandlestickData,
|
CandlestickData,
|
||||||
IChartApi,
|
IChartApi,
|
||||||
ISeriesApi,
|
ISeriesApi,
|
||||||
@@ -18,6 +19,8 @@ import type {
|
|||||||
KeyValuePairOfDateTimeAndDecimal,
|
KeyValuePairOfDateTimeAndDecimal,
|
||||||
Position,
|
Position,
|
||||||
Signal,
|
Signal,
|
||||||
|
StrategiesResultBase,
|
||||||
|
StrategyType,
|
||||||
} from '../../../../generated/ManagingApi'
|
} from '../../../../generated/ManagingApi'
|
||||||
import {
|
import {
|
||||||
PositionStatus,
|
PositionStatus,
|
||||||
@@ -25,11 +28,27 @@ import {
|
|||||||
} from '../../../../generated/ManagingApi'
|
} from '../../../../generated/ManagingApi'
|
||||||
import useTheme from '../../../../hooks/useTheme'
|
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 = {
|
type ITradeChartProps = {
|
||||||
candles: Candle[]
|
candles: Candle[]
|
||||||
positions: Position[]
|
positions: Position[]
|
||||||
signals: Signal[]
|
signals: Signal[]
|
||||||
walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null
|
walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null
|
||||||
|
strategiesValues?: { [key in keyof typeof StrategyType]?: StrategiesResultBase; } | null;
|
||||||
stream?: Candle | null
|
stream?: Candle | null
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
@@ -40,6 +59,7 @@ const TradeChart = ({
|
|||||||
positions,
|
positions,
|
||||||
signals,
|
signals,
|
||||||
walletBalances,
|
walletBalances,
|
||||||
|
strategiesValues,
|
||||||
stream,
|
stream,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@@ -68,6 +88,12 @@ const TradeChart = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const baselineOptions: BaselineSeriesOptions = {
|
||||||
|
bottomLineColor: theme.secondary,
|
||||||
|
topLineColor: theme.primary,
|
||||||
|
lineWidth: 1,
|
||||||
|
} as BaselineSeriesOptions
|
||||||
|
|
||||||
function buildMarker(
|
function buildMarker(
|
||||||
shape: SeriesMarkerShape,
|
shape: SeriesMarkerShape,
|
||||||
color: string,
|
color: string,
|
||||||
@@ -142,7 +168,7 @@ const TradeChart = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chartRef.current) {
|
if (chartRef.current) {
|
||||||
const lineColor = theme.secondary
|
const lineColor = theme['base-100']
|
||||||
chart.current = createChart(chartRef.current, {
|
chart.current = createChart(chartRef.current, {
|
||||||
crosshair: {
|
crosshair: {
|
||||||
mode: CrosshairMode.Normal,
|
mode: CrosshairMode.Normal,
|
||||||
@@ -159,8 +185,8 @@ const TradeChart = ({
|
|||||||
},
|
},
|
||||||
height: height,
|
height: height,
|
||||||
layout: {
|
layout: {
|
||||||
background: {color: '#121212'},
|
background: {color: theme['base-300']},
|
||||||
textColor: theme.secondary,
|
textColor: theme.accent,
|
||||||
},
|
},
|
||||||
localization: {
|
localization: {
|
||||||
dateFormat: 'yyyy-MM-dd',
|
dateFormat: 'yyyy-MM-dd',
|
||||||
@@ -198,11 +224,11 @@ const TradeChart = ({
|
|||||||
if (!chart.current) return
|
if (!chart.current) return
|
||||||
|
|
||||||
series1.current = chart.current.addCandlestickSeries({
|
series1.current = chart.current.addCandlestickSeries({
|
||||||
borderDownColor: theme.secondary,
|
borderDownColor: theme.accent,
|
||||||
borderUpColor: theme.primary,
|
borderUpColor: theme.primary,
|
||||||
downColor: theme.secondary,
|
downColor: theme.accent,
|
||||||
upColor: theme.primary,
|
upColor: theme.primary,
|
||||||
wickDownColor: theme.secondary,
|
wickDownColor: theme.accent,
|
||||||
wickUpColor: theme.primary,
|
wickUpColor: theme.primary,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -230,7 +256,6 @@ const TradeChart = ({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const markers: SeriesMarker<Time>[] = []
|
const markers: SeriesMarker<Time>[] = []
|
||||||
|
|
||||||
if (signals) {
|
if (signals) {
|
||||||
@@ -271,20 +296,268 @@ const TradeChart = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Price panel
|
||||||
|
if (strategiesValues?.EmaTrend != null || strategiesValues?.EmaCross != null)
|
||||||
|
{
|
||||||
|
const emaSeries = chart.current.addLineSeries({
|
||||||
|
color: theme.secondary,
|
||||||
|
lineWidth: 1,
|
||||||
|
priceLineVisible: true,
|
||||||
|
priceLineWidth: 1,
|
||||||
|
priceFormat: {
|
||||||
|
minMove: 0.0001,
|
||||||
|
precision: 4,
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
title: 'EMA',
|
||||||
|
})
|
||||||
|
|
||||||
|
const ema = strategiesValues.EmaTrend?.ema ?? strategiesValues.EmaCross?.ema
|
||||||
|
|
||||||
|
const emaData = ema?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.ema,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (emaData != null)
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
emaSeries.setData(emaData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategiesValues?.SuperTrend != null) {
|
||||||
|
const superTrendSeries = chart.current.addLineSeries({
|
||||||
|
color: theme.info,
|
||||||
|
lineWidth: 1,
|
||||||
|
priceLineVisible: false,
|
||||||
|
priceLineWidth: 1,
|
||||||
|
priceLineColor: theme.info,
|
||||||
|
title: 'SuperTrend',
|
||||||
|
pane: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const superTrend = strategiesValues.SuperTrend.superTrend?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.superTrend,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
superTrendSeries.setData(superTrend)
|
||||||
|
}
|
||||||
|
|
||||||
if (markers.length > 0) {
|
if (markers.length > 0) {
|
||||||
series1.current.setMarkers(markers)
|
series1.current.setMarkers(markers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Indicator panel
|
||||||
|
var paneCount = 1
|
||||||
|
|
||||||
|
|
||||||
|
if (strategiesValues?.RsiDivergence != null || strategiesValues?.RsiDivergenceConfirm != null)
|
||||||
|
{
|
||||||
|
const rsiSeries = chart.current.addLineSeries({
|
||||||
|
pane: paneCount,
|
||||||
|
title: 'RSI',
|
||||||
|
})
|
||||||
|
|
||||||
|
const rsi = strategiesValues.RsiDivergence?.rsi ?? strategiesValues.RsiDivergenceConfirm?.rsi
|
||||||
|
|
||||||
|
const rsiData = rsi?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.rsi,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
rsiSeries.setData(rsiData)
|
||||||
|
rsiSeries.applyOptions({
|
||||||
|
...baselineOptions,
|
||||||
|
priceFormat: {
|
||||||
|
minMove: 0.01,
|
||||||
|
precision: 4,
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
paneCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategiesValues?.Stc != null) {
|
||||||
|
const stcSeries = chart.current.addBaselineSeries({
|
||||||
|
pane: paneCount,
|
||||||
|
baseValue: {price: 50, type: 'price'},
|
||||||
|
|
||||||
|
title: 'STC',
|
||||||
|
})
|
||||||
|
|
||||||
|
stcSeries.createPriceLine(buildLine(theme.error, 25, 'low'))
|
||||||
|
stcSeries.createPriceLine(buildLine(theme.info, 75, 'high'))
|
||||||
|
|
||||||
|
const stcData = strategiesValues?.Stc.stc?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.stc,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
stcSeries.setData(stcData)
|
||||||
|
stcSeries.applyOptions({
|
||||||
|
...baselineOptions,
|
||||||
|
priceFormat: {
|
||||||
|
minMove: 1,
|
||||||
|
precision: 1,
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
paneCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategiesValues?.MacdCross != null) {
|
||||||
|
const histogramSeries = chart.current.addHistogramSeries({
|
||||||
|
color: theme.accent,
|
||||||
|
title: 'MACD',
|
||||||
|
pane: paneCount,
|
||||||
|
priceFormat: {
|
||||||
|
precision: 6,
|
||||||
|
type: 'volume',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const macd = strategiesValues.MacdCross.macd?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.histogram,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var priceOptions = {
|
||||||
|
scaleMargins:{
|
||||||
|
top: 0.7,
|
||||||
|
bottom: 0.02,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
histogramSeries.priceScale().applyOptions(priceOptions)
|
||||||
|
// @ts-ignore
|
||||||
|
histogramSeries.setData(macd)
|
||||||
|
|
||||||
|
const macdSeries = chart.current.addLineSeries({
|
||||||
|
color: theme.primary,
|
||||||
|
lineWidth: 1,
|
||||||
|
priceLineVisible: false,
|
||||||
|
priceLineWidth: 1,
|
||||||
|
title: 'EMA',
|
||||||
|
pane: paneCount,
|
||||||
|
priceFormat: {
|
||||||
|
precision: 6,
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const macdData = strategiesValues.MacdCross.macd?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.macd,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
macdSeries.priceScale().applyOptions(priceOptions)
|
||||||
|
// @ts-ignore
|
||||||
|
macdSeries.setData(macdData)
|
||||||
|
|
||||||
|
const signalSeries = chart.current.addLineSeries({
|
||||||
|
color: theme.info,
|
||||||
|
lineWidth: 1,
|
||||||
|
priceLineVisible: false,
|
||||||
|
priceLineWidth: 1,
|
||||||
|
lineStyle: LineStyle.Dotted,
|
||||||
|
title: 'Signal',
|
||||||
|
pane: paneCount,
|
||||||
|
priceFormat: {
|
||||||
|
precision: 6,
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const signalData = strategiesValues.MacdCross.macd?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.signal,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
signalSeries.priceScale().applyOptions(priceOptions)
|
||||||
|
// @ts-ignore
|
||||||
|
signalSeries.setData(signalData)
|
||||||
|
|
||||||
|
paneCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategiesValues?.StochRsiTrend){
|
||||||
|
const stochRsiSeries = chart.current.addLineSeries({
|
||||||
|
...baselineOptions,
|
||||||
|
priceLineVisible: false,
|
||||||
|
title: 'Stoch RSI',
|
||||||
|
pane: paneCount,
|
||||||
|
})
|
||||||
|
|
||||||
|
const stochRsi = strategiesValues.StochRsiTrend.stochRsi?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.stochRsi,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
stochRsiSeries.setData(stochRsi)
|
||||||
|
paneCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strategiesValues?.StDev != null) {
|
||||||
|
const stDevSeries = chart.current.addLineSeries({
|
||||||
|
color: theme.primary,
|
||||||
|
lineWidth: 1,
|
||||||
|
priceLineVisible: false,
|
||||||
|
priceLineWidth: 1,
|
||||||
|
title: 'StDev',
|
||||||
|
pane: paneCount,
|
||||||
|
})
|
||||||
|
|
||||||
|
const stDev = strategiesValues.StDev.stdDev?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.stdDev,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
stDevSeries.setData(stDev)
|
||||||
|
paneCount++
|
||||||
|
|
||||||
|
const zScoreSeries = chart.current.addBaselineSeries({
|
||||||
|
...baselineOptions,
|
||||||
|
baseValue: {price: 0, type: 'price'},
|
||||||
|
title: 'ZScore',
|
||||||
|
pane: paneCount,
|
||||||
|
})
|
||||||
|
|
||||||
|
const zScore = strategiesValues.StDev.stdDev?.map((w) => {
|
||||||
|
return {
|
||||||
|
time: moment(w.date).unix(),
|
||||||
|
value: w.zScore,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
zScoreSeries.setData(zScore)
|
||||||
|
|
||||||
|
paneCount++
|
||||||
|
}
|
||||||
|
|
||||||
if (walletBalances != null) {
|
if (walletBalances != null) {
|
||||||
const walletSeries = chart.current.addBaselineSeries({
|
const walletSeries = chart.current.addBaselineSeries({
|
||||||
baseValue: {price: walletBalances[0].value, type: 'price'},
|
baseValue: {price: walletBalances[0].value, type: 'price'},
|
||||||
bottomFillColor1: 'rgba( 239, 83, 80, 0.05)',
|
pane: paneCount,
|
||||||
bottomFillColor2: 'rgba( 239, 83, 80, 0.28)',
|
title: '$',
|
||||||
bottomLineColor: 'rgba( 239, 83, 80, 1)',
|
|
||||||
pane: 1,
|
|
||||||
topFillColor1: 'rgba( 38, 166, 154, 0.28)',
|
|
||||||
topFillColor2: 'rgba( 38, 166, 154, 0.05)',
|
|
||||||
topLineColor: 'rgba( 38, 166, 154, 1)',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const walletData = walletBalances.map((w) => {
|
const walletData = walletBalances.map((w) => {
|
||||||
@@ -296,12 +569,15 @@ const TradeChart = ({
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
walletSeries.setData(walletData)
|
walletSeries.setData(walletData)
|
||||||
walletSeries.applyOptions({
|
walletSeries.applyOptions({
|
||||||
|
...baselineOptions,
|
||||||
priceFormat: {
|
priceFormat: {
|
||||||
minMove: 0.0001,
|
minMove: 0.0001,
|
||||||
precision: 4,
|
precision: 4,
|
||||||
type: 'price',
|
type: 'price',
|
||||||
},
|
},
|
||||||
|
|
||||||
})
|
})
|
||||||
|
paneCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1158,6 +1158,54 @@ export class ScenarioClient extends AuthorizedApiBase {
|
|||||||
return Promise.resolve<FileResponse>(null as any);
|
return Promise.resolve<FileResponse>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scenario_UpdateScenario(name: string | null | undefined, loopbackPeriod: number | null | undefined, strategies: string[]): Promise<FileResponse> {
|
||||||
|
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);
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
body: content_,
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/octet-stream"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.transformOptions(options_).then(transformedOptions_ => {
|
||||||
|
return this.http.fetch(url_, transformedOptions_);
|
||||||
|
}).then((_response: Response) => {
|
||||||
|
return this.processScenario_UpdateScenario(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processScenario_UpdateScenario(response: Response): Promise<FileResponse> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200 || status === 206) {
|
||||||
|
const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined;
|
||||||
|
let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined;
|
||||||
|
let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined;
|
||||||
|
if (fileName) {
|
||||||
|
fileName = decodeURIComponent(fileName);
|
||||||
|
} else {
|
||||||
|
fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined;
|
||||||
|
fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined;
|
||||||
|
}
|
||||||
|
return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; });
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<FileResponse>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
scenario_GetStrategies(): Promise<Strategy[]> {
|
scenario_GetStrategies(): Promise<Strategy[]> {
|
||||||
let url_ = this.baseUrl + "/Scenario/strategy";
|
let url_ = this.baseUrl + "/Scenario/strategy";
|
||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
@@ -1291,6 +1339,68 @@ export class ScenarioClient extends AuthorizedApiBase {
|
|||||||
}
|
}
|
||||||
return Promise.resolve<FileResponse>(null as any);
|
return Promise.resolve<FileResponse>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scenario_UpdateStrategy(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<FileResponse> {
|
||||||
|
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 (name !== undefined && name !== null)
|
||||||
|
url_ += "name=" + encodeURIComponent("" + name) + "&";
|
||||||
|
if (period !== undefined && period !== null)
|
||||||
|
url_ += "period=" + encodeURIComponent("" + period) + "&";
|
||||||
|
if (fastPeriods !== undefined && fastPeriods !== null)
|
||||||
|
url_ += "fastPeriods=" + encodeURIComponent("" + fastPeriods) + "&";
|
||||||
|
if (slowPeriods !== undefined && slowPeriods !== null)
|
||||||
|
url_ += "slowPeriods=" + encodeURIComponent("" + slowPeriods) + "&";
|
||||||
|
if (signalPeriods !== undefined && signalPeriods !== null)
|
||||||
|
url_ += "signalPeriods=" + encodeURIComponent("" + signalPeriods) + "&";
|
||||||
|
if (multiplier !== undefined && multiplier !== null)
|
||||||
|
url_ += "multiplier=" + encodeURIComponent("" + multiplier) + "&";
|
||||||
|
if (stochPeriods !== undefined && stochPeriods !== null)
|
||||||
|
url_ += "stochPeriods=" + encodeURIComponent("" + stochPeriods) + "&";
|
||||||
|
if (smoothPeriods !== undefined && smoothPeriods !== null)
|
||||||
|
url_ += "smoothPeriods=" + encodeURIComponent("" + smoothPeriods) + "&";
|
||||||
|
if (cyclePeriods !== undefined && cyclePeriods !== null)
|
||||||
|
url_ += "cyclePeriods=" + encodeURIComponent("" + cyclePeriods) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/octet-stream"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.transformOptions(options_).then(transformedOptions_ => {
|
||||||
|
return this.http.fetch(url_, transformedOptions_);
|
||||||
|
}).then((_response: Response) => {
|
||||||
|
return this.processScenario_UpdateStrategy(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processScenario_UpdateStrategy(response: Response): Promise<FileResponse> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200 || status === 206) {
|
||||||
|
const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined;
|
||||||
|
let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined;
|
||||||
|
let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined;
|
||||||
|
if (fileName) {
|
||||||
|
fileName = decodeURIComponent(fileName);
|
||||||
|
} else {
|
||||||
|
fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined;
|
||||||
|
fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined;
|
||||||
|
}
|
||||||
|
return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; });
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<FileResponse>(null as any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SettingsClient extends AuthorizedApiBase {
|
export class SettingsClient extends AuthorizedApiBase {
|
||||||
@@ -1893,6 +2003,7 @@ export interface Backtest {
|
|||||||
walletBalances: KeyValuePairOfDateTimeAndDecimal[];
|
walletBalances: KeyValuePairOfDateTimeAndDecimal[];
|
||||||
optimizedMoneyManagement: MoneyManagement;
|
optimizedMoneyManagement: MoneyManagement;
|
||||||
moneyManagement: MoneyManagement;
|
moneyManagement: MoneyManagement;
|
||||||
|
strategiesValues?: { [key in keyof typeof StrategyType]?: StrategiesResultBase; } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Ticker {
|
export enum Ticker {
|
||||||
@@ -2152,6 +2263,94 @@ export interface KeyValuePairOfDateTimeAndDecimal {
|
|||||||
value?: number;
|
value?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StrategiesResultBase {
|
||||||
|
ema?: EmaResult[] | null;
|
||||||
|
macd?: MacdResult[] | null;
|
||||||
|
rsi?: RsiResult[] | null;
|
||||||
|
stoch?: StochResult[] | null;
|
||||||
|
stochRsi?: StochRsiResult[] | null;
|
||||||
|
bollingerBands?: BollingerBandsResult[] | null;
|
||||||
|
chandelierShort?: ChandelierResult[] | null;
|
||||||
|
stc?: StcResult[] | null;
|
||||||
|
stdDev?: StdDevResult[] | null;
|
||||||
|
superTrend?: SuperTrendResult[] | null;
|
||||||
|
chandelierLong?: ChandelierResult[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResultBase {
|
||||||
|
date?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmaResult extends ResultBase {
|
||||||
|
ema?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MacdResult extends ResultBase {
|
||||||
|
macd?: number | null;
|
||||||
|
signal?: number | null;
|
||||||
|
histogram?: number | null;
|
||||||
|
fastEma?: number | null;
|
||||||
|
slowEma?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RsiResult extends ResultBase {
|
||||||
|
rsi?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Stochastic indicator results includes aliases for those who prefer the simpler K,D,J outputs. See documentation for more information. */
|
||||||
|
export interface StochResult extends ResultBase {
|
||||||
|
oscillator?: number | null;
|
||||||
|
signal?: number | null;
|
||||||
|
percentJ?: number | null;
|
||||||
|
k?: number | null;
|
||||||
|
d?: number | null;
|
||||||
|
j?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StochRsiResult extends ResultBase {
|
||||||
|
stochRsi?: number | null;
|
||||||
|
signal?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BollingerBandsResult extends ResultBase {
|
||||||
|
sma?: number | null;
|
||||||
|
upperBand?: number | null;
|
||||||
|
lowerBand?: number | null;
|
||||||
|
percentB?: number | null;
|
||||||
|
zScore?: number | null;
|
||||||
|
width?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChandelierResult extends ResultBase {
|
||||||
|
chandelierExit?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StcResult extends ResultBase {
|
||||||
|
stc?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StdDevResult extends ResultBase {
|
||||||
|
stdDev?: number | null;
|
||||||
|
mean?: number | null;
|
||||||
|
zScore?: number | null;
|
||||||
|
stdDevSma?: number | null;
|
||||||
|
"skender.Stock.Indicators.IReusableResult.Value"?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SuperTrendResult extends ResultBase {
|
||||||
|
superTrend?: number | null;
|
||||||
|
upperBand?: number | null;
|
||||||
|
lowerBand?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface StartBotRequest {
|
export interface StartBotRequest {
|
||||||
botType: BotType;
|
botType: BotType;
|
||||||
botName: string;
|
botName: string;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import type {
|
|||||||
RiskLevel,
|
RiskLevel,
|
||||||
Scenario,
|
Scenario,
|
||||||
Signal,
|
Signal,
|
||||||
|
StrategiesResultBase,
|
||||||
|
StrategyType,
|
||||||
Ticker,
|
Ticker,
|
||||||
Timeframe,
|
Timeframe,
|
||||||
TradeDirection,
|
TradeDirection,
|
||||||
@@ -144,6 +146,7 @@ export type IBotRowDetails = {
|
|||||||
candles: Candle[]
|
candles: Candle[]
|
||||||
positions: Position[]
|
positions: Position[]
|
||||||
walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null
|
walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null
|
||||||
|
strategiesValues?: { [key in keyof typeof StrategyType]?: StrategiesResultBase; } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IBacktestFormInput = {
|
export type IBacktestFormInput = {
|
||||||
|
|||||||
@@ -36,17 +36,39 @@ const themes: ThemesInterface = {
|
|||||||
'--rounded-btn': '0',
|
'--rounded-btn': '0',
|
||||||
'--tab-radius': '0',
|
'--tab-radius': '0',
|
||||||
accent: '#343232',
|
accent: '#343232',
|
||||||
'base-100': '#000000',
|
'base-100': '#0B0B0B',
|
||||||
'base-200': '#0D0D0D',
|
'base-200': '#0D0D0D',
|
||||||
'base-300': '#1A1919',
|
'base-300': '#0B0B0B',
|
||||||
error: '#ff0000',
|
error: '#FF5340',
|
||||||
info: '#0000ff',
|
info: '#B0DB43',
|
||||||
neutral: '#272626',
|
neutral: '#151515',
|
||||||
'neutral-focus': '#343232',
|
'neutral-focus': '#343232',
|
||||||
primary: '#343232',
|
primary: '#54B5F9',
|
||||||
secondary: '#343232',
|
secondary: '#a3d9fe',
|
||||||
success: '#008000',
|
success: '#08C25F',
|
||||||
warning: '#ffff00',
|
warning: '#EB6F22',
|
||||||
|
},
|
||||||
|
'[data-theme=kaigen]': {
|
||||||
|
'--animation-btn': '0',
|
||||||
|
'--animation-input': '0',
|
||||||
|
'--btn-focus-scale': '1',
|
||||||
|
'--btn-text-case': 'lowercase',
|
||||||
|
'--rounded-badge': '0',
|
||||||
|
'--rounded-box': '0',
|
||||||
|
'--rounded-btn': '0',
|
||||||
|
'--tab-radius': '0',
|
||||||
|
accent: '#343232',
|
||||||
|
'base-100': '#0B0B0B',
|
||||||
|
'base-200': '#0D0D0D',
|
||||||
|
'base-300': '#0B0B0B',
|
||||||
|
error: '#FF5340',
|
||||||
|
info: '#B0DB43',
|
||||||
|
neutral: '#151515',
|
||||||
|
'neutral-focus': '#343232',
|
||||||
|
primary: '#54B5F9',
|
||||||
|
secondary: '#a3d9fe',
|
||||||
|
success: '#08C25F',
|
||||||
|
warning: '#EB6F22',
|
||||||
},
|
},
|
||||||
|
|
||||||
'[data-theme=coffee]': {
|
'[data-theme=coffee]': {
|
||||||
@@ -61,18 +83,18 @@ const themes: ThemesInterface = {
|
|||||||
success: '#9DB787',
|
success: '#9DB787',
|
||||||
warning: '#FFD25F',
|
warning: '#FFD25F',
|
||||||
},
|
},
|
||||||
'[data-theme=cyberpunk]': {
|
// '[data-theme=cyberpunk]': {
|
||||||
'--rounded-badge': '0',
|
// '--rounded-badge': '0',
|
||||||
'--rounded-box': '0',
|
// '--rounded-box': '0',
|
||||||
'--rounded-btn': '0',
|
// '--rounded-btn': '0',
|
||||||
'--tab-radius': '0',
|
// '--tab-radius': '0',
|
||||||
accent: '#c07eec',
|
// accent: '#c07eec',
|
||||||
'base-100': '#ffee00',
|
// 'base-100': '#ffee00',
|
||||||
neutral: '#423f00',
|
// neutral: '#423f00',
|
||||||
'neutral-content': '#ffee00',
|
// 'neutral-content': '#ffee00',
|
||||||
primary: '#ff7598',
|
// primary: '#ff7598',
|
||||||
secondary: '#75d1f0',
|
// secondary: '#75d1f0',
|
||||||
},
|
// },
|
||||||
'[data-theme=lofi]': {
|
'[data-theme=lofi]': {
|
||||||
'--animation-btn': '0',
|
'--animation-btn': '0',
|
||||||
'--animation-input': '0',
|
'--animation-input': '0',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
daisyui: {
|
daisyui: {
|
||||||
themes: true,
|
themes: ['black', 'coffee', 'cyberpunk', 'lofi', 'retro', 'kaigen'],
|
||||||
},
|
},
|
||||||
plugins: [require('@tailwindcss/typography'), require('daisyui')],
|
plugins: [require('@tailwindcss/typography'), require('daisyui')],
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
Reference in New Issue
Block a user