Remove timeframe from strategy (#13)

This commit is contained in:
Oda
2025-02-26 17:24:59 +07:00
committed by GitHub
parent 298b666a0b
commit 4302bb8435
39 changed files with 299 additions and 288 deletions

View File

@@ -206,7 +206,7 @@ public class BotController : ControllerBase
Timeframe = item.Timeframe,
Ticker = item.Ticker,
AccountName = item.AccountName,
Scenario = item.Scenario,
Scenario = item.ScenarioName,
IsForWatchingOnly = item.IsForWatchingOnly,
BotType = item.BotType,
MoneyManagement = item.MoneyManagement

View File

@@ -46,9 +46,9 @@ public class ScenarioController : ControllerBase
/// <param name="strategies">A list of strategy names to include in the scenario.</param>
/// <returns>The created scenario.</returns>
[HttpPost]
public ActionResult<Scenario> CreateScenario(string name, List<string> strategies)
public ActionResult<Scenario> CreateScenario(string name, List<string> strategies, int? loopbackPeriod = null)
{
return Ok(_scenarioService.CreateScenario(name, strategies));
return Ok(_scenarioService.CreateScenario(name, strategies, loopbackPeriod));
}
/// <summary>
@@ -92,7 +92,6 @@ public class ScenarioController : ControllerBase
[Route("strategy")]
public ActionResult<Strategy> CreateStrategy(
StrategyType strategyType,
Timeframe timeframe,
string name,
int? period = null,
int? fastPeriods = null,
@@ -105,7 +104,6 @@ public class ScenarioController : ControllerBase
{
return Ok(_scenarioService.CreateStrategy(
strategyType,
timeframe,
name,
period,
fastPeriods,

View File

@@ -51,7 +51,7 @@ namespace Managing.Application.Tests
{
// Arrange
var scenario = new Scenario("FlippingScenario");
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 14);
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, "RsiDiv", period: 14);
scenario.AddStrategy(strategy);
var localCandles =
FileHelpers.ReadJson<List<Candle>>($"{ticker.ToString()}-{timeframe.ToString()}-candles.json");
@@ -83,7 +83,7 @@ namespace Managing.Application.Tests
{
// Arrange
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 5);
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, "RsiDiv", period: 5);
scenario.AddStrategy(strategy);
// Act
@@ -104,7 +104,7 @@ namespace Managing.Application.Tests
{
// Arrange
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, timeframe, "RsiDiv", fastPeriods: 12,
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, "RsiDiv", fastPeriods: 12,
slowPeriods: 26, signalPeriods: 9);
scenario.AddStrategy(strategy);
@@ -163,7 +163,7 @@ namespace Managing.Application.Tests
Parallel.For(periodRange[0], periodRange[1], options, i =>
{
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", period: i);
var strategy = ScenarioHelpers.BuildStrategy(strategyType, "RsiDiv", period: i);
scenario.AddStrategy(strategy);
// -0.5 to -5
@@ -272,7 +272,7 @@ namespace Managing.Application.Tests
return;
var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", fastPeriods: 12,
var strategy = ScenarioHelpers.BuildStrategy(strategyType, "RsiDiv", fastPeriods: 12,
slowPeriods: 26, signalPeriods: 9);
scenario.AddStrategy(strategy);

View File

@@ -22,7 +22,7 @@ namespace Managing.Application.Tests
{
var account = GetAccount(exchange);
// Arrange
var rsiStrategy = new RSIDivergenceStrategy("unittest", timeframe, 5);
var rsiStrategy = new RSIDivergenceStrategy("unittest", 5);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe).Result;
var resultSignal = new List<Signal>();
@@ -56,7 +56,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var rsiStrategy = new RSIDivergenceStrategy("unittest", timeframe, 5);
var rsiStrategy = new RSIDivergenceStrategy("unittest", 5);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(-50), timeframe).Result;
var resultSignal = new List<Signal>();
@@ -83,7 +83,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var rsiStrategy = new MacdCrossStrategy("unittest", timeframe, 12, 26, 9);
var rsiStrategy = new MacdCrossStrategy("unittest", 12, 26, 9);
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
var resultSignal = new List<Signal>();
@@ -110,7 +110,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var superTrendStrategy = new SuperTrendStrategy("unittest", timeframe, 10, 3);
var superTrendStrategy = new SuperTrendStrategy("unittest", 10, 3);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result;
var resultSignal = new List<Signal>();
@@ -137,7 +137,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var chandelierExitStrategy = new ChandelierExitStrategy("unittest", timeframe, 22, 3);
var chandelierExitStrategy = new ChandelierExitStrategy("unittest", 22, 3);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result;
var resultSignal = new List<Signal>();
@@ -164,7 +164,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var emaTrendSrategy = new EmaTrendStrategy("unittest", timeframe, 200);
var emaTrendSrategy = new EmaTrendStrategy("unittest", 200);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result;
var resultSignal = new List<Signal>();
@@ -192,7 +192,7 @@ namespace Managing.Application.Tests
{
// Arrange
var account = GetAccount(exchange);
var stochRsiStrategy = new StochRsiTrendStrategy("unittest", timeframe, 14, 14, 3, 1);
var stochRsiStrategy = new StochRsiTrendStrategy("unittest", 14, 14, 3, 1);
var candles = _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe).Result;
var resultSignal = new List<Signal>();

View File

@@ -7,22 +7,23 @@ namespace Managing.Application.Abstractions
public interface IScenarioService
{
IEnumerable<Scenario> GetScenarios();
Scenario CreateScenario(string name, List<string> strategies);
Scenario CreateScenario(string name, List<string> strategies, int? loopbackPeriod = 1);
IEnumerable<Strategy> GetStrategies();
bool DeleteStrategy(string name);
bool DeleteScenario(string name);
Scenario GetScenario(string name);
Strategy CreateStrategy(StrategyType type,
Timeframe timeframe,
string name,
int? period = null,
int? fastPeriods = null,
int? slowPeriods = null,
int? signalPeriods = null,
double? multiplier = null,
int? stochPeriods = null,
int? smoothPeriods = null,
int? cyclePeriods = null);
string name,
int? period = null,
int? fastPeriods = null,
int? slowPeriods = null,
int? signalPeriods = null,
double? multiplier = null,
int? stochPeriods = null,
int? smoothPeriods = null,
int? cyclePeriods = null);
bool DeleteStrategies();
bool DeleteScenarios();
}

View File

@@ -17,7 +17,7 @@ namespace Managing.Application.Abstractions
Timeframe Timeframe { get; set; }
HashSet<IStrategy> Strategies { get; set; }
Ticker Ticker { get; }
string Scenario { get; }
string ScenarioName { get; }
string AccountName { get; }
bool IsForWatchingOnly { get; set; }
MoneyManagement MoneyManagement { get; set; }
@@ -31,5 +31,6 @@ namespace Managing.Application.Abstractions
decimal GetProfitAndLoss();
decimal GetTotalFees();
void LoadStrategies(IEnumerable<IStrategy> strategies);
void LoadScenario(string scenarioName);
}
}

View File

@@ -58,7 +58,7 @@ namespace Managing.Application.Backtesting
{
var scalpingBot = _botFactory.CreateBacktestScalpingBot(account.Name, moneyManagement, ticker, "scenario",
timeframe, isForWatchingOnly);
scalpingBot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario));
scalpingBot.LoadScenario(scenario.Name);
var candles = initialCandles ?? GetCandles(account, ticker, timeframe, days);
var result = GetBacktestingResult(ticker, scenario, timeframe, scalpingBot, candles, balance, account,
moneyManagement);
@@ -88,8 +88,7 @@ namespace Managing.Application.Backtesting
{
var flippingBot = _botFactory.CreateBacktestFlippingBot(account.Name, moneyManagement, ticker, "scenario",
timeframe, false);
var strategy = ScenarioHelpers.GetStrategiesFromScenario(scenario);
flippingBot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario));
flippingBot.LoadScenario(scenario.Name);
var candles = initialCandles ?? GetCandles(account, ticker, timeframe, days);
var result = GetBacktestingResult(ticker, scenario, timeframe, flippingBot, candles, balance, account,
moneyManagement);
@@ -107,7 +106,7 @@ namespace Managing.Application.Backtesting
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
var bot = _botFactory.CreateBacktestScalpingBot(account.Name, moneyManagement, ticker, "scenario",
timeframe, false);
bot.LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario));
bot.LoadScenario(scenario.Name);
var result = GetBacktestingResult(ticker, scenario, timeframe, bot, candles, balance, account,
moneyManagement);
return result;
@@ -119,6 +118,7 @@ namespace Managing.Application.Backtesting
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
var bot = _botFactory.CreateBacktestFlippingBot(account.Name, moneyManagement, ticker, "scenario",
timeframe, false);
bot.LoadScenario(scenario.Name);
var result = GetBacktestingResult(ticker, scenario, timeframe, bot, candles, balance, account,
moneyManagement);
return result;

View File

@@ -1,8 +1,8 @@
using Managing.Application.Abstractions;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;
using Managing.Application.Abstractions.Services;
using Managing.Domain.MoneyManagements;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;
namespace Managing.Application.Bots
{
@@ -11,7 +11,7 @@ namespace Managing.Application.Bots
public FlippingBot(string accountName,
MoneyManagement moneyManagement,
string name,
string scenario,
string scenarioName,
IExchangeService exchangeService,
Ticker ticker,
ITradingService tradingService,
@@ -26,7 +26,7 @@ namespace Managing.Application.Bots
moneyManagement,
name,
ticker,
scenario,
scenarioName,
exchangeService,
logger,
tradingService,

View File

@@ -1,8 +1,8 @@
using Managing.Application.Abstractions;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;
using Managing.Application.Abstractions.Services;
using Managing.Domain.MoneyManagements;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;
namespace Managing.Application.Bots
{
@@ -11,7 +11,7 @@ namespace Managing.Application.Bots
public ScalpingBot(string accountName,
MoneyManagement moneyManagement,
string name,
string scenario,
string scenarioName,
IExchangeService exchangeService,
Ticker ticker,
ITradingService tradingService,
@@ -23,19 +23,19 @@ namespace Managing.Application.Bots
bool isForBacktest = false,
bool isForWatchingOnly = false)
: base(accountName,
moneyManagement,
name,
ticker,
scenario,
exchangeService,
logger,
tradingService,
timeframe,
accountService,
messengerService,
botService,
isForBacktest,
isForWatchingOnly)
moneyManagement,
name,
ticker,
scenarioName,
exchangeService,
logger,
tradingService,
timeframe,
accountService,
messengerService,
botService,
isForBacktest,
isForWatchingOnly)
{
BotType = BotType.ScalpingBot;
}

View File

@@ -33,7 +33,7 @@ public class TradingBot : Bot, ITradingBot
public HashSet<Signal> Signals { get; set; }
public List<Position> Positions { get; set; }
public Ticker Ticker { get; set; }
public string Scenario { get; set; }
public string ScenarioName { get; set; }
public string AccountName { get; set; }
public MoneyManagement MoneyManagement { get; set; }
public Timeframe Timeframe { get; set; }
@@ -44,6 +44,7 @@ public class TradingBot : Bot, ITradingBot
public int PreloadedCandlesCount { get; set; }
public BotType BotType { get; set; }
public decimal Fee { get; set; }
public Scenario Scenario { get; set; }
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
public TradingBot(
@@ -51,7 +52,7 @@ public class TradingBot : Bot, ITradingBot
MoneyManagement moneyManagement,
string name,
Ticker ticker,
string scenario,
string scenarioName,
IExchangeService exchangeService,
ILogger<TradingBot> logger,
ITradingService tradingService,
@@ -75,7 +76,7 @@ public class TradingBot : Bot, ITradingBot
AccountName = accountName;
MoneyManagement = moneyManagement;
Ticker = ticker;
Scenario = scenario;
ScenarioName = scenarioName;
Timeframe = timeframe;
IsForBacktest = isForBacktest;
Logger = logger;
@@ -101,7 +102,7 @@ public class TradingBot : Bot, ITradingBot
if (!IsForBacktest)
{
LoadScenario();
LoadScenario(ScenarioName);
await PreloadCandles();
await CancelAllOrders();
@@ -135,9 +136,9 @@ public class TradingBot : Bot, ITradingBot
}
}
public void LoadScenario()
public void LoadScenario(string scenarioName)
{
var scenario = TradingService.GetScenarioByName(Scenario);
var scenario = TradingService.GetScenarioByName(scenarioName);
if (scenario == null)
{
Logger.LogWarning("No scenario found for this scenario name");
@@ -145,6 +146,7 @@ public class TradingBot : Bot, ITradingBot
}
else
{
Scenario = scenario;
LoadStrategies(ScenarioHelpers.GetStrategiesFromScenario(scenario));
}
}
@@ -159,9 +161,12 @@ public class TradingBot : Bot, ITradingBot
public async Task Run()
{
Logger.LogInformation($"____________________{Name}____________________");
Logger.LogInformation(
$"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}");
if (!IsForBacktest)
{
Logger.LogInformation($"____________________{Name}____________________");
Logger.LogInformation(
$"Time : {DateTime.Now} - Server time {DateTime.Now.ToUniversalTime()} - Bot : {Name} - Type {BotType} - Ticker : {Ticker}");
}
var previousLastCandle = OptimizedCandles.LastOrDefault();
@@ -213,7 +218,7 @@ public class TradingBot : Bot, ITradingBot
private async Task UpdateSignals(FixedSizeQueue<Candle> candles)
{
var signal = TradingBox.GetSignal(candles.ToHashSet(), Strategies, Signals);
var signal = TradingBox.GetSignal(candles.ToHashSet(), Strategies, Signals, Scenario.LoopbackPeriod);
if (signal == null) return;
@@ -231,7 +236,7 @@ public class TradingBot : Bot, ITradingBot
if (IsForWatchingOnly || (ExecutionCount < 1 && !IsForBacktest))
signal.Status = SignalStatus.Expired;
var signalText = $"{Scenario} trigger a signal. Signal told you " +
var signalText = $"{ScenarioName} trigger a signal. Signal told you " +
$"to {signal.Direction} {Ticker} on {Timeframe}. The confidence in this signal is {signal.Confidence}. Identifier : {signal.Identifier}";
Logger.LogInformation(signalText);
@@ -726,7 +731,7 @@ public class TradingBot : Bot, ITradingBot
Positions = Positions,
Timeframe = Timeframe,
Ticker = Ticker,
Scenario = Scenario,
ScenarioName = ScenarioName,
AccountName = AccountName,
IsForWatchingOnly = IsForWatchingOnly,
WalletBalances = WalletBalances,
@@ -744,7 +749,7 @@ public class TradingBot : Bot, ITradingBot
MoneyManagement = data.MoneyManagement;
Timeframe = data.Timeframe;
Ticker = data.Ticker;
Scenario = data.Scenario;
ScenarioName = data.ScenarioName;
AccountName = data.AccountName;
IsForWatchingOnly = data.IsForWatchingOnly;
}
@@ -758,7 +763,7 @@ public class TradingBotBackup
public List<Position> Positions { get; set; }
public Timeframe Timeframe { get; set; }
public Ticker Ticker { get; set; }
public string Scenario { get; set; }
public string ScenarioName { get; set; }
public string AccountName { get; set; }
public bool IsForWatchingOnly { get; set; }
public Dictionary<DateTime, decimal> WalletBalances { get; set; }

View File

@@ -128,7 +128,7 @@ namespace Managing.Application.ManageBot
scalpingBotData.MoneyManagement,
backupBot.Name,
scalpingBotData.Ticker,
scalpingBotData.Scenario,
scalpingBotData.ScenarioName,
scalpingBotData.Timeframe,
scalpingBotData.IsForWatchingOnly);
botTask = Task.Run(() => ((ITradingBot)bot).Start());
@@ -140,7 +140,7 @@ namespace Managing.Application.ManageBot
flippingBotData.MoneyManagement,
backupBot.Name,
flippingBotData.Ticker,
flippingBotData.Scenario,
flippingBotData.ScenarioName,
flippingBotData.Timeframe,
flippingBotData.IsForWatchingOnly);
botTask = Task.Run(() => ((ITradingBot)bot).Start());

View File

@@ -19,9 +19,9 @@ namespace Managing.Application.Scenarios
_tradingService = tradingService;
}
public Scenario CreateScenario(string name, List<string> strategies)
public Scenario CreateScenario(string name, List<string> strategies, int? loopbackPeriod = 1)
{
var scenario = new Scenario(name);
var scenario = new Scenario(name, loopbackPeriod);
foreach (var strategy in strategies)
{
@@ -43,7 +43,6 @@ namespace Managing.Application.Scenarios
public Strategy CreateStrategy(
StrategyType type,
Timeframe timeframe,
string name,
int? period = null,
int? fastPeriods = null,
@@ -56,7 +55,6 @@ namespace Managing.Application.Scenarios
{
var strategy = ScenarioHelpers.BuildStrategy(
type,
timeframe,
name,
period,
fastPeriods,

View File

@@ -62,7 +62,7 @@ public class SettingsService : ISettingsService
SetupMoneyManagementsSeed(Timeframe.FifteenMinutes);
SetupMoneyManagementsSeed(Timeframe.OneHour);
SetupMoneyManagementsSeed(Timeframe.OneDay);
SetupScenariosSeed(Timeframe.FifteenMinutes);
SetupScenariosSeed();
}
catch (Exception ex)
{
@@ -82,30 +82,29 @@ public class SettingsService : ISettingsService
Leverage = 1,
StopLoss = 0.021m,
TakeProfit = 0.042m,
Name = $"{timeframe} Money Management"
Name = $"{timeframe}-MediumRisk",
};
await _moneyManagementService.CreateOrUpdateMoneyManagement(moneyManagement);
}
private void SetupScenariosSeed(Timeframe timeframe)
private void SetupScenariosSeed()
{
SetupMacd(timeframe);
SetupRsiDiv(timeframe);
SetupRsiDivConfirm(timeframe);
SetupSuperTrend(timeframe);
SetupChandelierExit(timeframe);
SetupStochRsiTrend(timeframe);
SetupStochSTCTrend(timeframe);
SetupEmaTrend(timeframe);
SetupEmaCross(timeframe);
SetupMacd();
SetupRsiDiv();
SetupRsiDivConfirm();
SetupSuperTrend();
SetupChandelierExit();
SetupStochRsiTrend();
SetupStochSTCTrend();
SetupEmaTrend();
SetupEmaCross();
}
private void SetupStochSTCTrend(Timeframe timeframe)
private void SetupStochSTCTrend()
{
var name = "STCTrend";
var strategy = _scenarioService.CreateStrategy(StrategyType.Stc,
timeframe,
name,
fastPeriods: 23,
slowPeriods: 50,
@@ -113,11 +112,10 @@ public class SettingsService : ISettingsService
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupMacd(Timeframe timeframe)
private void SetupMacd()
{
var name = "MacdCross";
var strategy = _scenarioService.CreateStrategy(StrategyType.MacdCross,
timeframe,
name,
fastPeriods: 12,
slowPeriods: 26,
@@ -125,53 +123,48 @@ public class SettingsService : ISettingsService
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupRsiDiv(Timeframe timeframe)
private void SetupRsiDiv()
{
var name = "RsiDiv6";
var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergence,
timeframe,
name,
period: 6);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupRsiDivConfirm(Timeframe timeframe)
private void SetupRsiDivConfirm()
{
var name = "RsiDivConfirm6";
var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergenceConfirm,
timeframe,
name,
period: 6);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupSuperTrend(Timeframe timeframe)
private void SetupSuperTrend()
{
var name = "SuperTrend";
var strategy = _scenarioService.CreateStrategy(StrategyType.SuperTrend,
timeframe,
name,
period: 10,
multiplier: 3);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupChandelierExit(Timeframe timeframe)
private void SetupChandelierExit()
{
var name = "ChandelierExit";
var strategy = _scenarioService.CreateStrategy(StrategyType.ChandelierExit,
timeframe,
name,
period: 22,
multiplier: 3);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupStochRsiTrend(Timeframe timeframe)
private void SetupStochRsiTrend()
{
var name = "StochRsiTrend";
var strategy = _scenarioService.CreateStrategy(StrategyType.StochRsiTrend,
timeframe,
name,
period: 14,
stochPeriods: 14,
@@ -180,21 +173,19 @@ public class SettingsService : ISettingsService
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupEmaTrend(Timeframe timeframe)
private void SetupEmaTrend()
{
var name = "Ema200Trend";
var strategy = _scenarioService.CreateStrategy(StrategyType.EmaTrend,
timeframe,
name,
period: 200);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });
}
private void SetupEmaCross(Timeframe timeframe)
private void SetupEmaCross()
{
var name = "Ema200Cross";
var strategy = _scenarioService.CreateStrategy(StrategyType.EmaCross,
timeframe,
name,
period: 200);
_scenarioService.CreateScenario(name, new List<string> { strategy.Name });

View File

@@ -30,7 +30,7 @@ public class RsiDiv : FlowBase
MapParameters();
var candles = JsonConvert.DeserializeObject<HashSet<Candle>>(input);
var strategy = new RSIDivergenceStrategy(Name, RsiDivParameters.Timeframe, RsiDivParameters.Period);
var strategy = new RSIDivergenceStrategy(Name, RsiDivParameters.Period);
strategy.UpdateCandles(candles);
strategy.Run();

View File

@@ -4,14 +4,17 @@ namespace Managing.Domain.Scenarios
{
public class Scenario
{
public Scenario(string name)
public Scenario(string name, int? loopbackPeriod = 1)
{
Name = name;
Strategies = new List<Strategy>();
LoopbackPeriod = loopbackPeriod;
}
public string Name { get; set; }
public List<Strategy> Strategies { get; set; }
public int? LoopbackPeriod { get; set; }
public void AddStrategy(Strategy strategy)
{
Strategies.Add(strategy);

View File

@@ -14,25 +14,25 @@ public static class ScenarioHelpers
{
IStrategy result = strategy.Type switch
{
StrategyType.StDev => new StDevContext(strategy.Name, strategy.Timeframe, strategy.Period.Value),
StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name, strategy.Timeframe,
StrategyType.StDev => new StDevContext(strategy.Name, strategy.Period.Value),
StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name,
strategy.Period.Value),
StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe,
StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name,
strategy.Period.Value),
StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, strategy.Timeframe,
StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name,
strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value),
StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe,
StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Period.Value),
StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name,
strategy.Period.Value),
StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name, strategy.Timeframe,
StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name,
strategy.Period.Value, strategy.Multiplier.Value),
StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, strategy.Timeframe,
StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name,
strategy.Period.Value, strategy.Multiplier.Value),
StrategyType.EmaTrend => new EmaTrendStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name, strategy.Timeframe,
StrategyType.EmaTrend => new EmaTrendStrategy(strategy.Name, strategy.Period.Value),
StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name,
strategy.Period.Value, strategy.StochPeriods.Value, strategy.SignalPeriods.Value,
strategy.SmoothPeriods.Value),
StrategyType.Stc => new STCStrategy(strategy.Name, strategy.Timeframe, strategy.CyclePeriods.Value,
StrategyType.Stc => new STCStrategy(strategy.Name, strategy.CyclePeriods.Value,
strategy.FastPeriods.Value, strategy.SlowPeriods.Value),
_ => throw new NotImplementedException(),
};
@@ -46,7 +46,6 @@ public static class ScenarioHelpers
public static Strategy BuildStrategy(
StrategyType type,
Timeframe timeframe,
string name,
int? period = null,
int? fastPeriods = null,
@@ -57,7 +56,7 @@ public static class ScenarioHelpers
int? smoothPeriods = null,
int? cyclePeriods = null)
{
var strategy = new Strategy(name, timeframe, type);
var strategy = new Strategy(name, type);
switch (type)
{

View File

@@ -10,7 +10,7 @@ namespace Managing.Domain.Shared.Helpers;
public static class TradingBox
{
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IStrategy> strategies,
HashSet<Signal> previousSignal)
HashSet<Signal> previousSignal, int? loopbackPeriod = 1)
{
var signalOnCandles = new HashSet<Signal>();
var limitedCandles = newCandles.ToList().TakeLast(600).ToList();
@@ -21,7 +21,9 @@ public static class TradingBox
if (signals == null || signals.Count == 0) continue;
foreach (var signal in signals.Where(s => s.Date == newCandles.Last().Date))
var candleLoopback = limitedCandles.TakeLast(loopbackPeriod ?? 1).ToList();
foreach (var signal in signals.Where(s => s.Date >= candleLoopback.FirstOrDefault()?.Date))
{
if (previousSignal.SingleOrDefault(s => s.Identifier == signal.Identifier) == null)
{
@@ -68,7 +70,6 @@ public static class TradingBox
signals.Last().Candle,
signals.Last().Date,
signals.Last().Exchange,
timeframe,
StrategyType.Composite, SignalType.Signal);
}
else if (signals.All(s => s.Direction == TradeDirection.Short) &&
@@ -81,7 +82,6 @@ public static class TradingBox
signals.Last().Candle,
signals.Last().Date,
signals.Last().Exchange,
timeframe,
StrategyType.Composite, SignalType.Signal);
}
}

View File

@@ -6,7 +6,7 @@ namespace Managing.Domain.Strategies.Base;
public abstract class EmaBaseStrategy : Strategy
{
protected EmaBaseStrategy(string name, Enums.Timeframe timeframe, Enums.StrategyType type) : base(name, timeframe, type)
protected EmaBaseStrategy(string name, Enums.StrategyType type) : base(name, type)
{
}
@@ -29,6 +29,7 @@ public abstract class EmaBaseStrategy : Strategy
});
}
}
return emaList;
}

View File

@@ -9,7 +9,8 @@ namespace Managing.Domain.Strategies;
public class ChandelierExitStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public ChandelierExitStrategy(string name, Timeframe timeframe, int period, double multiplier) : base(name, timeframe, StrategyType.ChandelierExit)
public ChandelierExitStrategy(string name, int period, double multiplier) : base(name, StrategyType.ChandelierExit)
{
Signals = new List<Signal>();
Period = period;
@@ -39,7 +40,8 @@ public class ChandelierExitStrategy : Strategy
private void GetSignals(ChandelierType chandelierType)
{
var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType).Where(s => s.ChandelierExit.HasValue).ToList();
var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType)
.Where(s => s.ChandelierExit.HasValue).ToList();
var chandelierCandle = MapChandelierToCandle(chandelier, Candles.TakeLast(MinimumHistory));
var previousCandle = chandelierCandle[0];
@@ -51,7 +53,7 @@ public class ChandelierExitStrategy : Strategy
currentCandle.Close < previousCandle.Open &&
chandelierType == ChandelierType.Short)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
// Long
@@ -60,7 +62,7 @@ public class ChandelierExitStrategy : Strategy
currentCandle.Close > currentCandle.Open &&
chandelierType == ChandelierType.Long)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
previousCandle = currentCandle;
@@ -90,7 +92,8 @@ public class ChandelierExitStrategy : Strategy
return superTrends;
}
private void AddSignal(CandleChandelier candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleChandelier candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
@@ -99,7 +102,6 @@ public class ChandelierExitStrategy : Strategy
candleSignal,
candleSignal.Date,
candleSignal.Exchange,
timeframe,
Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -10,7 +10,7 @@ public class EmaCrossStrategy : EmaBaseStrategy
{
public List<Signal> Signals { get; set; }
public EmaCrossStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.EmaCross)
public EmaCrossStrategy(string name, int period) : base(name, StrategyType.EmaCross)
{
Signals = new List<Signal>();
Period = period;
@@ -37,13 +37,13 @@ public class EmaCrossStrategy : EmaBaseStrategy
if (previousCandle.Close > (decimal)currentCandle.Ema &&
currentCandle.Close < (decimal)currentCandle.Ema)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
if (previousCandle.Close < (decimal)currentCandle.Ema &&
currentCandle.Close > (decimal)currentCandle.Ema)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
previousCandle = currentCandle;
@@ -57,10 +57,10 @@ public class EmaCrossStrategy : EmaBaseStrategy
}
}
private void AddSignal(CandleEma candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{
Signals.AddItem(signal);

View File

@@ -10,7 +10,7 @@ public class EmaTrendStrategy : EmaBaseStrategy
{
public List<Signal> Signals { get; set; }
public EmaTrendStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.EmaTrend)
public EmaTrendStrategy(string name, int period) : base(name, StrategyType.EmaTrend)
{
Signals = new List<Signal>();
Period = period;
@@ -36,11 +36,11 @@ public class EmaTrendStrategy : EmaBaseStrategy
{
if (currentCandle.Close > (decimal)currentCandle.Ema)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None);
AddSignal(currentCandle, TradeDirection.Long, Confidence.None);
}
else
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None);
AddSignal(currentCandle, TradeDirection.Short, Confidence.None);
}
previousCandle = currentCandle;
@@ -54,9 +54,10 @@ public class EmaTrendStrategy : EmaBaseStrategy
}
}
public void AddSignal(CandleEma candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
public void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{
Signals.AddItem(signal);

View File

@@ -10,8 +10,8 @@ public class MacdCrossStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public MacdCrossStrategy(string name, Timeframe timeframe, int fastPeriods, int slowPeriods, int signalPeriods) :
base(name, timeframe, StrategyType.MacdCross)
public MacdCrossStrategy(string name, int fastPeriods, int slowPeriods, int signalPeriods) :
base(name, StrategyType.MacdCross)
{
Signals = new List<Signal>();
FastPeriods = fastPeriods;
@@ -39,12 +39,12 @@ public class MacdCrossStrategy : Strategy
{
if (previousCandle.Histogram > 0 && currentCandle.Histogram < 0 && currentCandle.Macd < 0)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
if (previousCandle.Histogram < 0 && currentCandle.Histogram > 0 && currentCandle.Macd > 0)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
previousCandle = currentCandle;
@@ -82,11 +82,11 @@ public class MacdCrossStrategy : Strategy
return macdList;
}
private void AddSignal(CandleMacd candleSignal, Timeframe timeframe, TradeDirection direction,
private void AddSignal(CandleMacd candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{
Signals.AddItem(signal);

View File

@@ -10,7 +10,7 @@ public class RSIDivergenceConfirmStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public RSIDivergenceConfirmStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.RsiDivergenceConfirm)
public RSIDivergenceConfirmStrategy(string name, int period) : base(name, StrategyType.RsiDivergenceConfirm)
{
Period = period;
Signals = new List<Signal>();
@@ -88,7 +88,7 @@ public class RSIDivergenceConfirmStrategy : Strategy
// Price go down but RSI go up
if (currentCandle.Close < lowPrices.TakeLast(Period.Value).Min(p => p.Close))
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None);
AddSignal(currentCandle, TradeDirection.Long, Confidence.None);
}
}
else
@@ -163,7 +163,7 @@ public class RSIDivergenceConfirmStrategy : Strategy
// Price go up but RSI go down
if (currentCandle.Close > highPrices.TakeLast(Period.Value).Max(p => p.Close))
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None);
AddSignal(currentCandle, TradeDirection.Short, Confidence.None);
}
}
else
@@ -199,31 +199,32 @@ public class RSIDivergenceConfirmStrategy : Strategy
{
var lastCandleOnPeriod = Candles.TakeLast(Period.Value).ToList();
var signalsOnPeriod = Signals.Where(s => s.Date >= lastCandleOnPeriod[0].Date
&& s.Date < currentCandle.Date
&& s.Direction == direction
&& s.Confidence == Confidence.None
&& s.Status != SignalStatus.Expired
&& s.Status != SignalStatus.PositionOpen).ToList();
&& s.Date < currentCandle.Date
&& s.Direction == direction
&& s.Confidence == Confidence.None
&& s.Status != SignalStatus.Expired
&& s.Status != SignalStatus.PositionOpen).ToList();
foreach (var signal in signalsOnPeriod)
{
if (direction == TradeDirection.Short && currentCandle.Close < signal.Candle.Open)
{
AddSignal(currentCandle, Timeframe, direction, Confidence.High);
AddSignal(currentCandle, direction, Confidence.High);
Signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.Expired;
}
if (direction == TradeDirection.Long && currentCandle.Close > signal.Candle.Open)
{
AddSignal(currentCandle, Timeframe, direction, Confidence.High);
AddSignal(currentCandle, direction, Confidence.High);
Signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.Expired;
}
}
}
private void AddSignal(CandleRsi candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleRsi candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{
Signals.AddItem(signal);
@@ -233,7 +234,6 @@ public class RSIDivergenceConfirmStrategy : Strategy
private List<CandleRsi> MapRsiToCandle(IReadOnlyCollection<RsiResult> rsiResult,
IEnumerable<Candle> candles)
{
return candles.Select(c => new CandleRsi()
{
Close = c.Close,

View File

@@ -13,7 +13,7 @@ public class RSIDivergenceStrategy : Strategy
private const int UpperBand = 70;
private const int LowerBand = 30;
public RSIDivergenceStrategy(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.RsiDivergence)
public RSIDivergenceStrategy(string name, int period) : base(name, StrategyType.RsiDivergence)
{
Period = period;
Signals = new List<Signal>();
@@ -91,7 +91,7 @@ public class RSIDivergenceStrategy : Strategy
// Price go down but RSI go up
if (currentCandle.Close < lowPrices.TakeLast(Period.Value).Min(p => p.Close))
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long);
AddSignal(currentCandle, TradeDirection.Long);
}
}
else
@@ -164,7 +164,7 @@ public class RSIDivergenceStrategy : Strategy
// Price go up but RSI go down
if (currentCandle.Close > highPrices.TakeLast(Period.Value).Max(p => p.Close))
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short);
AddSignal(currentCandle, TradeDirection.Short);
}
}
else
@@ -194,9 +194,10 @@ public class RSIDivergenceStrategy : Strategy
}
}
private void AddSignal(CandleRsi candleSignal, Timeframe timeframe, TradeDirection direction)
private void AddSignal(CandleRsi candleSignal, TradeDirection direction)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, Confidence.Low, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, Confidence.Low,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
if (Signals.Count(s => s.Identifier == signal.Identifier) < 1)
{
@@ -216,7 +217,6 @@ public class RSIDivergenceStrategy : Strategy
private List<CandleRsi> MapRsiToCandle(IReadOnlyCollection<RsiResult> rsiResult,
IEnumerable<Candle> candles)
{
return candles.Select(c => new CandleRsi()
{
Close = c.Close,

View File

@@ -10,7 +10,7 @@ public class STCStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public STCStrategy(string name, Timeframe timeframe, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, timeframe, StrategyType.Stc)
public STCStrategy(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, StrategyType.Stc)
{
Signals = new List<Signal>();
FastPeriods = fastPeriods;
@@ -38,12 +38,12 @@ public class STCStrategy : Strategy
{
if (previousCandle.Stc > 75 && currentCandle.Stc <= 75)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
if (previousCandle.Stc < 25 && currentCandle.Stc >= 25)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
previousCandle = currentCandle;
@@ -76,10 +76,11 @@ public class STCStrategy : Strategy
});
}
}
return sctList;
}
private void AddSignal(CandleSct candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleSct candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
@@ -88,7 +89,6 @@ public class STCStrategy : Strategy
candleSignal,
candleSignal.Date,
candleSignal.Exchange,
timeframe,
Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -1,37 +1,26 @@
using Managing.Core;
using System.ComponentModel.DataAnnotations;
using Managing.Core;
using Managing.Domain.Candles;
using System.ComponentModel.DataAnnotations;
using static Managing.Common.Enums;
namespace Managing.Domain.Strategies
{
public class Signal : ValueObject
{
[Required]
public SignalStatus Status { get; set; }
[Required]
public TradeDirection Direction { get; }
[Required]
public Confidence Confidence { get; private set; }
[Required]
public Timeframe Timeframe { get; }
[Required]
public DateTime Date { get; private set; }
[Required]
public Candle Candle { get; }
[Required]
public string Identifier { get; }
[Required]
public Ticker Ticker { get; }
[Required]
public TradingExchanges Exchange { get; set; }
[Required]
public StrategyType StrategyType { get; set; }
[Required]
public SignalType SignalType { get; set; }
[Required] public SignalStatus Status { get; set; }
[Required] public TradeDirection Direction { get; }
[Required] public Confidence Confidence { get; private set; }
[Required] public Timeframe Timeframe { get; }
[Required] public DateTime Date { get; private set; }
[Required] public Candle Candle { get; }
[Required] public string Identifier { get; }
[Required] public Ticker Ticker { get; }
[Required] public TradingExchanges Exchange { get; set; }
[Required] public StrategyType StrategyType { get; set; }
[Required] public SignalType SignalType { get; set; }
public Signal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date,
TradingExchanges exchange, Timeframe timeframe, StrategyType strategyType, SignalType signalType)
TradingExchanges exchange, StrategyType strategyType, SignalType signalType)
{
Direction = direction;
Confidence = confidence;
@@ -40,10 +29,9 @@ namespace Managing.Domain.Strategies
Ticker = ticker;
Exchange = exchange;
Status = SignalStatus.WaitingForPosition;
Timeframe = timeframe;
StrategyType = strategyType;
Identifier = $"{StrategyType}-{direction}-{ticker}-{Timeframe}-{candle?.Close}-{date:yyyyMMdd-HHmmss}";
Identifier = $"{StrategyType}-{direction}-{ticker}-{candle?.Close}-{date:yyyyMMdd-HHmmss}";
SignalType = signalType;
}

View File

@@ -10,7 +10,7 @@ public class StDevContext : Strategy
{
public List<Signal> Signals { get; set; }
public StDevContext(string name, Timeframe timeframe, int period) : base(name, timeframe, StrategyType.StDev)
public StDevContext(string name, int period) : base(name, StrategyType.StDev)
{
Signals = new List<Signal>();
Period = period;
@@ -35,7 +35,7 @@ public class StDevContext : Strategy
if (lastCandle.ZScore is < 1.2 and > (-1.2))
{
AddSignal(lastCandle, Timeframe, TradeDirection.None, Confidence.Medium);
AddSignal(lastCandle, TradeDirection.None, Confidence.Medium);
}
else
{
@@ -72,10 +72,12 @@ public class StDevContext : Strategy
});
}
}
return sctList;
}
private void AddSignal(CandleStDev candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleStDev candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
@@ -84,7 +86,6 @@ public class StDevContext : Strategy
candleSignal,
candleSignal.Date,
candleSignal.Exchange,
timeframe,
Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -12,11 +12,10 @@ public class StochRsiTrendStrategy : Strategy
public StochRsiTrendStrategy(
string name,
Timeframe timeframe,
int period,
int stochPeriod,
int signalPeriod,
int smoothPeriods) : base(name, timeframe, StrategyType.StochRsiTrend)
int smoothPeriods) : base(name, StrategyType.StochRsiTrend)
{
Signals = new List<Signal>();
StochPeriods = stochPeriod;
@@ -34,7 +33,9 @@ public class StochRsiTrendStrategy : Strategy
try
{
var stochRsi = Candles.GetStochRsi(Period.Value, StochPeriods.Value, SignalPeriods.Value, SmoothPeriods.Value).RemoveWarmupPeriods().ToList();
var stochRsi = Candles
.GetStochRsi(Period.Value, StochPeriods.Value, SignalPeriods.Value, SmoothPeriods.Value)
.RemoveWarmupPeriods().ToList();
var stochRsiCandles = MapStochRsiToCandle(stochRsi, Candles.TakeLast(Period.Value));
if (stochRsi.Count == 0)
@@ -45,11 +46,11 @@ public class StochRsiTrendStrategy : Strategy
{
if (currentCandle.Signal < 20)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.None);
AddSignal(currentCandle, TradeDirection.Long, Confidence.None);
}
else if (currentCandle.Signal > 80)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.None);
AddSignal(currentCandle, TradeDirection.Short, Confidence.None);
}
previousCandle = currentCandle;
@@ -83,10 +84,11 @@ public class StochRsiTrendStrategy : Strategy
});
}
}
return emaList;
}
private void AddSignal(CandleStochRsi candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleStochRsi candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
@@ -95,7 +97,6 @@ public class StochRsiTrendStrategy : Strategy
candleSignal,
candleSignal.Date,
candleSignal.Exchange,
timeframe,
Type,
SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))

View File

@@ -8,16 +8,14 @@ namespace Managing.Domain.Strategies
{
public class Strategy : IStrategy
{
public Strategy(string name, Timeframe timeframe, StrategyType type)
public Strategy(string name, StrategyType type)
{
Name = name;
Timeframe = timeframe;
Type = type;
SignalType = ScenarioHelpers.GetSignalType(type);
}
public string Name { get; set; }
public Timeframe Timeframe { get; set; }
[JsonIgnore] public FixedSizeQueue<Candle> Candles { get; set; }
public StrategyType Type { get; set; }
public SignalType SignalType { get; set; }

View File

@@ -10,7 +10,7 @@ public class SuperTrendStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public SuperTrendStrategy(string name, Timeframe timeframe, int period, double multiplier) : base(name, timeframe, StrategyType.SuperTrend)
public SuperTrendStrategy(string name, int period, double multiplier) : base(name, StrategyType.SuperTrend)
{
Signals = new List<Signal>();
Period = period;
@@ -27,7 +27,8 @@ public class SuperTrendStrategy : Strategy
try
{
var superTrend = Candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue).ToList();
var superTrend = Candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue)
.ToList();
var superTrendCandle = MapSuperTrendToCandle(superTrend, Candles.TakeLast(MinimumHistory));
if (superTrendCandle.Count == 0)
@@ -39,13 +40,13 @@ public class SuperTrendStrategy : Strategy
// Short
if (currentCandle.Close < previousCandle.SuperTrend && previousCandle.Close > previousCandle.SuperTrend)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
// Long
if (currentCandle.Close > previousCandle.SuperTrend && previousCandle.Close < previousCandle.SuperTrend)
{
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
previousCandle = currentCandle;
@@ -84,10 +85,11 @@ public class SuperTrendStrategy : Strategy
return superTrends;
}
private void AddSignal(CandleSuperTrend candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence)
private void AddSignal(CandleSuperTrend candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date,
candleSignal.Exchange, timeframe, Type, SignalType);
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date,
candleSignal.Exchange, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{
Signals.AddItem(signal);

View File

@@ -7,8 +7,8 @@ namespace Managing.Domain.Strategies
{
public class ThreeWhiteSoldiersStrategy : Strategy
{
public ThreeWhiteSoldiersStrategy(string name, Timeframe timeframe, int period)
: base(name, timeframe, StrategyType.ThreeWhiteSoldiers)
public ThreeWhiteSoldiersStrategy(string name, int period)
: base(name, StrategyType.ThreeWhiteSoldiers)
{
Period = period;
}

View File

@@ -8,5 +8,6 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections
{
public string Name { get; set; }
public List<StrategyDto> Strategies { get; set; }
public int LoopbackPeriod { get; set; }
}
}

View File

@@ -342,7 +342,7 @@ public static class MongoMappers
internal static Signal Map(SignalDto bSignal)
{
return new Signal(ticker: bSignal.Ticker, direction: bSignal.Direction, confidence: bSignal.Confidence,
candle: Map(bSignal.Candle), date: bSignal.Date, exchange: default, timeframe: bSignal.Timeframe,
candle: Map(bSignal.Candle), date: bSignal.Date, exchange: default,
strategyType: bSignal.Type, signalType: bSignal.SignalType)
{
Status = bSignal.Status
@@ -359,6 +359,7 @@ public static class MongoMappers
{
Name = scenario.Name,
Strategies = Map(scenario.Strategies),
LoopbackPeriod = scenario.LoopbackPeriod ?? 1
};
}
@@ -372,7 +373,8 @@ public static class MongoMappers
return new Scenario(d.Name)
{
Name = d.Name,
Strategies = Map(d.Strategies).ToList()
Strategies = Map(d.Strategies).ToList(),
LoopbackPeriod = d.LoopbackPeriod > 0 ? d.LoopbackPeriod : 1
};
}
@@ -383,7 +385,7 @@ public static class MongoMappers
internal static Strategy Map(StrategyDto strategyDto)
{
return new Strategy(name: strategyDto.Name, timeframe: strategyDto.Timeframe, type: strategyDto.Type)
return new Strategy(name: strategyDto.Name, type: strategyDto.Type)
{
Period = strategyDto.Period,
FastPeriods = strategyDto.FastPeriods,
@@ -401,7 +403,6 @@ public static class MongoMappers
var dto = new StrategyDto
{
Type = strategy.Type,
Timeframe = strategy.Timeframe,
Name = strategy.Name,
SignalType = strategy.SignalType
};

View File

@@ -1,5 +1,4 @@
using Managing.Application.Abstractions.Repositories;
using Managing.Common;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies;
using Managing.Domain.Trades;
@@ -19,7 +18,6 @@ public class TradingRepository : ITradingRepository
private readonly IMongoRepository<StrategyDto> _strategyRepository;
private readonly IMongoRepository<FeeDto> _feeRepository;
public TradingRepository(
IMongoRepository<ScenarioDto> scenarioRepository,
IMongoRepository<SignalDto> signalRepository,
@@ -69,7 +67,7 @@ public class TradingRepository : ITradingRepository
return positions.Select(MongoMappers.Map);
}
public IEnumerable<Position> GetPositionsByStatus(Enums.PositionStatus positionStatus)
public IEnumerable<Position> GetPositionsByStatus(PositionStatus positionStatus)
{
var filter = Builders<PositionDto>.Filter.Eq(p => p.Status, positionStatus);
var positions = _positionRepository.FilterBy(filter);

View File

@@ -8,7 +8,6 @@ namespace Managing.Infrastructure.MongoDb.Collections
public class StrategyDto : Document
{
public StrategyType Type { get; set; }
public Timeframe Timeframe { get; set; }
public string Name { get; set; }
public int? Period { get; set; }
public int? FastPeriods { get; set; }

View File

@@ -1073,10 +1073,12 @@ export class ScenarioClient extends AuthorizedApiBase {
return Promise.resolve<Scenario[]>(null as any);
}
scenario_CreateScenario(name: string | null | undefined, strategies: string[]): Promise<Scenario> {
scenario_CreateScenario(name: string | null | undefined, loopbackPeriod: number | null | undefined, strategies: string[]): Promise<Scenario> {
let url_ = this.baseUrl + "/Scenario?";
if (name !== undefined && name !== null)
url_ += "name=" + encodeURIComponent("" + name) + "&";
if (loopbackPeriod !== undefined && loopbackPeriod !== null)
url_ += "loopbackPeriod=" + encodeURIComponent("" + loopbackPeriod) + "&";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(strategies);
@@ -1191,16 +1193,12 @@ export class ScenarioClient extends AuthorizedApiBase {
return Promise.resolve<Strategy[]>(null as any);
}
scenario_CreateStrategy(strategyType: StrategyType | undefined, timeframe: Timeframe | undefined, name: string | null | undefined, period: number | null | undefined, fastPeriods: number | null | undefined, slowPeriods: number | null | undefined, signalPeriods: number | null | undefined, multiplier: number | null | undefined, stochPeriods: number | null | undefined, smoothPeriods: number | null | undefined, cyclePeriods: number | null | undefined): Promise<Strategy> {
scenario_CreateStrategy(strategyType: StrategyType | undefined, name: string | null | undefined, period: number | null | undefined, fastPeriods: number | null | undefined, slowPeriods: number | null | undefined, signalPeriods: number | null | undefined, multiplier: number | null | undefined, stochPeriods: number | null | undefined, smoothPeriods: number | null | undefined, cyclePeriods: number | null | undefined): Promise<Strategy> {
let url_ = this.baseUrl + "/Scenario/strategy?";
if (strategyType === null)
throw new Error("The parameter 'strategyType' cannot be null.");
else if (strategyType !== undefined)
url_ += "strategyType=" + encodeURIComponent("" + strategyType) + "&";
if (timeframe === null)
throw new Error("The parameter 'timeframe' cannot be null.");
else if (timeframe !== undefined)
url_ += "timeframe=" + encodeURIComponent("" + timeframe) + "&";
if (name !== undefined && name !== null)
url_ += "name=" + encodeURIComponent("" + name) + "&";
if (period !== undefined && period !== null)
@@ -1583,7 +1581,7 @@ export class TradingClient extends AuthorizedApiBase {
let options_: RequestInit = {
body: content_,
method: "GET",
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
@@ -2206,11 +2204,11 @@ export interface Spotlight {
export interface Scenario {
name?: string | null;
strategies?: Strategy[] | null;
loopbackPeriod?: number | null;
}
export interface Strategy {
name?: string | null;
timeframe?: Timeframe;
type?: StrategyType;
signalType?: SignalType;
minimumHistory?: number;

View File

@@ -1,13 +1,30 @@
import type {
TableInstance,
UsePaginationInstanceProps,
UsePaginationState,
UseSortByInstanceProps,
} from 'react-table'
import type { Edge, Node } from 'reactflow'
import type {TableInstance, UsePaginationInstanceProps, UsePaginationState, UseSortByInstanceProps,} from 'react-table'
import type {Edge, Node} from 'reactflow'
import type {
Account,
AccountType,
Backtest,
Balance,
BotType,
Candle,
FlowOutput,
FlowType,
IFlow,
KeyValuePairOfDateTimeAndDecimal,
MoneyManagement,
Position,
RiskLevel,
Scenario,
Signal,
Ticker,
Timeframe,
TradeDirection,
TradingBot,
TradingExchanges
} from '../generated/ManagingApi'
import {FC, ReactNode} from 'react'
import type { Account, AccountType, Backtest, Balance, BotType, Candle, FlowOutput, FlowType, IFlow, KeyValuePairOfDateTimeAndDecimal, MoneyManagement, Position, RiskLevel, Scenario, Signal, Ticker, Timeframe, TradeDirection, TradingBot, TradingExchanges } from '../generated/ManagingApi'
import { ReactNode, FC } from 'react'
export type TabsType = {
label: string
index: number
@@ -156,6 +173,7 @@ export type IBotList = {
export type IScenarioFormInput = {
name: string
strategies: string[]
loopbackPeriod: number | undefined
}
export type IScenarioList = {
list: Scenario[]

View File

@@ -1,13 +1,13 @@
import React, { useEffect, useState } from 'react'
import type { SubmitHandler } from 'react-hook-form'
import { useForm } from 'react-hook-form'
import React, {useEffect, useState} from 'react'
import type {SubmitHandler} from 'react-hook-form'
import {useForm} from 'react-hook-form'
import 'react-toastify/dist/ReactToastify.css'
import useApiUrlStore from '../../app/store/apiStore'
import { Modal, Toast } from '../../components/mollecules'
import type { Scenario, Strategy } from '../../generated/ManagingApi'
import { ScenarioClient } from '../../generated/ManagingApi'
import type { IScenarioFormInput } from '../../global/type'
import {Modal, Toast} from '../../components/mollecules'
import type {Scenario, Strategy} from '../../generated/ManagingApi'
import {ScenarioClient} from '../../generated/ManagingApi'
import type {IScenarioFormInput} from '../../global/type'
import ScenarioTable from './scenarioTable'
@@ -22,7 +22,7 @@ const ScenarioList: React.FC = () => {
async function createScenario(form: IScenarioFormInput) {
const t = new Toast('Creating scenario')
await client
.scenario_CreateScenario(form.name, form.strategies)
.scenario_CreateScenario(form.name, form.loopbackPeriod, form.strategies)
.then((data: Scenario) => {
t.update('success', 'Scenario created')
setScenarios((arr) => [...arr, data])
@@ -97,6 +97,17 @@ const ScenarioList: React.FC = () => {
</select>
</div>
</div>
<div className="form-control mb-5">
<div className="input-group">
<label htmlFor="name" className="label mr-6">
Loopback period
</label>
<input
className="bg-inherit w-full max-w-xs"
{...register('loopbackPeriod')}
></input>
</div>
</div>
<div className="modal-action">
<button type="submit" className="btn">
Build

View File

@@ -1,16 +1,12 @@
import React, { useEffect, useState } from 'react'
import type { SubmitHandler } from 'react-hook-form'
import { useForm } from 'react-hook-form'
import React, {useEffect, useState} from 'react'
import type {SubmitHandler} from 'react-hook-form'
import {useForm} from 'react-hook-form'
import 'react-toastify/dist/ReactToastify.css'
import useApiUrlStore from '../../app/store/apiStore'
import { Toast } from '../../components/mollecules'
import type { Strategy } from '../../generated/ManagingApi'
import {
StrategyType,
ScenarioClient,
Timeframe,
} from '../../generated/ManagingApi'
import {Toast} from '../../components/mollecules'
import type {Strategy} from '../../generated/ManagingApi'
import {ScenarioClient, StrategyType, Timeframe,} from '../../generated/ManagingApi'
import StrategyTable from './strategyTable'
@@ -43,7 +39,6 @@ const StrategyList: React.FC = () => {
await scenarioClient
.scenario_CreateStrategy(
form.type,
form.timeframe,
form.name,
form.period,
form.fastPeriods,