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:
@@ -0,0 +1,916 @@
|
||||
using Exilion.TradingAtomics;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Backtests;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
using Managing.Domain.Workers;
|
||||
using Managing.Infrastructure.Databases.PostgreSql.Entities;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
using SystemJsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Managing.Infrastructure.Databases.PostgreSql;
|
||||
|
||||
public static class PostgreSqlMappers
|
||||
{
|
||||
#region Account Mappings
|
||||
|
||||
public static Account Map(AccountEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new Account
|
||||
{
|
||||
Name = entity.Name,
|
||||
Exchange = entity.Exchange,
|
||||
Type = entity.Type,
|
||||
Key = entity.Key,
|
||||
Secret = entity.Secret,
|
||||
User = entity.User != null ? Map(entity.User) : null,
|
||||
Balances = new List<Balance>() // Empty list for now, balances handled separately if needed
|
||||
};
|
||||
}
|
||||
|
||||
public static AccountEntity Map(Account account)
|
||||
{
|
||||
if (account == null) return null;
|
||||
|
||||
return new AccountEntity
|
||||
{
|
||||
Name = account.Name,
|
||||
Exchange = account.Exchange,
|
||||
Type = account.Type,
|
||||
Key = account.Key,
|
||||
Secret = account.Secret,
|
||||
User = account.User != null ? Map(account.User) : null
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<Account> Map(IEnumerable<AccountEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Account>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MoneyManagement Mappings
|
||||
|
||||
public static MoneyManagement Map(MoneyManagementEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new MoneyManagement
|
||||
{
|
||||
Name = entity.Name,
|
||||
Timeframe = entity.Timeframe,
|
||||
StopLoss = entity.StopLoss,
|
||||
TakeProfit = entity.TakeProfit,
|
||||
Leverage = entity.Leverage,
|
||||
User = entity.User != null ? Map(entity.User) : null
|
||||
};
|
||||
}
|
||||
|
||||
public static MoneyManagementEntity Map(MoneyManagement moneyManagement)
|
||||
{
|
||||
if (moneyManagement == null) return null;
|
||||
|
||||
return new MoneyManagementEntity
|
||||
{
|
||||
Name = moneyManagement.Name,
|
||||
Timeframe = moneyManagement.Timeframe,
|
||||
StopLoss = moneyManagement.StopLoss,
|
||||
TakeProfit = moneyManagement.TakeProfit,
|
||||
Leverage = moneyManagement.Leverage,
|
||||
UserName = moneyManagement.User?.Name,
|
||||
User = moneyManagement.User != null ? Map(moneyManagement.User) : null
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<MoneyManagement> Map(IEnumerable<MoneyManagementEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<MoneyManagement>();
|
||||
}
|
||||
|
||||
public static MoneyManagementEntity Map(LightMoneyManagement lightMoneyManagement)
|
||||
{
|
||||
if (lightMoneyManagement == null) return null;
|
||||
|
||||
return new MoneyManagementEntity
|
||||
{
|
||||
Name = lightMoneyManagement.Name,
|
||||
Timeframe = lightMoneyManagement.Timeframe,
|
||||
StopLoss = lightMoneyManagement.StopLoss,
|
||||
TakeProfit = lightMoneyManagement.TakeProfit,
|
||||
Leverage = lightMoneyManagement.Leverage
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region User Mappings
|
||||
|
||||
public static User Map(UserEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new User
|
||||
{
|
||||
Name = entity.Name,
|
||||
AgentName = entity.AgentName,
|
||||
AvatarUrl = entity.AvatarUrl,
|
||||
TelegramChannel = entity.TelegramChannel
|
||||
};
|
||||
}
|
||||
|
||||
public static UserEntity Map(User user)
|
||||
{
|
||||
if (user == null) return null;
|
||||
|
||||
return new UserEntity
|
||||
{
|
||||
Name = user.Name,
|
||||
AgentName = user.AgentName,
|
||||
AvatarUrl = user.AvatarUrl,
|
||||
TelegramChannel = user.TelegramChannel
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GeneticRequest Mappings
|
||||
|
||||
public static GeneticRequest Map(GeneticRequestEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
var geneticRequest = new GeneticRequest(entity.RequestId)
|
||||
{
|
||||
User = entity.User != null ? Map(entity.User) : null,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CompletedAt = entity.CompletedAt,
|
||||
Status = Enum.Parse<GeneticRequestStatus>(entity.Status),
|
||||
Ticker = entity.Ticker,
|
||||
Timeframe = entity.Timeframe,
|
||||
StartDate = entity.StartDate,
|
||||
EndDate = entity.EndDate,
|
||||
Balance = entity.Balance,
|
||||
PopulationSize = entity.PopulationSize,
|
||||
Generations = entity.Generations,
|
||||
MutationRate = entity.MutationRate,
|
||||
SelectionMethod = entity.SelectionMethod,
|
||||
CrossoverMethod = entity.CrossoverMethod,
|
||||
MutationMethod = entity.MutationMethod,
|
||||
ElitismPercentage = entity.ElitismPercentage,
|
||||
MaxTakeProfit = entity.MaxTakeProfit,
|
||||
BestFitness = entity.BestFitness,
|
||||
BestIndividual = entity.BestIndividual,
|
||||
ErrorMessage = entity.ErrorMessage,
|
||||
ProgressInfo = entity.ProgressInfo,
|
||||
BestChromosome = entity.BestChromosome,
|
||||
BestFitnessSoFar = entity.BestFitnessSoFar,
|
||||
CurrentGeneration = entity.CurrentGeneration
|
||||
};
|
||||
|
||||
// Deserialize EligibleIndicators from JSON
|
||||
if (!string.IsNullOrEmpty(entity.EligibleIndicatorsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
geneticRequest.EligibleIndicators = SystemJsonSerializer.Deserialize<List<IndicatorType>>(entity.EligibleIndicatorsJson) ?? new List<IndicatorType>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
geneticRequest.EligibleIndicators = new List<IndicatorType>();
|
||||
}
|
||||
}
|
||||
|
||||
return geneticRequest;
|
||||
}
|
||||
|
||||
public static GeneticRequestEntity Map(GeneticRequest geneticRequest)
|
||||
{
|
||||
if (geneticRequest == null) return null;
|
||||
|
||||
var entity = new GeneticRequestEntity
|
||||
{
|
||||
RequestId = geneticRequest.RequestId,
|
||||
User = geneticRequest.User != null ? Map(geneticRequest.User) : null,
|
||||
CreatedAt = geneticRequest.CreatedAt,
|
||||
CompletedAt = geneticRequest.CompletedAt,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
Status = geneticRequest.Status.ToString(),
|
||||
Ticker = geneticRequest.Ticker,
|
||||
Timeframe = geneticRequest.Timeframe,
|
||||
StartDate = geneticRequest.StartDate,
|
||||
EndDate = geneticRequest.EndDate,
|
||||
Balance = geneticRequest.Balance,
|
||||
PopulationSize = geneticRequest.PopulationSize,
|
||||
Generations = geneticRequest.Generations,
|
||||
MutationRate = geneticRequest.MutationRate,
|
||||
SelectionMethod = geneticRequest.SelectionMethod,
|
||||
CrossoverMethod = geneticRequest.CrossoverMethod,
|
||||
MutationMethod = geneticRequest.MutationMethod,
|
||||
ElitismPercentage = geneticRequest.ElitismPercentage,
|
||||
MaxTakeProfit = geneticRequest.MaxTakeProfit,
|
||||
BestFitness = geneticRequest.BestFitness,
|
||||
BestIndividual = geneticRequest.BestIndividual,
|
||||
ErrorMessage = geneticRequest.ErrorMessage,
|
||||
ProgressInfo = geneticRequest.ProgressInfo,
|
||||
BestChromosome = geneticRequest.BestChromosome,
|
||||
BestFitnessSoFar = geneticRequest.BestFitnessSoFar,
|
||||
CurrentGeneration = geneticRequest.CurrentGeneration
|
||||
};
|
||||
|
||||
// Serialize EligibleIndicators to JSON
|
||||
if (geneticRequest.EligibleIndicators != null && geneticRequest.EligibleIndicators.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
entity.EligibleIndicatorsJson = SystemJsonSerializer.Serialize(geneticRequest.EligibleIndicators);
|
||||
}
|
||||
catch
|
||||
{
|
||||
entity.EligibleIndicatorsJson = "[]";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.EligibleIndicatorsJson = "[]";
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static IEnumerable<GeneticRequest> Map(IEnumerable<GeneticRequestEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<GeneticRequest>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Backtest Mappings
|
||||
|
||||
public static Backtest Map(BacktestEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
// Deserialize JSON fields using MongoMappers for compatibility
|
||||
var config = JsonConvert.DeserializeObject<TradingBotConfig>(entity.ConfigJson);
|
||||
var positions = JsonConvert.DeserializeObject<List<Position>>(entity.PositionsJson) ?? new List<Position>();
|
||||
var signals = JsonConvert.DeserializeObject<List<LightSignal>>(entity.SignalsJson) ?? new List<LightSignal>();
|
||||
var statistics = !string.IsNullOrEmpty(entity.StatisticsJson)
|
||||
? JsonConvert.DeserializeObject<PerformanceMetrics>(entity.StatisticsJson)
|
||||
: null;
|
||||
|
||||
var backtest = new Backtest(config, positions, signals)
|
||||
{
|
||||
Id = entity.Identifier,
|
||||
FinalPnl = entity.FinalPnl,
|
||||
WinRate = entity.WinRate,
|
||||
GrowthPercentage = entity.GrowthPercentage,
|
||||
HodlPercentage = entity.HodlPercentage,
|
||||
StartDate = entity.StartDate,
|
||||
EndDate = entity.EndDate,
|
||||
User = new User { Name = entity.UserName },
|
||||
Statistics = statistics,
|
||||
Fees = entity.Fees,
|
||||
Score = entity.Score,
|
||||
ScoreMessage = entity.ScoreMessage,
|
||||
RequestId = entity.RequestId,
|
||||
Metadata = entity.Metadata
|
||||
};
|
||||
|
||||
return backtest;
|
||||
}
|
||||
|
||||
public static BacktestEntity Map(Backtest backtest)
|
||||
{
|
||||
if (backtest == null) return null;
|
||||
|
||||
return new BacktestEntity
|
||||
{
|
||||
Identifier = backtest.Id,
|
||||
RequestId = backtest.RequestId,
|
||||
FinalPnl = backtest.FinalPnl,
|
||||
WinRate = backtest.WinRate,
|
||||
GrowthPercentage = backtest.GrowthPercentage,
|
||||
HodlPercentage = backtest.HodlPercentage,
|
||||
ConfigJson = JsonConvert.SerializeObject(backtest.Config),
|
||||
PositionsJson = JsonConvert.SerializeObject(backtest.Positions),
|
||||
SignalsJson = JsonConvert.SerializeObject(backtest.Signals),
|
||||
StartDate = backtest.StartDate,
|
||||
EndDate = backtest.EndDate,
|
||||
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
|
||||
UserName = backtest.User?.Name ?? string.Empty,
|
||||
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics) : null,
|
||||
Fees = backtest.Fees,
|
||||
Score = backtest.Score,
|
||||
ScoreMessage = backtest.ScoreMessage ?? string.Empty,
|
||||
Metadata = backtest.Metadata?.ToString(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<Backtest> Map(IEnumerable<BacktestEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Backtest>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BundleBacktestRequest Mappings
|
||||
|
||||
public static BundleBacktestRequest Map(BundleBacktestRequestEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
var bundleRequest = new BundleBacktestRequest(entity.RequestId)
|
||||
{
|
||||
User = entity.User != null ? Map(entity.User) : new User { Name = entity.UserName },
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CompletedAt = entity.CompletedAt,
|
||||
Status = entity.Status,
|
||||
BacktestRequestsJson = entity.BacktestRequestsJson,
|
||||
TotalBacktests = entity.TotalBacktests,
|
||||
CompletedBacktests = entity.CompletedBacktests,
|
||||
FailedBacktests = entity.FailedBacktests,
|
||||
ErrorMessage = entity.ErrorMessage,
|
||||
ProgressInfo = entity.ProgressInfo,
|
||||
CurrentBacktest = entity.CurrentBacktest,
|
||||
EstimatedTimeRemainingSeconds = entity.EstimatedTimeRemainingSeconds,
|
||||
Name = entity.Name
|
||||
};
|
||||
|
||||
// Deserialize Results from JSON
|
||||
if (!string.IsNullOrEmpty(entity.ResultsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
bundleRequest.Results = JsonConvert.DeserializeObject<List<string>>(entity.ResultsJson) ?? new List<string>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
bundleRequest.Results = new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
return bundleRequest;
|
||||
}
|
||||
|
||||
public static BundleBacktestRequestEntity Map(BundleBacktestRequest bundleRequest)
|
||||
{
|
||||
if (bundleRequest == null) return null;
|
||||
|
||||
var entity = new BundleBacktestRequestEntity
|
||||
{
|
||||
RequestId = bundleRequest.RequestId,
|
||||
UserName = bundleRequest.User?.Name ?? string.Empty,
|
||||
UserId = null, // Will be set by the repository when saving
|
||||
CreatedAt = bundleRequest.CreatedAt,
|
||||
CompletedAt = bundleRequest.CompletedAt,
|
||||
Status = bundleRequest.Status,
|
||||
BacktestRequestsJson = bundleRequest.BacktestRequestsJson,
|
||||
TotalBacktests = bundleRequest.TotalBacktests,
|
||||
CompletedBacktests = bundleRequest.CompletedBacktests,
|
||||
FailedBacktests = bundleRequest.FailedBacktests,
|
||||
ErrorMessage = bundleRequest.ErrorMessage,
|
||||
ProgressInfo = bundleRequest.ProgressInfo,
|
||||
CurrentBacktest = bundleRequest.CurrentBacktest,
|
||||
EstimatedTimeRemainingSeconds = bundleRequest.EstimatedTimeRemainingSeconds,
|
||||
Name = bundleRequest.Name,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
// Serialize Results to JSON
|
||||
if (bundleRequest.Results != null && bundleRequest.Results.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
entity.ResultsJson = JsonConvert.SerializeObject(bundleRequest.Results);
|
||||
}
|
||||
catch
|
||||
{
|
||||
entity.ResultsJson = "[]";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.ResultsJson = "[]";
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static IEnumerable<BundleBacktestRequest> Map(IEnumerable<BundleBacktestRequestEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<BundleBacktestRequest>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Trading Mappings
|
||||
|
||||
// Scenario mappings
|
||||
public static Scenario Map(ScenarioEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new Scenario(entity.Name, entity.LoopbackPeriod)
|
||||
{
|
||||
User = entity.UserName != null ? new User { Name = entity.UserName } : null,
|
||||
Indicators = new List<Indicator>() // Will be populated separately when needed
|
||||
};
|
||||
}
|
||||
|
||||
public static ScenarioEntity Map(Scenario scenario)
|
||||
{
|
||||
if (scenario == null) return null;
|
||||
|
||||
return new ScenarioEntity
|
||||
{
|
||||
Name = scenario.Name,
|
||||
LoopbackPeriod = scenario.LoopbackPeriod ?? 1,
|
||||
UserName = scenario.User?.Name
|
||||
};
|
||||
}
|
||||
|
||||
// Indicator mappings
|
||||
public static Indicator Map(IndicatorEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new Indicator(entity.Name, entity.Type)
|
||||
{
|
||||
SignalType = entity.SignalType,
|
||||
MinimumHistory = entity.MinimumHistory,
|
||||
Period = entity.Period,
|
||||
FastPeriods = entity.FastPeriods,
|
||||
SlowPeriods = entity.SlowPeriods,
|
||||
SignalPeriods = entity.SignalPeriods,
|
||||
Multiplier = entity.Multiplier,
|
||||
SmoothPeriods = entity.SmoothPeriods,
|
||||
StochPeriods = entity.StochPeriods,
|
||||
CyclePeriods = entity.CyclePeriods,
|
||||
User = entity.UserName != null ? new User { Name = entity.UserName } : null
|
||||
};
|
||||
}
|
||||
|
||||
public static IndicatorEntity Map(Indicator indicator)
|
||||
{
|
||||
if (indicator == null) return null;
|
||||
|
||||
return new IndicatorEntity
|
||||
{
|
||||
Name = indicator.Name,
|
||||
Type = indicator.Type,
|
||||
Timeframe = Timeframe.FifteenMinutes, // Default timeframe
|
||||
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,
|
||||
UserName = indicator.User?.Name
|
||||
};
|
||||
}
|
||||
|
||||
// Signal mappings
|
||||
public static Signal Map(SignalEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
var candle = !string.IsNullOrEmpty(entity.CandleJson)
|
||||
? JsonConvert.DeserializeObject<Candle>(entity.CandleJson)
|
||||
: null;
|
||||
|
||||
return new Signal(
|
||||
entity.Ticker,
|
||||
entity.Direction,
|
||||
entity.Confidence,
|
||||
candle,
|
||||
entity.Date,
|
||||
TradingExchanges.Evm, // Default exchange
|
||||
entity.Type,
|
||||
entity.SignalType,
|
||||
entity.IndicatorName,
|
||||
entity.UserName != null ? new User { Name = entity.UserName } : null)
|
||||
{
|
||||
Status = entity.Status
|
||||
};
|
||||
}
|
||||
|
||||
public static SignalEntity Map(Signal signal)
|
||||
{
|
||||
if (signal == null) return null;
|
||||
|
||||
return new SignalEntity
|
||||
{
|
||||
Identifier = signal.Identifier,
|
||||
Direction = signal.Direction,
|
||||
Confidence = signal.Confidence,
|
||||
Date = signal.Date,
|
||||
Ticker = signal.Ticker,
|
||||
Status = signal.Status,
|
||||
Timeframe = signal.Timeframe,
|
||||
Type = signal.IndicatorType,
|
||||
SignalType = signal.SignalType,
|
||||
IndicatorName = signal.IndicatorName,
|
||||
UserName = signal.User?.Name,
|
||||
CandleJson = signal.Candle != null ? JsonConvert.SerializeObject(signal.Candle) : null
|
||||
};
|
||||
}
|
||||
|
||||
// Position mappings
|
||||
public static Position Map(PositionEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
// Deserialize money management
|
||||
var moneyManagement = new MoneyManagement(); // Default money management
|
||||
if (!string.IsNullOrEmpty(entity.MoneyManagementJson))
|
||||
{
|
||||
moneyManagement = JsonConvert.DeserializeObject<MoneyManagement>(entity.MoneyManagementJson) ?? new MoneyManagement();
|
||||
}
|
||||
|
||||
var position = new Position(
|
||||
entity.Identifier,
|
||||
entity.AccountName,
|
||||
entity.OriginDirection,
|
||||
entity.Ticker,
|
||||
moneyManagement,
|
||||
entity.Initiator,
|
||||
entity.Date,
|
||||
entity.UserName != null ? new User { Name = entity.UserName } : null)
|
||||
{
|
||||
Status = entity.Status,
|
||||
SignalIdentifier = entity.SignalIdentifier
|
||||
};
|
||||
|
||||
// Set ProfitAndLoss with proper type
|
||||
position.ProfitAndLoss = new ProfitAndLoss { Realized = entity.ProfitAndLoss };
|
||||
|
||||
// Map related trades
|
||||
if (entity.OpenTrade != null)
|
||||
position.Open = Map(entity.OpenTrade);
|
||||
if (entity.StopLossTrade != null)
|
||||
position.StopLoss = Map(entity.StopLossTrade);
|
||||
if (entity.TakeProfit1Trade != null)
|
||||
position.TakeProfit1 = Map(entity.TakeProfit1Trade);
|
||||
if (entity.TakeProfit2Trade != null)
|
||||
position.TakeProfit2 = Map(entity.TakeProfit2Trade);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
public static PositionEntity Map(Position position)
|
||||
{
|
||||
if (position == null) return null;
|
||||
|
||||
return new PositionEntity
|
||||
{
|
||||
Identifier = position.Identifier,
|
||||
Date = position.Date,
|
||||
ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0,
|
||||
OriginDirection = position.OriginDirection,
|
||||
Status = position.Status,
|
||||
Ticker = position.Ticker,
|
||||
Initiator = position.Initiator,
|
||||
SignalIdentifier = position.SignalIdentifier,
|
||||
AccountName = position.AccountName,
|
||||
UserName = position.User?.Name,
|
||||
MoneyManagementJson = position.MoneyManagement != null ? JsonConvert.SerializeObject(position.MoneyManagement) : null
|
||||
};
|
||||
}
|
||||
|
||||
// Trade mappings
|
||||
public static Trade Map(TradeEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new Trade(
|
||||
entity.Date,
|
||||
entity.Direction,
|
||||
entity.Status,
|
||||
entity.TradeType,
|
||||
entity.Ticker,
|
||||
entity.Quantity,
|
||||
entity.Price,
|
||||
entity.Leverage,
|
||||
entity.ExchangeOrderId,
|
||||
entity.Message)
|
||||
{
|
||||
Fee = entity.Fee
|
||||
};
|
||||
}
|
||||
|
||||
public static TradeEntity Map(Trade trade)
|
||||
{
|
||||
if (trade == null) return null;
|
||||
|
||||
return new TradeEntity
|
||||
{
|
||||
Date = trade.Date,
|
||||
Direction = trade.Direction,
|
||||
Status = trade.Status,
|
||||
TradeType = trade.TradeType,
|
||||
Ticker = trade.Ticker,
|
||||
Fee = trade.Fee,
|
||||
Quantity = trade.Quantity,
|
||||
Price = trade.Price,
|
||||
Leverage = trade.Leverage,
|
||||
ExchangeOrderId = trade.ExchangeOrderId,
|
||||
Message = trade.Message
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Collection mappings
|
||||
public static IEnumerable<Scenario> Map(IEnumerable<ScenarioEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Scenario>();
|
||||
}
|
||||
|
||||
public static IEnumerable<Indicator> Map(IEnumerable<IndicatorEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Indicator>();
|
||||
}
|
||||
|
||||
public static IEnumerable<Signal> Map(IEnumerable<SignalEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Signal>();
|
||||
}
|
||||
|
||||
public static IEnumerable<Position> Map(IEnumerable<PositionEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Position>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bot Mappings
|
||||
|
||||
// BotBackup mappings
|
||||
public static BotBackup Map(BotBackupEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
var botBackup = new BotBackup
|
||||
{
|
||||
Identifier = entity.Identifier,
|
||||
User = entity.User != null ? Map(entity.User) : null,
|
||||
LastStatus = entity.LastStatus,
|
||||
CreateDate = entity.CreateDate
|
||||
};
|
||||
|
||||
// Deserialize the JSON data using the helper method
|
||||
botBackup.DeserializeData(entity.Data);
|
||||
|
||||
return botBackup;
|
||||
}
|
||||
|
||||
public static BotBackupEntity Map(BotBackup botBackup)
|
||||
{
|
||||
if (botBackup == null) return null;
|
||||
|
||||
return new BotBackupEntity
|
||||
{
|
||||
Identifier = botBackup.Identifier,
|
||||
UserName = botBackup.User?.Name,
|
||||
User = botBackup.User != null ? Map(botBackup.User) : null,
|
||||
Data = botBackup.SerializeData(), // Serialize the data using the helper method
|
||||
LastStatus = botBackup.LastStatus,
|
||||
CreateDate = botBackup.CreateDate,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<BotBackup> Map(IEnumerable<BotBackupEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<BotBackup>();
|
||||
}
|
||||
|
||||
public static IEnumerable<BotBackupEntity> Map(IEnumerable<BotBackup> botBackups)
|
||||
{
|
||||
return botBackups?.Select(Map) ?? Enumerable.Empty<BotBackupEntity>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Statistics Mappings
|
||||
|
||||
// TopVolumeTicker mappings
|
||||
public static TopVolumeTicker Map(TopVolumeTickerEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new TopVolumeTicker
|
||||
{
|
||||
Ticker = entity.Ticker,
|
||||
Date = entity.Date,
|
||||
Volume = entity.Volume,
|
||||
Rank = entity.Rank,
|
||||
Exchange = entity.Exchange
|
||||
};
|
||||
}
|
||||
|
||||
public static TopVolumeTickerEntity Map(TopVolumeTicker topVolumeTicker)
|
||||
{
|
||||
if (topVolumeTicker == null) return null;
|
||||
|
||||
return new TopVolumeTickerEntity
|
||||
{
|
||||
Ticker = topVolumeTicker.Ticker,
|
||||
Date = topVolumeTicker.Date,
|
||||
Volume = topVolumeTicker.Volume,
|
||||
Rank = topVolumeTicker.Rank,
|
||||
Exchange = topVolumeTicker.Exchange
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<TopVolumeTicker> Map(IEnumerable<TopVolumeTickerEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<TopVolumeTicker>();
|
||||
}
|
||||
|
||||
// SpotlightOverview mappings
|
||||
public static SpotlightOverview Map(SpotlightOverviewEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
var overview = new SpotlightOverview
|
||||
{
|
||||
Identifier = entity.Identifier,
|
||||
DateTime = entity.DateTime,
|
||||
ScenarioCount = entity.ScenarioCount,
|
||||
Spotlights = new List<Spotlight>()
|
||||
};
|
||||
|
||||
// Deserialize the JSON spotlights data
|
||||
if (!string.IsNullOrEmpty(entity.SpotlightsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
overview.Spotlights = SystemJsonSerializer.Deserialize<List<Spotlight>>(entity.SpotlightsJson) ?? new List<Spotlight>();
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// If deserialization fails, return empty list
|
||||
overview.Spotlights = new List<Spotlight>();
|
||||
}
|
||||
}
|
||||
|
||||
return overview;
|
||||
}
|
||||
|
||||
public static SpotlightOverviewEntity Map(SpotlightOverview overview)
|
||||
{
|
||||
if (overview == null) return null;
|
||||
|
||||
var entity = new SpotlightOverviewEntity
|
||||
{
|
||||
Identifier = overview.Identifier,
|
||||
DateTime = overview.DateTime,
|
||||
ScenarioCount = overview.ScenarioCount
|
||||
};
|
||||
|
||||
// Serialize the spotlights to JSON
|
||||
if (overview.Spotlights != null)
|
||||
{
|
||||
entity.SpotlightsJson = SystemJsonSerializer.Serialize(overview.Spotlights);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static IEnumerable<SpotlightOverview> Map(IEnumerable<SpotlightOverviewEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<SpotlightOverview>();
|
||||
}
|
||||
|
||||
// Trader mappings
|
||||
public static Trader Map(TraderEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new Trader
|
||||
{
|
||||
Address = entity.Address,
|
||||
Winrate = entity.Winrate,
|
||||
Pnl = entity.Pnl,
|
||||
TradeCount = entity.TradeCount,
|
||||
AverageWin = entity.AverageWin,
|
||||
AverageLoss = entity.AverageLoss,
|
||||
Roi = entity.Roi
|
||||
};
|
||||
}
|
||||
|
||||
public static TraderEntity Map(Trader trader, bool isBestTrader)
|
||||
{
|
||||
if (trader == null) return null;
|
||||
|
||||
return new TraderEntity
|
||||
{
|
||||
Address = trader.Address,
|
||||
Winrate = trader.Winrate,
|
||||
Pnl = trader.Pnl,
|
||||
TradeCount = trader.TradeCount,
|
||||
AverageWin = trader.AverageWin,
|
||||
AverageLoss = trader.AverageLoss,
|
||||
Roi = trader.Roi,
|
||||
IsBestTrader = isBestTrader
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<Trader> Map(IEnumerable<TraderEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Trader>();
|
||||
}
|
||||
|
||||
// FundingRate mappings
|
||||
public static FundingRate Map(FundingRateEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
|
||||
return new FundingRate
|
||||
{
|
||||
Ticker = entity.Ticker,
|
||||
Exchange = entity.Exchange,
|
||||
Rate = entity.Rate,
|
||||
OpenInterest = entity.OpenInterest,
|
||||
Date = entity.Date,
|
||||
Direction = entity.Direction
|
||||
};
|
||||
}
|
||||
|
||||
public static FundingRateEntity Map(FundingRate fundingRate)
|
||||
{
|
||||
if (fundingRate == null) return null;
|
||||
|
||||
return new FundingRateEntity
|
||||
{
|
||||
Ticker = fundingRate.Ticker,
|
||||
Exchange = fundingRate.Exchange,
|
||||
Rate = fundingRate.Rate,
|
||||
OpenInterest = fundingRate.OpenInterest,
|
||||
Date = fundingRate.Date,
|
||||
Direction = fundingRate.Direction
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<FundingRate> Map(IEnumerable<FundingRateEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<FundingRate>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Worker Mappings
|
||||
|
||||
public static Worker Map(WorkerEntity entity)
|
||||
{
|
||||
if (entity == null) return null;
|
||||
return new Worker
|
||||
{
|
||||
WorkerType = entity.WorkerType,
|
||||
StartTime = entity.StartTime,
|
||||
LastRunTime = entity.LastRunTime,
|
||||
ExecutionCount = entity.ExecutionCount,
|
||||
Delay = TimeSpan.FromTicks(entity.DelayTicks),
|
||||
IsActive = entity.IsActive
|
||||
};
|
||||
}
|
||||
|
||||
public static WorkerEntity Map(Worker worker)
|
||||
{
|
||||
if (worker == null) return null;
|
||||
return new WorkerEntity
|
||||
{
|
||||
WorkerType = worker.WorkerType,
|
||||
StartTime = worker.StartTime,
|
||||
LastRunTime = worker.LastRunTime,
|
||||
ExecutionCount = worker.ExecutionCount,
|
||||
DelayTicks = worker.Delay.Ticks,
|
||||
IsActive = worker.IsActive
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<Worker> Map(IEnumerable<WorkerEntity> entities)
|
||||
{
|
||||
return entities?.Select(Map) ?? Enumerable.Empty<Worker>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user