Postgres (#30)

* Add postgres

* Migrate users

* Migrate geneticRequest

* Try to fix Concurrent call

* Fix asyncawait

* Fix async and concurrent

* Migrate backtests

* Add cache for user by address

* Fix backtest migration

* Fix not open connection

* Fix backtest command error

* Fix concurrent

* Fix all concurrency

* Migrate TradingRepo

* Fix scenarios

* Migrate statistic repo

* Save botbackup

* Add settings et moneymanagement

* Add bot postgres

* fix a bit more backups

* Fix bot model

* Fix loading backup

* Remove cache market for read positions

* Add workers to postgre

* Fix workers api

* Reduce get Accounts for workers

* Migrate synth to postgre

* Fix backtest saved

* Remove mongodb

* botservice decorrelation

* Fix tradingbot scope call

* fix tradingbot

* fix concurrent

* Fix scope for genetics

* Fix account over requesting

* Fix bundle backtest worker

* fix a lot of things

* fix tab backtest

* Remove optimized moneymanagement

* Add light signal to not use User and too much property

* Make money management lighter

* insert indicators to awaitable

* Migrate add strategies to await

* Refactor scenario and indicator retrieval to use asynchronous methods throughout the application

* add more async await

* Add services

* Fix and clean

* Fix bot a bit

* Fix bot and add message for cooldown

* Remove fees

* Add script to deploy db

* Update dfeeploy script

* fix script

* Add idempotent script and backup

* finish script migration

* Fix did user and agent name on start bot
This commit is contained in:
Oda
2025-07-27 15:42:17 +02:00
committed by GitHub
parent 361bfbf6e8
commit 422fecea7b
294 changed files with 23953 additions and 7272 deletions

View File

@@ -3,8 +3,6 @@ using System.ComponentModel.DataAnnotations;
using Exilion.TradingAtomics;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Strategies;
using Managing.Domain.Strategies.Base;
using Managing.Domain.Trades;
using Managing.Domain.Users;
@@ -17,7 +15,7 @@ public class Backtest
public Backtest(
TradingBotConfig config,
List<Position> positions,
List<Signal> signals,
List<LightSignal> signals,
List<Candle> candles = null)
{
Config = config;
@@ -47,14 +45,13 @@ public class Backtest
[Required] public decimal HodlPercentage { get; set; }
[Required] public TradingBotConfig Config { get; }
[Required] public List<Position> Positions { get; }
[Required] public List<Signal> Signals { get; }
[Required] public List<LightSignal> Signals { get; }
[Required] public List<Candle> Candles { get; set; }
[Required] public DateTime StartDate { get; set; }
[Required] public DateTime EndDate { get; set; }
[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 User User { get; set; }
[Required] public Dictionary<IndicatorType, IndicatorsResultBase> IndicatorsValues { get; set; }
[Required] public double Score { get; set; }
@@ -75,7 +72,7 @@ public class Backtest
string accountName,
string botName,
decimal initialTradingBalance,
MoneyManagement moneyManagement = null)
LightMoneyManagement moneyManagement = null)
{
return new TradingBotConfig
{
@@ -100,16 +97,16 @@ public class Backtest
/// Creates a copy of the backtest's configuration for a new backtest.
/// Useful for running similar backtests with modified parameters.
/// </summary>
/// <param name="startDate">New start date for the backtest</param>
/// <param name="endDate">New end date for the backtest</param>
/// <param name="balance">New initial balance for the backtest</param>
/// <param name="startDate">Start date for the new backtest</param>
/// <param name="endDate">End date for the new backtest</param>
/// <param name="balance">Initial balance for the new backtest</param>
/// <param name="moneyManagement">Optional money management override</param>
/// <returns>A new TradingBotConfig for backtesting</returns>
public TradingBotConfig CreateBacktestConfig(
DateTime startDate,
DateTime endDate,
decimal balance,
MoneyManagement moneyManagement = null)
LightMoneyManagement moneyManagement = null)
{
return new TradingBotConfig
{
@@ -123,10 +120,10 @@ public class Backtest
IsForBacktest = true,
CooldownPeriod = Config.CooldownPeriod,
MaxLossStreak = Config.MaxLossStreak,
MaxPositionTimeHours = Config.MaxPositionTimeHours, // Properly copy nullable value
MaxPositionTimeHours = Config.MaxPositionTimeHours,
FlipOnlyWhenInProfit = Config.FlipOnlyWhenInProfit,
FlipPosition = Config.FlipPosition,
Name = $"Backtest-{Config.ScenarioName}-{DateTime.UtcNow:yyyyMMdd-HHmmss}"
Name = Config.Name
};
}

View File

@@ -1,4 +1,3 @@
using Managing.Domain.MoneyManagements;
using static Managing.Common.Enums;
namespace Managing.Domain.Backtests;
@@ -21,7 +20,7 @@ public class BacktestScoringParams
public DateTime StartDate { get; }
public DateTime EndDate { get; }
public Timeframe Timeframe { get; }
public MoneyManagement MoneyManagement { get; }
public LightMoneyManagement MoneyManagement { get; }
public BacktestScoringParams(
double sharpeRatio,
@@ -38,7 +37,7 @@ public class BacktestScoringParams
DateTime startDate = default,
DateTime endDate = default,
Timeframe timeframe = Timeframe.OneHour,
MoneyManagement moneyManagement = null)
LightMoneyManagement moneyManagement = null)
{
SharpeRatio = sharpeRatio;
GrowthPercentage = growthPercentage;

View File

@@ -58,7 +58,6 @@ namespace Managing.Domain.Bots
{
await action();
ExecutionCount++;
await Task.Delay(Interval, CancellationToken.Token);
if (CancellationToken.IsCancellationRequested)
break;
}
@@ -72,6 +71,10 @@ namespace Managing.Domain.Bots
SentrySdk.CaptureException(ex);
Console.WriteLine(ex.Message);
}
finally
{
await Task.Delay(Interval, CancellationToken.Token);
}
}
}, CancellationToken.Token);
}
@@ -84,7 +87,7 @@ namespace Managing.Domain.Bots
public void Stop()
{
Status = BotStatus.Down;
SaveBackup();
_ = Task.Run(async () => await SaveBackup());
// CancellationToken.Cancel();
}
@@ -116,7 +119,7 @@ namespace Managing.Domain.Bots
return DateTime.UtcNow - StartupTime;
}
public abstract void SaveBackup();
public abstract Task SaveBackup();
public abstract void LoadBackup(BotBackup backup);
}
}

View File

@@ -1,4 +1,5 @@
using Managing.Domain.Users;
using Newtonsoft.Json;
using static Managing.Common.Enums;
namespace Managing.Domain.Bots;
@@ -7,7 +8,33 @@ public class BotBackup
{
public string Identifier { get; set; }
public User User { get; set; }
public string Data { get; set; }
public TradingBotBackup Data { get; set; }
public BotStatus LastStatus { get; set; }
public DateTime CreateDate { get; set; }
/// <summary>
/// Serializes the TradingBotBackup data to JSON string
/// </summary>
/// <returns>JSON string representation of the data</returns>
public string SerializeData()
{
if (Data == null) return null;
return JsonConvert.SerializeObject(Data);
}
/// <summary>
/// Deserializes JSON string to TradingBotBackup data
/// </summary>
/// <param name="jsonData">JSON string to deserialize</param>
public void DeserializeData(string jsonData)
{
if (string.IsNullOrEmpty(jsonData))
{
Data = null;
return;
}
Data = JsonConvert.DeserializeObject<TradingBotBackup>(jsonData);
}
}

View File

@@ -24,7 +24,7 @@ namespace Managing.Domain.Bots
DateTime StartupTime { get; }
string Identifier { get; set; }
void SaveBackup();
Task SaveBackup();
void LoadBackup(BotBackup backup);
}
}

View File

@@ -0,0 +1,36 @@
using Managing.Domain.Trades;
namespace Managing.Domain.Bots;
public class TradingBotBackup
{
/// <summary>
/// The complete trading bot configuration
/// </summary>
public TradingBotConfig Config { get; set; }
/// <summary>
/// Runtime state: Active signals for the bot
/// </summary>
public HashSet<LightSignal> Signals { get; set; }
/// <summary>
/// Runtime state: Open and closed positions for the bot
/// </summary>
public List<Position> Positions { get; set; }
/// <summary>
/// Runtime state: Historical wallet balances over time
/// </summary>
public Dictionary<DateTime, decimal> WalletBalances { get; set; }
/// <summary>
/// Runtime state: When the bot was started
/// </summary>
public DateTime StartupTime { get; set; }
/// <summary>
/// Runtime state: When the bot was created
/// </summary>
public DateTime CreateDate { get; set; }
}

View File

@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Risk;
using Managing.Domain.Scenarios;
using static Managing.Common.Enums;
@@ -9,7 +8,7 @@ namespace Managing.Domain.Bots;
public class TradingBotConfig
{
[Required] public string AccountName { get; set; }
[Required] public MoneyManagement MoneyManagement { get; set; }
[Required] public LightMoneyManagement MoneyManagement { get; set; }
[Required] public Ticker Ticker { get; set; }
[Required] public Timeframe Timeframe { get; set; }
[Required] public bool IsForWatchingOnly { get; set; }

View File

@@ -1,34 +1,20 @@
using Managing.Common;
using System.ComponentModel.DataAnnotations;
using Managing.Common;
using Skender.Stock.Indicators;
using System.ComponentModel.DataAnnotations;
namespace Managing.Domain.Candles
{
public class Candle : IQuote
{
[Required]
public Enums.TradingExchanges Exchange { get; set; }
[Required]
public string Ticker { get; set; }
[Required]
public DateTime OpenTime { get; set; }
[Required]
public DateTime Date { get; set; }
[Required]
public decimal Open { get; set; }
[Required]
public decimal Close { get; set; }
public decimal Volume { get; }
[Required]
public decimal High { get; set; }
[Required]
public decimal Low { get; set; }
public decimal BaseVolume { get; set; }
public decimal QuoteVolume { get; set; }
public int TradeCount { get; set; }
public decimal TakerBuyBaseVolume { get; set; }
public decimal TakerBuyQuoteVolume { get; set; }
[Required]
public Enums.Timeframe Timeframe { get; set; }
[Required] public Enums.TradingExchanges Exchange { get; set; }
[Required] public string Ticker { get; set; }
[Required] public DateTime OpenTime { get; set; }
[Required] public DateTime Date { get; set; }
[Required] public decimal Open { get; set; }
[Required] public decimal Close { get; set; }
[Required] public decimal High { get; set; }
[Required] public decimal Low { get; set; }
[Required] public Enums.Timeframe Timeframe { get; set; }
public decimal Volume { get; set; }
}
}
}

View File

@@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Exilion.TradingAtomics" Version="1.0.4" />
<PackageReference Include="Skender.Stock.Indicators" Version="2.5.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Exilion.TradingAtomics" Version="1.0.4"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="Skender.Stock.Indicators" Version="2.5.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Managing.Common\Managing.Common.csproj" />
<ProjectReference Include="..\Managing.Core\Managing.Core.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Managing.Common\Managing.Common.csproj"/>
<ProjectReference Include="..\Managing.Core\Managing.Core.csproj"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using static Managing.Common.Enums;
public class LightMoneyManagement
{
[Required] public string Name { get; set; }
[Required] public Timeframe Timeframe { get; set; }
[Required] public decimal StopLoss { get; set; }
[Required] public decimal TakeProfit { get; set; }
[Required] public decimal Leverage { get; set; }
public void FormatPercentage()
{
StopLoss /= 100;
TakeProfit /= 100;
}
}

View File

@@ -1,28 +1,9 @@
using System.ComponentModel.DataAnnotations;
using Managing.Domain.Users;
using static Managing.Common.Enums;
using Managing.Domain.Users;
namespace Managing.Domain.MoneyManagements
{
public class MoneyManagement
public class MoneyManagement : LightMoneyManagement
{
[Required]
public string Name { get; set; }
[Required]
public Timeframe Timeframe { get; set; }
[Required]
public decimal StopLoss { get; set; }
[Required]
public decimal TakeProfit { get; set; }
[Required]
public decimal Leverage { get; set; }
public User User { get; set; }
public void FormatPercentage()
{
StopLoss /= 100;
TakeProfit /= 100;
}
}
}

View File

@@ -1,18 +1,17 @@
using Managing.Domain.MoneyManagements;
using static Managing.Common.Enums;
using static Managing.Common.Enums;
namespace Managing.Domain.Shared.Helpers
{
public static class RiskHelpers
{
public static decimal GetStopLossPrice(TradeDirection direction, decimal price, MoneyManagement moneyManagement)
public static decimal GetStopLossPrice(TradeDirection direction, decimal price, LightMoneyManagement moneyManagement)
{
return direction == TradeDirection.Long ?
price -= price * moneyManagement.StopLoss :
price += price * moneyManagement.StopLoss;
}
public static decimal GetTakeProfitPrice(TradeDirection direction, decimal price, MoneyManagement moneyManagement, int count = 1)
public static decimal GetTakeProfitPrice(TradeDirection direction, decimal price, LightMoneyManagement moneyManagement, int count = 1)
{
decimal percentage = moneyManagement.TakeProfit * count;

View File

@@ -49,16 +49,16 @@ public static class TradingBox
{
private static readonly IndicatorComboConfig _defaultConfig = new();
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
HashSet<Signal> previousSignal, int? loopbackPeriod = 1)
public static LightSignal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
HashSet<LightSignal> previousSignal, int? loopbackPeriod = 1)
{
return GetSignal(newCandles, strategies, previousSignal, _defaultConfig, loopbackPeriod);
}
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
HashSet<Signal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod = 1)
public static LightSignal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
HashSet<LightSignal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod = 1)
{
var signalOnCandles = new List<Signal>();
var signalOnCandles = new List<LightSignal>();
var limitedCandles = newCandles.ToList().TakeLast(600).ToList();
foreach (var strategy in strategies)
@@ -126,13 +126,15 @@ public static class TradingBox
data.Timeframe, config);
}
public static Signal ComputeSignals(HashSet<IIndicator> strategies, HashSet<Signal> signalOnCandles, Ticker ticker,
public static LightSignal ComputeSignals(HashSet<IIndicator> strategies, HashSet<LightSignal> signalOnCandles,
Ticker ticker,
Timeframe timeframe)
{
return ComputeSignals(strategies, signalOnCandles, ticker, timeframe, _defaultConfig);
}
public static Signal ComputeSignals(HashSet<IIndicator> strategies, HashSet<Signal> signalOnCandles, Ticker ticker,
public static LightSignal ComputeSignals(HashSet<IIndicator> strategies, HashSet<LightSignal> signalOnCandles,
Ticker ticker,
Timeframe timeframe, IndicatorComboConfig config)
{
if (strategies.Count == 1)
@@ -194,7 +196,7 @@ public static class TradingBox
var lastSignal = signals.LastOrDefault() ??
trendSignals.LastOrDefault() ?? contextSignals.LastOrDefault();
return new Signal(
return new LightSignal(
ticker,
finalDirection,
averageConfidence,
@@ -208,7 +210,7 @@ public static class TradingBox
/// <summary>
/// Calculates the average confidence level from a list of signals
/// </summary>
private static Confidence CalculateAverageConfidence(List<Signal> signals)
private static Confidence CalculateAverageConfidence(List<LightSignal> signals)
{
if (!signals.Any())
{
@@ -231,7 +233,7 @@ public static class TradingBox
/// <summary>
/// Validates context strategies based on confidence levels indicating market condition quality
/// </summary>
private static bool ValidateContextStrategies(HashSet<IIndicator> allStrategies, List<Signal> contextSignals,
private static bool ValidateContextStrategies(HashSet<IIndicator> allStrategies, List<LightSignal> contextSignals,
IndicatorComboConfig config)
{
var contextStrategiesCount = allStrategies.Count(s => s.SignalType == SignalType.Context);

View File

@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Managing.Common;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies;
namespace Managing.Domain.Statistics;
@@ -22,9 +21,9 @@ public class Spotlight
public class TickerSignal
{
[Required] public Enums.Ticker Ticker { get; set; }
[Required] public List<Signal> FiveMinutes { get; set; }
[Required] public List<Signal> FifteenMinutes { get; set; }
[Required] public List<Signal> OneHour { get; set; }
[Required] public List<Signal> FourHour { get; set; }
[Required] public List<Signal> OneDay { get; set; }
[Required] public List<LightSignal> FiveMinutes { get; set; }
[Required] public List<LightSignal> FifteenMinutes { get; set; }
[Required] public List<LightSignal> OneHour { get; set; }
[Required] public List<LightSignal> FourHour { get; set; }
[Required] public List<LightSignal> OneDay { get; set; }
}

View File

@@ -9,15 +9,15 @@ namespace Managing.Domain.Strategies.Context;
public class StDevContext : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public StDevContext(string name, int period) : base(name, IndicatorType.StDev)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= Period)
{
@@ -112,7 +112,7 @@ public class StDevContext : Indicator
private void AddSignal(CandleStDev candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(
var signal = new LightSignal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
direction,
confidence,

View File

@@ -16,7 +16,7 @@ namespace Managing.Domain.Strategies
int? SignalPeriods { get; set; }
FixedSizeQueue<Candle> Candles { get; set; }
List<Signal> Run();
List<LightSignal> Run();
IndicatorsResultBase GetIndicatorValues();
void UpdateCandles(HashSet<Candle> newCandles);
string GetName();

View File

@@ -34,9 +34,9 @@ namespace Managing.Domain.Strategies
public int? CyclePeriods { get; set; }
public User User { get; set; }
public virtual List<Signal> Run()
public virtual List<LightSignal> Run()
{
return new List<Signal>();
return new List<LightSignal>();
}
public virtual IndicatorsResultBase GetIndicatorValues()

View File

@@ -0,0 +1,51 @@
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Managing.Core;
using Managing.Domain.Candles;
using static Managing.Common.Enums;
public class LightSignal : ValueObject
{
public LightSignal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date,
TradingExchanges exchange, IndicatorType indicatorType, SignalType signalType, string indicatorName)
{
Direction = direction;
Confidence = confidence;
Candle = candle;
Date = date;
Ticker = ticker;
Exchange = exchange;
Status = SignalStatus.WaitingForPosition;
IndicatorType = indicatorType;
IndicatorName = indicatorName;
SignalType = signalType;
Identifier =
$"{indicatorName}-{indicatorType}-{direction}-{ticker}-{candle?.Close.ToString(CultureInfo.InvariantCulture)}-{date:yyyyMMdd-HHmmss}";
}
[Required] public SignalStatus Status { get; set; }
[Required] public TradeDirection Direction { get; }
[Required] public Confidence Confidence { get; 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 IndicatorType IndicatorType { get; set; }
[Required] public SignalType SignalType { get; set; }
[Required] public string IndicatorName { get; set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Direction;
yield return Confidence;
yield return Date;
}
public void SetConfidence(Confidence confidence)
{
Confidence = confidence;
}
}

View File

@@ -1,14 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.Users;
using static Managing.Common.Enums;
namespace Managing.Domain.Strategies
{
public class Signal : ValueObject
public class Signal : LightSignal
{
public Signal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date,
TradingExchanges exchange, IndicatorType indicatorType, SignalType signalType, string indicatorName,
User user)
: base(ticker, direction, confidence, candle, date, exchange, indicatorType, signalType, indicatorName)
{
User = user;
}
[Required] public SignalStatus Status { get; set; }
[Required] public TradeDirection Direction { get; }
[Required] public Confidence Confidence { get; private set; }
@@ -22,37 +28,5 @@ namespace Managing.Domain.Strategies
[Required] public SignalType SignalType { get; set; }
public User User { get; set; }
[Required] public string IndicatorName { get; set; }
public Signal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date,
TradingExchanges exchange, IndicatorType indicatorType, SignalType signalType, string indicatorName,
User user = null)
{
Direction = direction;
Confidence = confidence;
Candle = candle;
Date = date;
Ticker = ticker;
Exchange = exchange;
Status = SignalStatus.WaitingForPosition;
IndicatorType = indicatorType;
User = user;
IndicatorName = indicatorName;
SignalType = signalType;
Identifier =
$"{indicatorName}-{indicatorType}-{direction}-{ticker}-{candle?.Close.ToString(CultureInfo.InvariantCulture)}-{date:yyyyMMdd-HHmmss}";
}
public void SetConfidence(Confidence confidence)
{
Confidence = confidence;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Direction;
yield return Confidence;
yield return Date;
}
}
}

View File

@@ -9,18 +9,18 @@ namespace Managing.Domain.Strategies.Signals;
public class ChandelierExitIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public ChandelierExitIndicator(string name, int period, double multiplier) : base(name,
IndicatorType.ChandelierExit)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
Multiplier = multiplier;
MinimumHistory = 1 + Period.Value;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= MinimumHistory)
{
@@ -106,7 +106,7 @@ public class ChandelierExitIndicator : Indicator
private void AddSignal(CandleChandelier candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(
var signal = new LightSignal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
direction,
confidence,

View File

@@ -9,11 +9,11 @@ namespace Managing.Domain.Strategies.Signals;
public class DualEmaCrossIndicator : EmaBaseIndicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public DualEmaCrossIndicator(string name, int fastPeriod, int slowPeriod) : base(name, IndicatorType.DualEmaCross)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
FastPeriods = fastPeriod;
SlowPeriods = slowPeriod;
MinimumHistory = Math.Max(fastPeriod, slowPeriod) * 2;
@@ -28,7 +28,7 @@ public class DualEmaCrossIndicator : EmaBaseIndicator
};
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= MinimumHistory)
{
@@ -103,7 +103,7 @@ public class DualEmaCrossIndicator : EmaBaseIndicator
private void AddSignal(CandleDualEma candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -8,11 +8,11 @@ namespace Managing.Domain.Strategies.Signals;
public class EmaCrossIndicator : EmaBaseIndicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public EmaCrossIndicator(string name, int period) : base(name, IndicatorType.EmaCross)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
}
@@ -24,7 +24,7 @@ public class EmaCrossIndicator : EmaBaseIndicator
};
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= Period)
{
@@ -67,7 +67,7 @@ public class EmaCrossIndicator : EmaBaseIndicator
private void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -16,18 +16,18 @@ namespace Managing.Domain.Strategies.Signals;
/// </summary>
public class LaggingSTC : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public LaggingSTC(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name,
IndicatorType.LaggingStc)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
FastPeriods = fastPeriods;
SlowPeriods = slowPeriods;
CyclePeriods = cyclePeriods;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= 2 * (SlowPeriods + CyclePeriods))
{
@@ -123,7 +123,7 @@ public class LaggingSTC : Indicator
private void AddSignal(CandleSct candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(
var signal = new LightSignal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
direction,
confidence,

View File

@@ -9,18 +9,18 @@ namespace Managing.Domain.Strategies.Signals;
public class MacdCrossIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public MacdCrossIndicator(string name, int fastPeriods, int slowPeriods, int signalPeriods) :
base(name, IndicatorType.MacdCross)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
FastPeriods = fastPeriods;
SlowPeriods = slowPeriods;
SignalPeriods = signalPeriods;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= 2 * (SlowPeriods + SignalPeriods))
{
@@ -104,7 +104,7 @@ public class MacdCrossIndicator : Indicator
private void AddSignal(CandleMacd candleSignal, TradeDirection direction,
Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -9,19 +9,19 @@ namespace Managing.Domain.Strategies.Signals;
public class RsiDivergenceConfirmIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public RsiDivergenceConfirmIndicator(string name, int period) : base(name, IndicatorType.RsiDivergenceConfirm)
{
Period = period;
Signals = new List<Signal>();
Signals = new List<LightSignal>();
}
/// <summary>
/// Get RSI signals
/// </summary>
/// <returns></returns>
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= Period)
{
@@ -232,7 +232,7 @@ public class RsiDivergenceConfirmIndicator : Indicator
private void AddSignal(CandleRsi candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -9,7 +9,7 @@ namespace Managing.Domain.Strategies.Signals;
public class RsiDivergenceIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public TradeDirection Direction { get; set; }
private const int UpperBand = 70;
private const int LowerBand = 30;
@@ -17,14 +17,14 @@ public class RsiDivergenceIndicator : Indicator
public RsiDivergenceIndicator(string name, int period) : base(name, IndicatorType.RsiDivergence)
{
Period = period;
Signals = new List<Signal>();
Signals = new List<LightSignal>();
}
/// <summary>
/// Get RSI signals
/// </summary>
/// <returns></returns>
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (!Period.HasValue || Candles.Count <= Period)
{
@@ -205,7 +205,7 @@ public class RsiDivergenceIndicator : Indicator
private void AddSignal(CandleRsi candleSignal, TradeDirection direction)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, Confidence.Low,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, Confidence.Low,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (Signals.Count(s => s.Identifier == signal.Identifier) < 1)

View File

@@ -9,17 +9,17 @@ namespace Managing.Domain.Strategies.Signals;
public class StcIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public StcIndicator(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, IndicatorType.Stc)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
FastPeriods = fastPeriods;
SlowPeriods = slowPeriods;
CyclePeriods = cyclePeriods;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= 2 * (SlowPeriods + CyclePeriods))
{
@@ -103,7 +103,7 @@ public class StcIndicator : Indicator
private void AddSignal(CandleSct candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(
var signal = new LightSignal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
direction,
confidence,

View File

@@ -9,17 +9,17 @@ namespace Managing.Domain.Strategies.Signals;
public class SuperTrendCrossEma : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public SuperTrendCrossEma(string name, int period, double multiplier) : base(name, IndicatorType.SuperTrendCrossEma)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
Multiplier = multiplier;
MinimumHistory = 100 + Period.Value;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
// Validate sufficient historical data for all indicators
const int emaPeriod = 50;
@@ -169,7 +169,7 @@ public class SuperTrendCrossEma : Indicator
private void AddSignal(CandleSuperTrend candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date,
candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))

View File

@@ -9,17 +9,17 @@ namespace Managing.Domain.Strategies.Signals;
public class SuperTrendIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public SuperTrendIndicator(string name, int period, double multiplier) : base(name, IndicatorType.SuperTrend)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
Multiplier = multiplier;
MinimumHistory = 100 + Period.Value;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= MinimumHistory)
{
@@ -106,7 +106,7 @@ public class SuperTrendIndicator : Indicator
private void AddSignal(CandleSuperTrend candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date,
candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))

View File

@@ -16,9 +16,9 @@ namespace Managing.Domain.Strategies.Signals
public TradeDirection Direction { get; }
public override List<Signal> Run()
public override List<LightSignal> Run()
{
var signals = new List<Signal>();
var signals = new List<LightSignal>();
if (Candles.Count <= 3)
{

View File

@@ -8,15 +8,15 @@ namespace Managing.Domain.Strategies.Trends;
public class EmaTrendIndicator : EmaBaseIndicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public EmaTrendIndicator(string name, int period) : base(name, IndicatorType.EmaTrend)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
Period = period;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= 2 * Period)
{
@@ -64,7 +64,7 @@ public class EmaTrendIndicator : EmaBaseIndicator
public void AddSignal(CandleEma candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
if (!Signals.Any(s => s.Identifier == signal.Identifier))
{

View File

@@ -9,7 +9,7 @@ namespace Managing.Domain.Strategies.Trends;
public class StochRsiTrendIndicator : Indicator
{
public List<Signal> Signals { get; set; }
public List<LightSignal> Signals { get; set; }
public StochRsiTrendIndicator(
string name,
@@ -18,14 +18,14 @@ public class StochRsiTrendIndicator : Indicator
int signalPeriod,
int smoothPeriods) : base(name, IndicatorType.StochRsiTrend)
{
Signals = new List<Signal>();
Signals = new List<LightSignal>();
StochPeriods = stochPeriod;
SignalPeriods = signalPeriod;
SmoothPeriods = smoothPeriods;
Period = period;
}
public override List<Signal> Run()
public override List<LightSignal> Run()
{
if (Candles.Count <= 10 * Period + 50)
{
@@ -100,7 +100,7 @@ public class StochRsiTrendIndicator : Indicator
private void AddSignal(CandleStochRsi candleSignal, TradeDirection direction, Confidence confidence)
{
var signal = new Signal(
var signal = new LightSignal(
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
direction,
confidence,

View File

@@ -1,5 +1,5 @@
using System.ComponentModel.DataAnnotations;
using Managing.Domain.MoneyManagements;
using System.Text.Json.Serialization;
using Managing.Domain.Users;
using static Managing.Common.Enums;
@@ -8,29 +8,37 @@ namespace Managing.Domain.Trades
public class Position
{
public Position(string identifier, string accountName, TradeDirection originDirection, Ticker ticker,
MoneyManagement moneyManagement, PositionInitiator positionInitiator, DateTime date, User user)
LightMoneyManagement moneyManagement, PositionInitiator initiator, DateTime date, User user)
{
Identifier = identifier;
AccountName = accountName;
OriginDirection = originDirection;
Ticker = ticker;
MoneyManagement = moneyManagement;
Initiator = positionInitiator;
Initiator = initiator;
Date = date;
Status = Initiator == PositionInitiator.PaperTrading ? PositionStatus.Filled : PositionStatus.New;
User = user;
}
[Required] public string AccountName { get; }
[Required] public string AccountName { get; set; }
[Required] public DateTime Date { get; set; }
[Required] public TradeDirection OriginDirection { get; }
[Required] public Ticker Ticker { get; }
[Required] public MoneyManagement MoneyManagement { get; }
[Required] public Trade Open { get; set; }
[Required] public Trade StopLoss { get; set; }
[Required] public Trade TakeProfit1 { get; set; }
public Trade TakeProfit2 { get; set; }
public ProfitAndLoss ProfitAndLoss { get; set; }
[Required] public TradeDirection OriginDirection { get; set; }
[Required] public Ticker Ticker { get; set; }
[Required] public LightMoneyManagement MoneyManagement { get; set; }
[Required] [JsonPropertyName("Open")] public Trade Open { get; set; }
[Required]
[JsonPropertyName("StopLoss")]
public Trade StopLoss { get; set; }
[Required]
[JsonPropertyName("TakeProfit1")]
public Trade TakeProfit1 { get; set; }
[JsonPropertyName("TakeProfit2")] public Trade TakeProfit2 { get; set; }
[JsonPropertyName("ProfitAndLoss")] public ProfitAndLoss ProfitAndLoss { get; set; }
[Required] public PositionStatus Status { get; set; }
public string SignalIdentifier { get; set; }
[Required] public string Identifier { get; set; }

View File

@@ -5,7 +5,7 @@ namespace Managing.Domain.Trades
{
public class Trade
{
public Trade(DateTime date, TradeDirection direction, TradeStatus status, TradeType tradeType, Ticker ticker,
public Trade(DateTime date, TradeDirection direction, TradeStatus status, TradeType tradeType, Ticker ticker,
decimal quantity, decimal price, decimal? leverage, string exchangeOrderId, string message)
{
Date = date;
@@ -21,25 +21,17 @@ namespace Managing.Domain.Trades
Fee = 0;
}
public decimal Fee { get; set; }
[Required]
public DateTime Date { get; private set; }
[Required]
public TradeDirection Direction { get; }
[Required]
public TradeStatus Status { get; private set; }
[Required]
public TradeType TradeType { get; }
[Required]
public Ticker Ticker { get; }
[Required]
public decimal Quantity { get; set; }
[Required]
public decimal Price { get; set; }
public decimal Leverage { get; }
[Required]
public string ExchangeOrderId { get; private set; }
public string Message { get; private set; }
[Required] public decimal Fee { get; set; }
[Required] public DateTime Date { get; set; }
[Required] public TradeDirection Direction { get; set; }
[Required] public TradeStatus Status { get; set; }
[Required] public TradeType TradeType { get; set; }
[Required] public Ticker Ticker { get; set; }
[Required] public decimal Quantity { get; set; }
[Required] public decimal Price { get; set; }
[Required] public decimal Leverage { get; set; }
[Required] public string ExchangeOrderId { get; set; }
[Required] public string Message { get; set; }
public void SetStatus(TradeStatus status)
{
@@ -71,4 +63,4 @@ namespace Managing.Domain.Trades
Price = Math.Round(price, precision);
}
}
}
}