Add net Pnl in db

This commit is contained in:
2025-09-28 22:18:58 +07:00
parent 6267dad8fa
commit f041c1e8e8
28 changed files with 3095 additions and 54 deletions

View File

@@ -346,6 +346,7 @@ public class DataController : ControllerBase
{ {
StrategyName = bot.Name, StrategyName = bot.Name,
PnL = bot.Pnl, PnL = bot.Pnl,
NetPnL = bot.NetPnL,
AgentName = bot.User.AgentName, AgentName = bot.User.AgentName,
}) })
.ToList() .ToList()
@@ -373,6 +374,7 @@ public class DataController : ControllerBase
StrategyName = bot.Name, StrategyName = bot.Name,
Roi = bot.Roi, Roi = bot.Roi,
PnL = bot.Pnl, PnL = bot.Pnl,
NetPnL = bot.NetPnL,
Volume = bot.Volume Volume = bot.Volume
}) })
.ToList() .ToList()
@@ -393,10 +395,10 @@ public class DataController : ControllerBase
// Get all agent summaries // Get all agent summaries
var allAgentSummaries = await _mediator.Send(new GetAllAgentSummariesCommand()); var allAgentSummaries = await _mediator.Send(new GetAllAgentSummariesCommand());
// Filter agents with valid PnL data and order by PnL // Filter agents with valid PnL data and order by NetPnL
var agentsWithPnL = allAgentSummaries var agentsWithPnL = allAgentSummaries
.Where(agent => agent.TotalPnL != 0) // Only include agents with actual PnL .Where(agent => agent.NetPnL != 0) // Only include agents with actual NetPnL
.OrderByDescending(agent => agent.TotalPnL) .OrderByDescending(agent => agent.NetPnL)
.Take(3) .Take(3)
.ToList(); .ToList();
@@ -408,6 +410,7 @@ public class DataController : ControllerBase
{ {
AgentName = agent.AgentName, AgentName = agent.AgentName,
PnL = agent.TotalPnL, PnL = agent.TotalPnL,
NetPnL = agent.NetPnL,
TotalROI = agent.TotalROI, TotalROI = agent.TotalROI,
TotalVolume = agent.TotalVolume, TotalVolume = agent.TotalVolume,
ActiveStrategiesCount = agent.ActiveStrategiesCount, ActiveStrategiesCount = agent.ActiveStrategiesCount,
@@ -521,6 +524,7 @@ public class DataController : ControllerBase
Name = strategy.Name, Name = strategy.Name,
State = strategy.Status, State = strategy.Status,
PnL = strategy.Pnl, PnL = strategy.Pnl,
NetPnL = strategy.NetPnL,
ROIPercentage = strategy.Roi, ROIPercentage = strategy.Roi,
Runtime = strategy.StartupTime, Runtime = strategy.StartupTime,
WinRate = winRate, WinRate = winRate,
@@ -579,7 +583,7 @@ public class DataController : ControllerBase
public async Task<ActionResult<PaginatedAgentIndexResponse>> GetAgentIndexPaginated( public async Task<ActionResult<PaginatedAgentIndexResponse>> GetAgentIndexPaginated(
int page = 1, int page = 1,
int pageSize = 10, int pageSize = 10,
SortableFields sortBy = SortableFields.TotalPnL, SortableFields sortBy = SortableFields.NetPnL,
string sortOrder = "desc", string sortOrder = "desc",
string? agentNames = null) string? agentNames = null)
{ {
@@ -632,6 +636,7 @@ public class DataController : ControllerBase
{ {
AgentName = agentSummary.AgentName, AgentName = agentSummary.AgentName,
TotalPnL = agentSummary.TotalPnL, TotalPnL = agentSummary.TotalPnL,
NetPnL = agentSummary.NetPnL,
TotalROI = agentSummary.TotalROI, TotalROI = agentSummary.TotalROI,
Wins = agentSummary.Wins, Wins = agentSummary.Wins,
Losses = agentSummary.Losses, Losses = agentSummary.Losses,
@@ -799,6 +804,7 @@ public class DataController : ControllerBase
TotalStrategies = s.TotalStrategies, TotalStrategies = s.TotalStrategies,
TotalVolume = s.TotalVolume, TotalVolume = s.TotalVolume,
TotalPnL = s.TotalPnL, TotalPnL = s.TotalPnL,
NetPnL = s.NetPnL,
TotalOpenInterest = s.TotalOpenInterest, TotalOpenInterest = s.TotalOpenInterest,
TotalPositionCount = s.TotalLifetimePositionCount TotalPositionCount = s.TotalLifetimePositionCount
}) })

View File

@@ -13,10 +13,15 @@ namespace Managing.Api.Models.Responses
public string AgentName { get; set; } public string AgentName { get; set; }
/// <summary> /// <summary>
/// Total profit and loss in USD /// Total profit and loss in USD (gross, before fees)
/// </summary> /// </summary>
public decimal TotalPnL { get; set; } public decimal TotalPnL { get; set; }
/// <summary>
/// Net profit and loss in USD (after fees)
/// </summary>
public decimal NetPnL { get; set; }
/// <summary> /// <summary>
/// Total return on investment as a percentage /// Total return on investment as a percentage
/// </summary> /// </summary>
@@ -160,10 +165,15 @@ namespace Managing.Api.Models.Responses
public required decimal TotalVolume { get; set; } public required decimal TotalVolume { get; set; }
/// <summary> /// <summary>
/// Total PnL on this date in USD /// Total PnL on this date in USD (gross, before fees)
/// </summary> /// </summary>
public required decimal TotalPnL { get; set; } public required decimal TotalPnL { get; set; }
/// <summary>
/// Net PnL on this date in USD (after fees)
/// </summary>
public required decimal NetPnL { get; set; }
/// <summary> /// <summary>
/// Total open interest on this date in USD /// Total open interest on this date in USD
/// </summary> /// </summary>

View File

@@ -50,7 +50,7 @@ public class PaginatedAgentIndexResponse
/// <summary> /// <summary>
/// Field used for sorting /// Field used for sorting
/// </summary> /// </summary>
public SortableFields SortBy { get; set; } = SortableFields.TotalPnL; public SortableFields SortBy { get; set; } = SortableFields.NetPnL;
/// <summary> /// <summary>
/// Sort order (asc or desc) /// Sort order (asc or desc)

View File

@@ -11,10 +11,15 @@ namespace Managing.Api.Models.Responses
public string StrategyName { get; set; } public string StrategyName { get; set; }
/// <summary> /// <summary>
/// Profit and Loss value of the strategy /// Profit and Loss value of the strategy (gross, before fees)
/// </summary> /// </summary>
public decimal PnL { get; set; } public decimal PnL { get; set; }
/// <summary>
/// Net Profit and Loss value of the strategy (after fees)
/// </summary>
public decimal NetPnL { get; set; }
public string AgentName { get; set; } public string AgentName { get; set; }
} }
@@ -34,10 +39,15 @@ namespace Managing.Api.Models.Responses
public decimal Roi { get; set; } public decimal Roi { get; set; }
/// <summary> /// <summary>
/// Profit and Loss value of the strategy /// Profit and Loss value of the strategy (gross, before fees)
/// </summary> /// </summary>
public decimal PnL { get; set; } public decimal PnL { get; set; }
/// <summary>
/// Net Profit and Loss value of the strategy (after fees)
/// </summary>
public decimal NetPnL { get; set; }
/// <summary> /// <summary>
/// Volume traded by the strategy /// Volume traded by the strategy
/// </summary> /// </summary>
@@ -77,10 +87,15 @@ namespace Managing.Api.Models.Responses
public string AgentName { get; set; } public string AgentName { get; set; }
/// <summary> /// <summary>
/// Profit and Loss value of the agent /// Profit and Loss value of the agent (gross, before fees)
/// </summary> /// </summary>
public decimal PnL { get; set; } public decimal PnL { get; set; }
/// <summary>
/// Net Profit and Loss value of the agent (after fees)
/// </summary>
public decimal NetPnL { get; set; }
/// <summary> /// <summary>
/// Total ROI percentage of the agent /// Total ROI percentage of the agent
/// </summary> /// </summary>

View File

@@ -19,10 +19,15 @@ namespace Managing.Api.Models.Responses
public Enums.BotStatus State { get; set; } public Enums.BotStatus State { get; set; }
/// <summary> /// <summary>
/// Total profit or loss generated by the strategy in USD /// Total profit or loss generated by the strategy in USD (gross, before fees)
/// </summary> /// </summary>
public decimal PnL { get; set; } public decimal PnL { get; set; }
/// <summary>
/// Net profit or loss generated by the strategy in USD (after fees)
/// </summary>
public decimal NetPnL { get; set; }
/// <summary> /// <summary>
/// Return on investment percentage /// Return on investment percentage
/// </summary> /// </summary>

View File

@@ -22,27 +22,29 @@ public class PlatformSummaryGrainState
[Id(5)] public decimal TotalPlatformPnL { get; set; } [Id(5)] public decimal TotalPlatformPnL { get; set; }
[Id(6)] public decimal TotalPlatformVolume { get; set; } [Id(6)] public decimal NetPnL { get; set; }
[Id(7)] public decimal OpenInterest { get; set; } [Id(7)] public decimal TotalPlatformVolume { get; set; }
[Id(8)] public int TotalLifetimePositionCount { get; set; } [Id(8)] public decimal OpenInterest { get; set; }
[Id(9)] public decimal TotalPlatformFees { get; set; } [Id(9)] public int TotalLifetimePositionCount { get; set; }
[Id(10)] public decimal TotalPlatformFees { get; set; }
// Historical snapshots // Historical snapshots
[Id(10)] public List<DailySnapshot> DailySnapshots { get; set; } = new(); [Id(11)] public List<DailySnapshot> DailySnapshots { get; set; } = new();
// Volume breakdown by asset // Volume breakdown by asset
[Id(11)] public Dictionary<Ticker, decimal> VolumeByAsset { get; set; } = new(); [Id(12)] public Dictionary<Ticker, decimal> VolumeByAsset { get; set; } = new();
// Position count breakdown // Position count breakdown
[Id(12)] public Dictionary<Ticker, int> PositionCountByAsset { get; set; } = new(); [Id(13)] public Dictionary<Ticker, int> PositionCountByAsset { get; set; } = new();
[Id(13)] public Dictionary<TradeDirection, int> PositionCountByDirection { get; set; } = new(); [Id(14)] public Dictionary<TradeDirection, int> PositionCountByDirection { get; set; } = new();
// Flag to track if volume has been updated by events (not from bot strategies) // Flag to track if volume has been updated by events (not from bot strategies)
[Id(14)] public bool VolumeUpdatedByEvents { get; set; } [Id(15)] public bool VolumeUpdatedByEvents { get; set; }
} }
/// <summary> /// <summary>
@@ -61,9 +63,11 @@ public class DailySnapshot
[Id(4)] public decimal TotalPnL { get; set; } [Id(4)] public decimal TotalPnL { get; set; }
[Id(5)] public decimal TotalOpenInterest { get; set; } [Id(5)] public decimal NetPnL { get; set; }
[Id(6)] public int TotalLifetimePositionCount { get; set; } [Id(6)] public decimal TotalOpenInterest { get; set; }
[Id(7)] public int TotalPlatformFees { get; set; } [Id(7)] public int TotalLifetimePositionCount { get; set; }
[Id(8)] public int TotalPlatformFees { get; set; }
} }

View File

@@ -237,7 +237,8 @@ public class AgentGrain : Grain, IAgentGrain
{ {
UserId = (int)this.GetPrimaryKeyLong(), UserId = (int)this.GetPrimaryKeyLong(),
AgentName = _state.State.AgentName, AgentName = _state.State.AgentName,
TotalPnL = totalPnL, // Use net PnL without fees TotalPnL = totalPnL, // Gross PnL before fees
NetPnL = netPnL, // Net PnL after fees
Wins = totalWins, Wins = totalWins,
Losses = totalLosses, Losses = totalLosses,
TotalROI = totalROI, TotalROI = totalROI,

View File

@@ -720,12 +720,13 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
var (tradeWins, tradeLosses) = TradingBox.GetWinLossCount(_tradingBot.Positions); var (tradeWins, tradeLosses) = TradingBox.GetWinLossCount(_tradingBot.Positions);
var pnl = _tradingBot.GetProfitAndLoss(); var pnl = _tradingBot.GetProfitAndLoss();
var fees = _tradingBot.GetTotalFees(); var fees = _tradingBot.GetTotalFees();
var netPnl = pnl - fees; // Net PnL after fees
var volume = TradingBox.GetTotalVolumeTraded(_tradingBot.Positions); var volume = TradingBox.GetTotalVolumeTraded(_tradingBot.Positions);
// Calculate ROI based on total investment (PnL minus fees) // Calculate ROI based on total investment (Net PnL)
var totalInvestment = _tradingBot.Positions.Values var totalInvestment = _tradingBot.Positions.Values
.Sum(p => p.Open.Quantity * p.Open.Price); .Sum(p => p.Open.Quantity * p.Open.Price);
var roi = totalInvestment > 0 ? ((pnl - fees) / totalInvestment) * 100 : 0; var roi = totalInvestment > 0 ? (netPnl / totalInvestment) * 100 : 0;
// Calculate long and short position counts // Calculate long and short position counts
var longPositionCount = _tradingBot.Positions.Values var longPositionCount = _tradingBot.Positions.Values
@@ -745,7 +746,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
CreateDate = _state.State.CreateDate, CreateDate = _state.State.CreateDate,
TradeWins = tradeWins, TradeWins = tradeWins,
TradeLosses = tradeLosses, TradeLosses = tradeLosses,
Pnl = pnl, Pnl = pnl, // Gross PnL before fees
NetPnL = netPnl, // Net PnL after fees
Roi = roi, Roi = roi,
Volume = volume, Volume = volume,
Fees = fees, Fees = fees,

View File

@@ -68,6 +68,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
TotalStrategies = 0, TotalStrategies = 0,
TotalVolume = 0, TotalVolume = 0,
TotalPnL = 0, TotalPnL = 0,
NetPnL = 0,
TotalOpenInterest = 0, TotalOpenInterest = 0,
TotalLifetimePositionCount = 0, TotalLifetimePositionCount = 0,
TotalPlatformFees = 0, TotalPlatformFees = 0,
@@ -170,6 +171,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
_state.State.TotalPlatformVolume = totalVolume; _state.State.TotalPlatformVolume = totalVolume;
_state.State.TotalPlatformFees = totalFees; _state.State.TotalPlatformFees = totalFees;
_state.State.TotalPlatformPnL = totalPnL; _state.State.TotalPlatformPnL = totalPnL;
_state.State.NetPnL = totalPnL - totalFees; // Calculate NetPnL
_state.State.OpenInterest = totalOpenInterest; _state.State.OpenInterest = totalOpenInterest;
_state.State.TotalLifetimePositionCount = totalPositionCount; _state.State.TotalLifetimePositionCount = totalPositionCount;
_state.State.HasPendingChanges = false; _state.State.HasPendingChanges = false;
@@ -289,6 +291,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
TotalStrategies = _state.State.TotalActiveStrategies, TotalStrategies = _state.State.TotalActiveStrategies,
TotalVolume = _state.State.TotalPlatformVolume, TotalVolume = _state.State.TotalPlatformVolume,
TotalPnL = _state.State.TotalPlatformPnL, TotalPnL = _state.State.TotalPlatformPnL,
NetPnL = _state.State.NetPnL,
TotalOpenInterest = _state.State.OpenInterest, TotalOpenInterest = _state.State.OpenInterest,
TotalLifetimePositionCount = _state.State.TotalLifetimePositionCount, TotalLifetimePositionCount = _state.State.TotalLifetimePositionCount,
}; };

View File

@@ -37,7 +37,7 @@ namespace Managing.Application.ManageBot.Commands
public GetPaginatedAgentSummariesCommand( public GetPaginatedAgentSummariesCommand(
int page = 1, int page = 1,
int pageSize = 10, int pageSize = 10,
SortableFields sortBy = SortableFields.TotalPnL, SortableFields sortBy = SortableFields.NetPnL,
string sortOrder = "desc", string sortOrder = "desc",
IEnumerable<string>? agentNames = null) IEnumerable<string>? agentNames = null)
{ {

View File

@@ -477,7 +477,7 @@ public static class Enums
/// </summary> /// </summary>
public enum SortableFields public enum SortableFields
{ {
TotalPnL, NetPnL,
TotalROI, TotalROI,
Wins, Wins,
Losses, Losses,

View File

@@ -16,6 +16,7 @@ namespace Managing.Domain.Bots
public int TradeWins { get; set; } public int TradeWins { get; set; }
public int TradeLosses { get; set; } public int TradeLosses { get; set; }
public decimal Pnl { get; set; } public decimal Pnl { get; set; }
public decimal NetPnL { get; set; }
public decimal Roi { get; set; } public decimal Roi { get; set; }
public decimal Volume { get; set; } public decimal Volume { get; set; }
public decimal Fees { get; set; } public decimal Fees { get; set; }

View File

@@ -50,4 +50,7 @@ public class AgentSummary
[Id(14)] [Id(14)]
public decimal TotalFees { get; set; } public decimal TotalFees { get; set; }
[Id(15)]
public decimal NetPnL { get; set; }
} }

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Managing.Infrastructure.Databases.Migrations
{
/// <inheritdoc />
public partial class AddNetPnLToAgentSummary : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "NetPnL",
table: "AgentSummaries",
type: "numeric",
nullable: false,
defaultValue: 0m);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "NetPnL",
table: "AgentSummaries");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Managing.Infrastructure.Databases.Migrations
{
/// <inheritdoc />
public partial class AddNetPnLToBot : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "NetPnL",
table: "Bots",
type: "numeric(18,8)",
precision: 18,
scale: 8,
nullable: false,
defaultValue: 0m);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "NetPnL",
table: "Bots");
}
}
}

View File

@@ -92,6 +92,9 @@ namespace Managing.Infrastructure.Databases.Migrations
b.Property<int>("Losses") b.Property<int>("Losses")
.HasColumnType("integer"); .HasColumnType("integer");
b.Property<decimal>("NetPnL")
.HasColumnType("numeric");
b.Property<DateTime?>("Runtime") b.Property<DateTime?>("Runtime")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
@@ -250,6 +253,10 @@ namespace Managing.Infrastructure.Databases.Migrations
.HasMaxLength(255) .HasMaxLength(255)
.HasColumnType("character varying(255)"); .HasColumnType("character varying(255)");
b.Property<decimal>("NetPnL")
.HasPrecision(18, 8)
.HasColumnType("numeric(18,8)");
b.Property<decimal>("Pnl") b.Property<decimal>("Pnl")
.HasPrecision(18, 8) .HasPrecision(18, 8)
.HasColumnType("numeric(18,8)"); .HasColumnType("numeric(18,8)");

View File

@@ -189,9 +189,9 @@ public class AgentSummaryRepository : IAgentSummaryRepository
var isDescending = sortOrder.ToLowerInvariant() == "desc"; var isDescending = sortOrder.ToLowerInvariant() == "desc";
query = sortBy switch query = sortBy switch
{ {
SortableFields.TotalPnL => isDescending SortableFields.NetPnL => isDescending
? query.OrderByDescending(a => a.TotalPnL) ? query.OrderByDescending(a => a.NetPnL)
: query.OrderBy(a => a.TotalPnL), : query.OrderBy(a => a.NetPnL),
SortableFields.TotalROI => isDescending SortableFields.TotalROI => isDescending
? query.OrderByDescending(a => a.TotalROI) ? query.OrderByDescending(a => a.TotalROI)
: query.OrderBy(a => a.TotalROI), : query.OrderBy(a => a.TotalROI),
@@ -241,6 +241,7 @@ public class AgentSummaryRepository : IAgentSummaryRepository
UserId = domain.UserId, UserId = domain.UserId,
AgentName = domain.AgentName, AgentName = domain.AgentName,
TotalPnL = domain.TotalPnL, TotalPnL = domain.TotalPnL,
NetPnL = domain.NetPnL,
TotalROI = domain.TotalROI, TotalROI = domain.TotalROI,
Wins = domain.Wins, Wins = domain.Wins,
Losses = domain.Losses, Losses = domain.Losses,
@@ -259,6 +260,7 @@ public class AgentSummaryRepository : IAgentSummaryRepository
entity.UserId = domain.UserId; entity.UserId = domain.UserId;
entity.AgentName = domain.AgentName; entity.AgentName = domain.AgentName;
entity.TotalPnL = domain.TotalPnL; entity.TotalPnL = domain.TotalPnL;
entity.NetPnL = domain.NetPnL;
entity.TotalROI = domain.TotalROI; entity.TotalROI = domain.TotalROI;
entity.Wins = domain.Wins; entity.Wins = domain.Wins;
entity.Losses = domain.Losses; entity.Losses = domain.Losses;
@@ -277,6 +279,7 @@ public class AgentSummaryRepository : IAgentSummaryRepository
UserId = entity.UserId, UserId = entity.UserId,
AgentName = entity.AgentName, AgentName = entity.AgentName,
TotalPnL = entity.TotalPnL, TotalPnL = entity.TotalPnL,
NetPnL = entity.NetPnL,
TotalROI = entity.TotalROI, TotalROI = entity.TotalROI,
Wins = entity.Wins, Wins = entity.Wins,
Losses = entity.Losses, Losses = entity.Losses,

View File

@@ -16,6 +16,7 @@ public class AgentSummaryEntity
public decimal TotalVolume { get; set; } public decimal TotalVolume { get; set; }
public decimal TotalBalance { get; set; } public decimal TotalBalance { get; set; }
public decimal TotalFees { get; set; } public decimal TotalFees { get; set; }
public decimal NetPnL { get; set; }
// Navigation property // Navigation property
public UserEntity User { get; set; } public UserEntity User { get; set; }

View File

@@ -24,6 +24,7 @@ public class BotEntity
public int TradeWins { get; set; } public int TradeWins { get; set; }
public int TradeLosses { get; set; } public int TradeLosses { get; set; }
public decimal Pnl { get; set; } public decimal Pnl { get; set; }
public decimal NetPnL { get; set; }
public decimal Roi { get; set; } public decimal Roi { get; set; }
public decimal Volume { get; set; } public decimal Volume { get; set; }
public decimal Fees { get; set; } public decimal Fees { get; set; }

View File

@@ -447,6 +447,7 @@ public class ManagingDbContext : DbContext
entity.Property(e => e.TradeWins).IsRequired(); entity.Property(e => e.TradeWins).IsRequired();
entity.Property(e => e.TradeLosses).IsRequired(); entity.Property(e => e.TradeLosses).IsRequired();
entity.Property(e => e.Pnl).HasPrecision(18, 8); entity.Property(e => e.Pnl).HasPrecision(18, 8);
entity.Property(e => e.NetPnL).HasPrecision(18, 8);
entity.Property(e => e.Roi).HasPrecision(18, 8); entity.Property(e => e.Roi).HasPrecision(18, 8);
entity.Property(e => e.Volume).HasPrecision(18, 8); entity.Property(e => e.Volume).HasPrecision(18, 8);
entity.Property(e => e.Fees).HasPrecision(18, 8); entity.Property(e => e.Fees).HasPrecision(18, 8);

View File

@@ -69,6 +69,7 @@ public class PostgreSqlBotRepository : IBotRepository
existingEntity.TradeWins = bot.TradeWins; existingEntity.TradeWins = bot.TradeWins;
existingEntity.TradeLosses = bot.TradeLosses; existingEntity.TradeLosses = bot.TradeLosses;
existingEntity.Pnl = bot.Pnl; existingEntity.Pnl = bot.Pnl;
existingEntity.NetPnL = bot.NetPnL;
existingEntity.Roi = bot.Roi; existingEntity.Roi = bot.Roi;
existingEntity.Volume = bot.Volume; existingEntity.Volume = bot.Volume;
existingEntity.Fees = bot.Fees; existingEntity.Fees = bot.Fees;

View File

@@ -694,6 +694,7 @@ public static class PostgreSqlMappers
TradeWins = entity.TradeWins, TradeWins = entity.TradeWins,
TradeLosses = entity.TradeLosses, TradeLosses = entity.TradeLosses,
Pnl = entity.Pnl, Pnl = entity.Pnl,
NetPnL = entity.NetPnL,
Roi = entity.Roi, Roi = entity.Roi,
Volume = entity.Volume, Volume = entity.Volume,
Fees = entity.Fees, Fees = entity.Fees,
@@ -720,6 +721,7 @@ public static class PostgreSqlMappers
TradeWins = bot.TradeWins, TradeWins = bot.TradeWins,
TradeLosses = bot.TradeLosses, TradeLosses = bot.TradeLosses,
Pnl = bot.Pnl, Pnl = bot.Pnl,
NetPnL = bot.NetPnL,
Roi = bot.Roi, Roi = bot.Roi,
Volume = bot.Volume, Volume = bot.Volume,
Fees = bot.Fees, Fees = bot.Fees,

View File

@@ -3563,6 +3563,7 @@ export class UserClient extends AuthorizedApiBase {
} }
export interface Account { export interface Account {
id?: number;
name: string; name: string;
exchange: TradingExchanges; exchange: TradingExchanges;
type: AccountType; type: AccountType;
@@ -3909,8 +3910,8 @@ export enum SignalType {
} }
export interface Position { export interface Position {
accountName: string;
date: Date; date: Date;
accountId: number;
originDirection: TradeDirection; originDirection: TradeDirection;
ticker: Ticker; ticker: Ticker;
moneyManagement: LightMoneyManagement; moneyManagement: LightMoneyManagement;
@@ -3919,6 +3920,8 @@ export interface Position {
TakeProfit1: Trade; TakeProfit1: Trade;
TakeProfit2?: Trade | null; TakeProfit2?: Trade | null;
ProfitAndLoss?: ProfitAndLoss | null; ProfitAndLoss?: ProfitAndLoss | null;
uiFees?: number;
gasFees?: number;
status: PositionStatus; status: PositionStatus;
signalIdentifier?: string | null; signalIdentifier?: string | null;
identifier: string; identifier: string;
@@ -3982,7 +3985,6 @@ export enum PositionStatus {
Canceled = "Canceled", Canceled = "Canceled",
Rejected = "Rejected", Rejected = "Rejected",
Updating = "Updating", Updating = "Updating",
PartiallyFilled = "PartiallyFilled",
Filled = "Filled", Filled = "Filled",
Flipped = "Flipped", Flipped = "Flipped",
Finished = "Finished", Finished = "Finished",
@@ -4502,6 +4504,7 @@ export interface TopStrategiesViewModel {
export interface StrategyPerformance { export interface StrategyPerformance {
strategyName?: string | null; strategyName?: string | null;
pnL?: number; pnL?: number;
netPnL?: number;
agentName?: string | null; agentName?: string | null;
} }
@@ -4513,6 +4516,7 @@ export interface StrategyRoiPerformance {
strategyName?: string | null; strategyName?: string | null;
roi?: number; roi?: number;
pnL?: number; pnL?: number;
netPnL?: number;
volume?: number; volume?: number;
} }
@@ -4523,6 +4527,7 @@ export interface TopAgentsByPnLViewModel {
export interface AgentPerformance { export interface AgentPerformance {
agentName?: string | null; agentName?: string | null;
pnL?: number; pnL?: number;
netPnL?: number;
totalROI?: number; totalROI?: number;
totalVolume?: number; totalVolume?: number;
activeStrategiesCount?: number; activeStrategiesCount?: number;
@@ -4533,6 +4538,7 @@ export interface UserStrategyDetailsViewModel {
name?: string | null; name?: string | null;
state?: BotStatus; state?: BotStatus;
pnL?: number; pnL?: number;
netPnL?: number;
roiPercentage?: number; roiPercentage?: number;
runtime?: Date; runtime?: Date;
winRate?: number; winRate?: number;
@@ -4569,6 +4575,7 @@ export interface DailySnapshot {
totalStrategies?: number; totalStrategies?: number;
totalVolume?: number; totalVolume?: number;
totalPnL?: number; totalPnL?: number;
netPnL?: number;
totalOpenInterest?: number; totalOpenInterest?: number;
totalPositionCount?: number; totalPositionCount?: number;
} }
@@ -4590,16 +4597,18 @@ export interface PaginatedAgentIndexResponse {
export interface AgentSummaryViewModel { export interface AgentSummaryViewModel {
agentName?: string | null; agentName?: string | null;
totalPnL?: number; totalPnL?: number;
netPnL?: number;
totalROI?: number; totalROI?: number;
wins?: number; wins?: number;
losses?: number; losses?: number;
activeStrategiesCount?: number; activeStrategiesCount?: number;
totalVolume?: number; totalVolume?: number;
totalBalance?: number; totalBalance?: number;
totalFees?: number;
} }
export enum SortableFields { export enum SortableFields {
TotalPnL = "TotalPnL", NetPnL = "NetPnL",
TotalROI = "TotalROI", TotalROI = "TotalROI",
Wins = "Wins", Wins = "Wins",
Losses = "Losses", Losses = "Losses",

View File

@@ -11,6 +11,7 @@
export interface Account { export interface Account {
id?: number;
name: string; name: string;
exchange: TradingExchanges; exchange: TradingExchanges;
type: AccountType; type: AccountType;
@@ -357,8 +358,8 @@ export enum SignalType {
} }
export interface Position { export interface Position {
accountName: string;
date: Date; date: Date;
accountId: number;
originDirection: TradeDirection; originDirection: TradeDirection;
ticker: Ticker; ticker: Ticker;
moneyManagement: LightMoneyManagement; moneyManagement: LightMoneyManagement;
@@ -367,6 +368,8 @@ export interface Position {
TakeProfit1: Trade; TakeProfit1: Trade;
TakeProfit2?: Trade | null; TakeProfit2?: Trade | null;
ProfitAndLoss?: ProfitAndLoss | null; ProfitAndLoss?: ProfitAndLoss | null;
uiFees?: number;
gasFees?: number;
status: PositionStatus; status: PositionStatus;
signalIdentifier?: string | null; signalIdentifier?: string | null;
identifier: string; identifier: string;
@@ -430,7 +433,6 @@ export enum PositionStatus {
Canceled = "Canceled", Canceled = "Canceled",
Rejected = "Rejected", Rejected = "Rejected",
Updating = "Updating", Updating = "Updating",
PartiallyFilled = "PartiallyFilled",
Filled = "Filled", Filled = "Filled",
Flipped = "Flipped", Flipped = "Flipped",
Finished = "Finished", Finished = "Finished",
@@ -950,6 +952,7 @@ export interface TopStrategiesViewModel {
export interface StrategyPerformance { export interface StrategyPerformance {
strategyName?: string | null; strategyName?: string | null;
pnL?: number; pnL?: number;
netPnL?: number;
agentName?: string | null; agentName?: string | null;
} }
@@ -961,6 +964,7 @@ export interface StrategyRoiPerformance {
strategyName?: string | null; strategyName?: string | null;
roi?: number; roi?: number;
pnL?: number; pnL?: number;
netPnL?: number;
volume?: number; volume?: number;
} }
@@ -971,6 +975,7 @@ export interface TopAgentsByPnLViewModel {
export interface AgentPerformance { export interface AgentPerformance {
agentName?: string | null; agentName?: string | null;
pnL?: number; pnL?: number;
netPnL?: number;
totalROI?: number; totalROI?: number;
totalVolume?: number; totalVolume?: number;
activeStrategiesCount?: number; activeStrategiesCount?: number;
@@ -981,6 +986,7 @@ export interface UserStrategyDetailsViewModel {
name?: string | null; name?: string | null;
state?: BotStatus; state?: BotStatus;
pnL?: number; pnL?: number;
netPnL?: number;
roiPercentage?: number; roiPercentage?: number;
runtime?: Date; runtime?: Date;
winRate?: number; winRate?: number;
@@ -1017,6 +1023,7 @@ export interface DailySnapshot {
totalStrategies?: number; totalStrategies?: number;
totalVolume?: number; totalVolume?: number;
totalPnL?: number; totalPnL?: number;
netPnL?: number;
totalOpenInterest?: number; totalOpenInterest?: number;
totalPositionCount?: number; totalPositionCount?: number;
} }
@@ -1038,16 +1045,18 @@ export interface PaginatedAgentIndexResponse {
export interface AgentSummaryViewModel { export interface AgentSummaryViewModel {
agentName?: string | null; agentName?: string | null;
totalPnL?: number; totalPnL?: number;
netPnL?: number;
totalROI?: number; totalROI?: number;
wins?: number; wins?: number;
losses?: number; losses?: number;
activeStrategiesCount?: number; activeStrategiesCount?: number;
totalVolume?: number; totalVolume?: number;
totalBalance?: number; totalBalance?: number;
totalFees?: number;
} }
export enum SortableFields { export enum SortableFields {
TotalPnL = "TotalPnL", NetPnL = "NetPnL",
TotalROI = "TotalROI", TotalROI = "TotalROI",
Wins = "Wins", Wins = "Wins",
Losses = "Losses", Losses = "Losses",

View File

@@ -203,8 +203,8 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
<div className="stat-value text-success">{strategyData.winRate || 0}%</div> <div className="stat-value text-success">{strategyData.winRate || 0}%</div>
</div> </div>
<div className="stat bg-base-200 rounded-lg"> <div className="stat bg-base-200 rounded-lg">
<div className="stat-title">PnL</div> <div className="stat-title">Net PnL</div>
<div className="stat-value text-success">{formatCurrency(strategyData.pnL)}</div> <div className="stat-value text-success">{formatCurrency(strategyData.netPnL)}</div>
</div> </div>
<div className="stat bg-base-200 rounded-lg"> <div className="stat bg-base-200 rounded-lg">
<div className="stat-title">Backtest</div> <div className="stat-title">Backtest</div>
@@ -283,8 +283,8 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
<div className="card-body"> <div className="card-body">
<h3 className="card-title">PnL $</h3> <h3 className="card-title">PnL $</h3>
<div className="text-2xl font-bold">{formatCurrency(strategyData.pnL)}</div> <div className="text-2xl font-bold">{formatCurrency(strategyData.pnL)}</div>
<div className="text-sm"> <div className="text-sm text-gray-400">
{formatCurrency((strategyData.pnL || 0) * 0.1)} Today Net: {formatCurrency(strategyData.netPnL)}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -210,8 +210,8 @@ function PlatformSummary({index}: { index: number }) {
</div> </div>
</div> </div>
<div <div
className={`text-sm font-bold ${strategy.pnL && strategy.pnL >= 0 ? 'text-green-500' : 'text-red-500'}`}> className={`text-sm font-bold ${strategy.netPnL && strategy.netPnL >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{strategy.pnL && strategy.pnL >= 0 ? '+' : ''}{formatCurrency(strategy.pnL || 0)} {strategy.netPnL && strategy.netPnL >= 0 ? '+' : ''}{formatCurrency(strategy.netPnL || 0)}
</div> </div>
</div> </div>
)) || ( )) || (
@@ -250,8 +250,8 @@ function PlatformSummary({index}: { index: number }) {
{(strategy.roi || 0) >= 0 ? '+' : ''}{strategy.roi?.toFixed(2) || 0}% {(strategy.roi || 0) >= 0 ? '+' : ''}{strategy.roi?.toFixed(2) || 0}%
</div> </div>
<div <div
className={`text-xs ${(strategy.pnL || 0) >= 0 ? 'text-green-400' : 'text-red-400'}`}> className={`text-xs ${(strategy.netPnL || 0) >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{(strategy.pnL || 0) >= 0 ? '+' : ''}{formatCurrency(strategy.pnL || 0)} {(strategy.netPnL || 0) >= 0 ? '+' : ''}{formatCurrency(strategy.netPnL || 0)}
</div> </div>
</div> </div>
</div> </div>
@@ -287,8 +287,8 @@ function PlatformSummary({index}: { index: number }) {
</div> </div>
<div className="text-right"> <div className="text-right">
<div <div
className={`text-sm font-bold ${(agent.pnL || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}> className={`text-sm font-bold ${(agent.netPnL || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(agent.pnL || 0) >= 0 ? '+' : ''}{formatCurrency(agent.pnL || 0)} {(agent.netPnL || 0) >= 0 ? '+' : ''}{formatCurrency(agent.netPnL || 0)}
</div> </div>
<div className="text-xs text-gray-400"> <div className="text-xs text-gray-400">
{(agent.totalROI || 0).toFixed(2)}% ROI {(agent.totalROI || 0).toFixed(2)}% ROI
@@ -332,6 +332,9 @@ function PlatformSummary({index}: { index: number }) {
className={`text-3xl font-bold ${(platformData?.totalPlatformPnL || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}> className={`text-3xl font-bold ${(platformData?.totalPlatformPnL || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(platformData?.totalPlatformPnL || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.totalPlatformPnL || 0)} {(platformData?.totalPlatformPnL || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.totalPlatformPnL || 0)}
</div> </div>
<div className="text-sm text-gray-400 mb-1">
Fees: {formatCurrency(platformData?.totalPlatformFees || 0)}
</div>
<div <div
className={`text-sm ${changesToday.pnLChange >= 0 ? 'text-green-500' : 'text-red-500'}`}> className={`text-sm ${changesToday.pnLChange >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{changesToday.pnLChange >= 0 ? '+' : ''}{formatCurrency(changesToday.pnLChange)} Today {changesToday.pnLChange >= 0 ? '+' : ''}{formatCurrency(changesToday.pnLChange)} Today