* Start building with orlean

* Add missing file

* Serialize grain state

* Remove grain and proxies

* update and add plan

* Update a bit

* Fix backtest grain

* Fix backtest grain

* Clean a bit
This commit is contained in:
Oda
2025-07-30 11:03:30 +02:00
committed by GitHub
parent d281d7cd02
commit 3de8b5e00e
59 changed files with 2626 additions and 677 deletions

View File

@@ -1,17 +1,32 @@
using Managing.Domain.Users;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using Managing.Domain.Users;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Accounts;
[GenerateSerializer]
public class Account
{
[Id(0)]
[Required] public string Name { get; set; }
[Id(1)]
[Required] public TradingExchanges Exchange { get; set; }
[Id(2)]
[Required] public AccountType Type { get; set; }
[Id(3)]
public string Key { get; set; }
[Id(4)]
public string Secret { get; set; }
[Id(5)]
public User User { get; set; }
[Id(6)]
public List<Balance> Balances { get; set; }
public bool IsPrivyWallet => Type == AccountType.Privy;

View File

@@ -1,14 +1,29 @@
using Managing.Domain.Evm;
using Orleans;
namespace Managing.Domain.Accounts;
[GenerateSerializer]
public class Balance
{
[Id(0)]
public string TokenImage { get; set; }
[Id(1)]
public string TokenName { get; set; }
[Id(2)]
public decimal Amount { get; set; }
[Id(3)]
public decimal Price { get; set; }
[Id(4)]
public decimal Value { get; set; }
[Id(5)]
public string TokenAdress { get; set; }
[Id(6)]
public Chain Chain { get; set; }
}

View File

@@ -1,20 +1,26 @@
using Managing.Domain.Bots;
using Orleans;
namespace Managing.Domain.Backtests;
/// <summary>
/// Lightweight backtest class for Orleans serialization
/// Contains only the essential properties needed for backtest results
/// </summary>
[GenerateSerializer]
public class LightBacktest
{
public string Id { get; set; } = string.Empty;
public TradingBotConfig Config { get; set; } = new();
public decimal FinalPnl { get; set; }
public int WinRate { get; set; }
public decimal GrowthPercentage { get; set; }
public decimal HodlPercentage { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal? MaxDrawdown { get; set; }
public decimal Fees { get; set; }
public double? SharpeRatio { get; set; }
public double Score { get; set; }
public string ScoreMessage { get; set; } = string.Empty;
[Id(0)] public string Id { get; set; } = string.Empty;
[Id(1)] public TradingBotConfig Config { get; set; } = new();
[Id(2)] public decimal FinalPnl { get; set; }
[Id(3)] public int WinRate { get; set; }
[Id(4)] public decimal GrowthPercentage { get; set; }
[Id(5)] public decimal HodlPercentage { get; set; }
[Id(6)] public DateTime StartDate { get; set; }
[Id(7)] public DateTime EndDate { get; set; }
[Id(8)] public decimal? MaxDrawdown { get; set; }
[Id(9)] public decimal Fees { get; set; }
[Id(10)] public double? SharpeRatio { get; set; }
[Id(11)] public double Score { get; set; }
[Id(12)] public string ScoreMessage { get; set; } = string.Empty;
}

View File

@@ -1,15 +1,26 @@
using Managing.Domain.Users;
using Newtonsoft.Json;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Bots;
[GenerateSerializer]
public class BotBackup
{
[Id(0)]
public string Identifier { get; set; }
[Id(1)]
public User User { get; set; }
[Id(2)]
public TradingBotBackup Data { get; set; }
[Id(3)]
public BotStatus LastStatus { get; set; }
[Id(4)]
public DateTime CreateDate { get; set; }
/// <summary>

View File

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

View File

@@ -1,22 +1,45 @@
using System.ComponentModel.DataAnnotations;
using Managing.Domain.Risk;
using Managing.Domain.Scenarios;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Bots;
[GenerateSerializer]
public class TradingBotConfig
{
[Id(0)]
[Required] public string AccountName { get; set; }
[Id(1)]
[Required] public LightMoneyManagement MoneyManagement { get; set; }
[Id(2)]
[Required] public Ticker Ticker { get; set; }
[Id(3)]
[Required] public Timeframe Timeframe { get; set; }
[Id(4)]
[Required] public bool IsForWatchingOnly { get; set; }
[Id(5)]
[Required] public decimal BotTradingBalance { get; set; }
[Id(6)]
[Required] public bool IsForBacktest { get; set; }
[Id(7)]
[Required] public int CooldownPeriod { get; set; }
[Id(8)]
[Required] public int MaxLossStreak { get; set; }
[Id(9)]
[Required] public bool FlipPosition { get; set; }
[Id(10)]
[Required] public string Name { get; set; }
/// <summary>
@@ -24,23 +47,28 @@ public class TradingBotConfig
/// Contains all configurable parameters for Expected Utility Theory, Kelly Criterion, and probability thresholds.
/// If null, default risk management settings will be used.
/// </summary>
[Id(11)]
public RiskManagement RiskManagement { get; set; } = new();
/// <summary>
/// The scenario object containing all strategies. When provided, this takes precedence over ScenarioName.
/// The lightweight scenario object containing all strategies. When provided, this takes precedence over ScenarioName.
/// This allows running backtests without requiring scenarios to be saved in the database.
/// Orleans-friendly version without FixedSizeQueue and User properties.
/// </summary>
public Scenario Scenario { get; set; }
[Id(12)]
public LightScenario Scenario { get; set; }
/// <summary>
/// The scenario name to load from database. Only used when Scenario object is not provided.
/// </summary>
[Id(13)]
public string ScenarioName { get; set; }
/// <summary>
/// Maximum time in hours that a position can remain open before being automatically closed.
/// If null, time-based position closure is disabled.
/// </summary>
[Id(14)]
public decimal? MaxPositionTimeHours { get; set; }
/// <summary>
@@ -49,6 +77,7 @@ public class TradingBotConfig
/// If false, the position will only be closed when MaxPositionTimeHours is reached.
/// Default is false to maintain existing behavior.
/// </summary>
[Id(15)]
public bool CloseEarlyWhenProfitable { get; set; } = false;
/// <summary>
@@ -56,6 +85,7 @@ public class TradingBotConfig
/// If false, positions will be flipped regardless of profit status.
/// Default is true for safer trading.
/// </summary>
[Id(16)]
[Required]
public bool FlipOnlyWhenInProfit { get; set; } = true;
@@ -65,20 +95,24 @@ public class TradingBotConfig
/// When false, the bot operates in traditional mode without Synth predictions.
/// The actual Synth configuration is managed centrally in SynthPredictionService.
/// </summary>
[Id(17)]
public bool UseSynthApi { get; set; } = false;
/// <summary>
/// Whether to use Synth predictions for position sizing adjustments and risk assessment
/// </summary>
[Id(18)]
public bool UseForPositionSizing { get; set; } = true;
/// <summary>
/// Whether to use Synth predictions for signal filtering
/// </summary>
[Id(19)]
public bool UseForSignalFiltering { get; set; } = true;
/// <summary>
/// Whether to use Synth predictions for dynamic stop-loss/take-profit adjustments
/// </summary>
[Id(20)]
public bool UseForDynamicStopLoss { get; set; } = true;
}

View File

@@ -1,20 +1,41 @@
using System.ComponentModel.DataAnnotations;
using Managing.Common;
using Orleans;
using Skender.Stock.Indicators;
namespace Managing.Domain.Candles
{
[GenerateSerializer]
public class Candle : IQuote
{
[Id(0)]
[Required] public Enums.TradingExchanges Exchange { get; set; }
[Id(1)]
[Required] public string Ticker { get; set; }
[Id(2)]
[Required] public DateTime OpenTime { get; set; }
[Id(3)]
[Required] public DateTime Date { get; set; }
[Id(4)]
[Required] public decimal Open { get; set; }
[Id(5)]
[Required] public decimal Close { get; set; }
[Id(6)]
[Required] public decimal High { get; set; }
[Id(7)]
[Required] public decimal Low { get; set; }
[Id(8)]
[Required] public Enums.Timeframe Timeframe { get; set; }
[Id(9)]
public decimal Volume { get; set; }
}
}

View File

@@ -1,9 +1,19 @@
namespace Managing.Domain.Evm;
using Orleans;
namespace Managing.Domain.Evm;
[GenerateSerializer]
public class Chain
{
[Id(0)]
public string Id { get; set; }
[Id(1)]
public string RpcUrl { get; set; }
[Id(2)]
public string Name { get; set; }
[Id(3)]
public int ChainId { get; set; }
}

View File

@@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="Exilion.TradingAtomics" Version="1.0.4"/>
<PackageReference Include="Microsoft.Orleans.Core.Abstractions" Version="9.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="Skender.Stock.Indicators" Version="2.5.0"/>
</ItemGroup>

View File

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

View File

@@ -1,9 +1,12 @@
using Managing.Domain.Users;
using Orleans;
namespace Managing.Domain.MoneyManagements
{
[GenerateSerializer]
public class MoneyManagement : LightMoneyManagement
{
[Id(5)]
public User User { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Managing.Common;
using Orleans;
namespace Managing.Domain.Risk;
@@ -7,6 +8,7 @@ namespace Managing.Domain.Risk;
/// Risk management configuration for trading bots
/// Contains all configurable risk parameters for probabilistic analysis and position sizing
/// </summary>
[GenerateSerializer]
public class RiskManagement
{
/// <summary>
@@ -14,6 +16,7 @@ public class RiskManagement
/// Signals with SL probability above this threshold may be filtered out
/// Range: 0.05 (5%) to 0.50 (50%)
/// </summary>
[Id(0)]
[Range(0.05, 0.50)]
[Required]
public decimal AdverseProbabilityThreshold { get; set; } = 0.20m;
@@ -23,6 +26,7 @@ public class RiskManagement
/// Used for additional signal filtering and confidence assessment
/// Range: 0.10 (10%) to 0.70 (70%)
/// </summary>
[Id(1)]
[Range(0.10, 0.70)]
[Required]
public decimal FavorableProbabilityThreshold { get; set; } = 0.30m;
@@ -32,6 +36,7 @@ public class RiskManagement
/// Higher values = more risk-averse behavior in utility calculations
/// Range: 0.1 (risk-seeking) to 5.0 (highly risk-averse)
/// </summary>
[Id(2)]
[Range(0.1, 5.0)]
[Required]
public decimal RiskAversion { get; set; } = 1.0m;
@@ -41,6 +46,7 @@ public class RiskManagement
/// Trades with Kelly fraction below this threshold are considered unfavorable
/// Range: 0.5% to 10%
/// </summary>
[Id(3)]
[Range(0.005, 0.10)]
[Required]
public decimal KellyMinimumThreshold { get; set; } = 0.01m;
@@ -50,6 +56,7 @@ public class RiskManagement
/// Prevents over-allocation even when Kelly suggests higher percentages
/// Range: 5% to 50%
/// </summary>
[Id(4)]
[Range(0.05, 0.50)]
[Required]
public decimal KellyMaximumCap { get; set; } = 0.25m;
@@ -59,6 +66,7 @@ public class RiskManagement
/// Positions with higher liquidation risk may be blocked or reduced
/// Range: 5% to 30%
/// </summary>
[Id(5)]
[Range(0.05, 0.30)]
[Required]
public decimal MaxLiquidationProbability { get; set; } = 0.10m;
@@ -68,6 +76,7 @@ public class RiskManagement
/// Longer horizons provide more stable predictions but less responsive signals
/// Range: 1 hour to 168 hours (1 week)
/// </summary>
[Id(6)]
[Range(1, 168)]
[Required]
public int SignalValidationTimeHorizonHours { get; set; } = 24;
@@ -77,6 +86,7 @@ public class RiskManagement
/// Shorter horizons for more frequent risk updates on open positions
/// Range: 1 hour to 48 hours
/// </summary>
[Id(7)]
[Range(1, 48)]
[Required]
public int PositionMonitoringTimeHorizonHours { get; set; } = 6;
@@ -86,6 +96,7 @@ public class RiskManagement
/// Positions exceeding this liquidation risk will trigger warnings
/// Range: 10% to 40%
/// </summary>
[Id(8)]
[Range(0.10, 0.40)]
[Required]
public decimal PositionWarningThreshold { get; set; } = 0.20m;
@@ -95,6 +106,7 @@ public class RiskManagement
/// Positions exceeding this liquidation risk will be automatically closed
/// Range: 30% to 80%
/// </summary>
[Id(9)]
[Range(0.30, 0.80)]
[Required]
public decimal PositionAutoCloseThreshold { get; set; } = 0.50m;
@@ -104,6 +116,7 @@ public class RiskManagement
/// Values less than 1.0 implement fractional Kelly (e.g., 0.5 = half-Kelly)
/// Range: 0.1 to 1.0
/// </summary>
[Id(10)]
[Range(0.1, 1.0)]
[Required]
public decimal KellyFractionalMultiplier { get; set; } = 1.0m;
@@ -111,18 +124,21 @@ public class RiskManagement
/// <summary>
/// Risk tolerance level affecting overall risk calculations
/// </summary>
[Id(11)]
[Required]
public Enums.RiskToleranceLevel RiskTolerance { get; set; } = Enums.RiskToleranceLevel.Moderate;
/// <summary>
/// Whether to use Expected Utility Theory for decision making
/// </summary>
[Id(12)]
[Required]
public bool UseExpectedUtility { get; set; } = true;
/// <summary>
/// Whether to use Kelly Criterion for position sizing recommendations
/// </summary>
[Id(13)]
[Required]
public bool UseKellyCriterion { get; set; } = true;

View File

@@ -0,0 +1,57 @@
using Managing.Domain.Strategies;
using Orleans;
namespace Managing.Domain.Scenarios;
/// <summary>
/// Lightweight scenario class for Orleans serialization
/// Contains only the essential properties needed for backtesting
/// </summary>
[GenerateSerializer]
public class LightScenario
{
public LightScenario(string name, int? loopbackPeriod = 1)
{
Name = name;
Indicators = new List<LightIndicator>();
LoopbackPeriod = loopbackPeriod;
}
[Id(0)] public string Name { get; set; }
[Id(1)] public List<LightIndicator> Indicators { get; set; }
[Id(2)] public int? LoopbackPeriod { get; set; }
/// <summary>
/// Converts a full Scenario to a LightScenario
/// </summary>
public static LightScenario FromScenario(Scenario scenario)
{
var lightScenario = new LightScenario(scenario.Name, scenario.LoopbackPeriod)
{
Indicators = scenario.Indicators?.Select(LightIndicator.FromIndicator).ToList() ??
new List<LightIndicator>()
};
return lightScenario;
}
/// <summary>
/// Converts a LightScenario back to a full Scenario
/// </summary>
public Scenario ToScenario()
{
var scenario = new Scenario(Name, LoopbackPeriod)
{
Indicators = Indicators?.Select(li => li.ToIndicator()).ToList() ?? new List<Indicator>()
};
return scenario;
}
public void AddIndicator(LightIndicator indicator)
{
if (Indicators == null)
Indicators = new List<LightIndicator>();
Indicators.Add(indicator);
}
}

View File

@@ -1,8 +1,10 @@
using Managing.Domain.Strategies;
using Managing.Domain.Users;
using Orleans;
namespace Managing.Domain.Scenarios
{
[GenerateSerializer]
public class Scenario
{
public Scenario(string name, int? loopbackPeriod = 1)
@@ -12,9 +14,16 @@ namespace Managing.Domain.Scenarios
LoopbackPeriod = loopbackPeriod;
}
[Id(0)]
public string Name { get; set; }
[Id(1)]
public List<Indicator> Indicators { get; set; }
[Id(2)]
public int? LoopbackPeriod { get; set; }
[Id(3)]
public User User { get; set; }
public void AddIndicator(Indicator indicator)

View File

@@ -1,6 +1,4 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using Managing.Core.FixedSizedQueue;
using Managing.Core.FixedSizedQueue;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies.Base;
@@ -20,18 +18,31 @@ namespace Managing.Domain.Strategies
}
public string Name { get; set; }
[JsonIgnore] [IgnoreDataMember] public FixedSizeQueue<Candle> Candles { get; set; }
public FixedSizeQueue<Candle> Candles { get; set; }
public IndicatorType Type { get; set; }
public SignalType SignalType { get; set; }
public int MinimumHistory { get; set; }
public int? Period { get; set; }
public int? FastPeriods { get; set; }
public int? SlowPeriods { get; set; }
public int? SignalPeriods { get; set; }
public double? Multiplier { get; set; }
public int? SmoothPeriods { get; set; }
public int? StochPeriods { get; set; }
public int? CyclePeriods { get; set; }
public User User { get; set; }
public virtual List<LightSignal> Run()

View File

@@ -0,0 +1,84 @@
using Managing.Domain.Scenarios;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Strategies;
/// <summary>
/// Lightweight indicator class for Orleans serialization
/// Contains only the essential properties needed for backtesting
/// </summary>
[GenerateSerializer]
public class LightIndicator
{
public LightIndicator(string name, IndicatorType type)
{
Name = name;
Type = type;
SignalType = ScenarioHelpers.GetSignalType(type);
}
[Id(0)] public string Name { get; set; }
[Id(1)] public IndicatorType Type { get; set; }
[Id(2)] public SignalType SignalType { get; set; }
[Id(3)] public int MinimumHistory { get; set; }
[Id(4)] public int? Period { get; set; }
[Id(5)] public int? FastPeriods { get; set; }
[Id(6)] public int? SlowPeriods { get; set; }
[Id(7)] public int? SignalPeriods { get; set; }
[Id(8)] public double? Multiplier { get; set; }
[Id(9)] public int? SmoothPeriods { get; set; }
[Id(10)] public int? StochPeriods { get; set; }
[Id(11)] public int? CyclePeriods { get; set; }
/// <summary>
/// Converts a full Indicator to a LightIndicator
/// </summary>
public static LightIndicator FromIndicator(Indicator indicator)
{
return new LightIndicator(indicator.Name, indicator.Type)
{
SignalType = indicator.SignalType,
MinimumHistory = indicator.MinimumHistory,
Period = indicator.Period,
FastPeriods = indicator.FastPeriods,
SlowPeriods = indicator.SlowPeriods,
SignalPeriods = indicator.SignalPeriods,
Multiplier = indicator.Multiplier,
SmoothPeriods = indicator.SmoothPeriods,
StochPeriods = indicator.StochPeriods,
CyclePeriods = indicator.CyclePeriods
};
}
/// <summary>
/// Converts a LightIndicator back to a full Indicator
/// </summary>
public Indicator ToIndicator()
{
return new Indicator(Name, Type)
{
SignalType = SignalType,
MinimumHistory = MinimumHistory,
Period = Period,
FastPeriods = FastPeriods,
SlowPeriods = SlowPeriods,
SignalPeriods = SignalPeriods,
Multiplier = Multiplier,
SmoothPeriods = SmoothPeriods,
StochPeriods = StochPeriods,
CyclePeriods = CyclePeriods
};
}
}

View File

@@ -2,8 +2,10 @@ using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Managing.Core;
using Managing.Domain.Candles;
using Orleans;
using static Managing.Common.Enums;
[GenerateSerializer]
public class LightSignal : ValueObject
{
public LightSignal(Ticker ticker, TradeDirection direction, Confidence confidence, Candle candle, DateTime date,
@@ -24,17 +26,40 @@ public class LightSignal : ValueObject
$"{indicatorName}-{indicatorType}-{direction}-{ticker}-{candle?.Close.ToString(CultureInfo.InvariantCulture)}-{date:yyyyMMdd-HHmmss}";
}
[Id(0)]
[Required] public SignalStatus Status { get; set; }
[Id(1)]
[Required] public TradeDirection Direction { get; }
[Id(2)]
[Required] public Confidence Confidence { get; set; }
[Id(3)]
[Required] public Timeframe Timeframe { get; }
[Id(4)]
[Required] public DateTime Date { get; private set; }
[Id(5)]
[Required] public Candle Candle { get; }
[Id(6)]
[Required] public string Identifier { get; }
[Id(7)]
[Required] public Ticker Ticker { get; }
[Id(8)]
[Required] public TradingExchanges Exchange { get; set; }
[Id(9)]
[Required] public IndicatorType IndicatorType { get; set; }
[Id(10)]
[Required] public SignalType SignalType { get; set; }
[Id(11)]
[Required] public string IndicatorName { get; set; }
protected override IEnumerable<object> GetEqualityComponents()

View File

@@ -1,10 +1,12 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Managing.Domain.Users;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Trades
{
[GenerateSerializer]
public class Position
{
public Position(string identifier, string accountName, TradeDirection originDirection, Ticker ticker,
@@ -21,28 +23,53 @@ namespace Managing.Domain.Trades
User = user;
}
[Id(0)]
[Required] public string AccountName { get; set; }
[Id(1)]
[Required] public DateTime Date { get; set; }
[Id(2)]
[Required] public TradeDirection OriginDirection { get; set; }
[Id(3)]
[Required] public Ticker Ticker { get; set; }
[Id(4)]
[Required] public LightMoneyManagement MoneyManagement { get; set; }
[Id(5)]
[Required] [JsonPropertyName("Open")] public Trade Open { get; set; }
[Id(6)]
[Required]
[JsonPropertyName("StopLoss")]
public Trade StopLoss { get; set; }
[Id(7)]
[Required]
[JsonPropertyName("TakeProfit1")]
public Trade TakeProfit1 { get; set; }
[Id(8)]
[JsonPropertyName("TakeProfit2")] public Trade TakeProfit2 { get; set; }
[Id(9)]
[JsonPropertyName("ProfitAndLoss")] public ProfitAndLoss ProfitAndLoss { get; set; }
[Id(10)]
[Required] public PositionStatus Status { get; set; }
[Id(11)]
public string SignalIdentifier { get; set; }
[Id(12)]
[Required] public string Identifier { get; set; }
[Id(13)]
[Required] public PositionInitiator Initiator { get; set; }
[Id(14)]
[Required] public User User { get; set; }
public bool IsFinished()

View File

@@ -1,13 +1,18 @@
using static Managing.Common.Enums;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Trades
{
[GenerateSerializer]
public sealed class ProfitAndLoss
{
[Id(0)]
public decimal Realized { get; set; }
[Id(1)]
public decimal Net { get; set; }
[Id(2)]
public decimal AverageOpenPrice { get; private set; }
private const decimal _multiplier = 100000;

View File

@@ -1,8 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Orleans;
using static Managing.Common.Enums;
namespace Managing.Domain.Trades
{
[GenerateSerializer]
public class Trade
{
public Trade(DateTime date, TradeDirection direction, TradeStatus status, TradeType tradeType, Ticker ticker,
@@ -21,16 +23,37 @@ namespace Managing.Domain.Trades
Fee = 0;
}
[Id(0)]
[Required] public decimal Fee { get; set; }
[Id(1)]
[Required] public DateTime Date { get; set; }
[Id(2)]
[Required] public TradeDirection Direction { get; set; }
[Id(3)]
[Required] public TradeStatus Status { get; set; }
[Id(4)]
[Required] public TradeType TradeType { get; set; }
[Id(5)]
[Required] public Ticker Ticker { get; set; }
[Id(6)]
[Required] public decimal Quantity { get; set; }
[Id(7)]
[Required] public decimal Price { get; set; }
[Id(8)]
[Required] public decimal Leverage { get; set; }
[Id(9)]
[Required] public string ExchangeOrderId { get; set; }
[Id(10)]
[Required] public string Message { get; set; }
public void SetStatus(TradeStatus status)

View File

@@ -1,12 +1,23 @@
using Managing.Domain.Accounts;
using Orleans;
namespace Managing.Domain.Users;
[GenerateSerializer]
public class User
{
[Id(0)]
public string Name { get; set; }
[Id(1)]
public List<Account> Accounts { get; set; }
[Id(2)]
public string AgentName { get; set; }
[Id(3)]
public string AvatarUrl { get; set; }
[Id(4)]
public string TelegramChannel { get; set; }
}