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

View File

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

View File

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

View File

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

View File

@@ -19,10 +19,15 @@ namespace Managing.Api.Models.Responses
public Enums.BotStatus State { get; set; }
/// <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>
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>
/// Return on investment percentage
/// </summary>

View File

@@ -22,27 +22,29 @@ public class PlatformSummaryGrainState
[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
[Id(10)] public List<DailySnapshot> DailySnapshots { get; set; } = new();
[Id(11)] public List<DailySnapshot> DailySnapshots { get; set; } = new();
// 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
[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)
[Id(14)] public bool VolumeUpdatedByEvents { get; set; }
[Id(15)] public bool VolumeUpdatedByEvents { get; set; }
}
/// <summary>
@@ -61,9 +63,11 @@ public class DailySnapshot
[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(),
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,
Losses = totalLosses,
TotalROI = totalROI,

View File

@@ -720,12 +720,13 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
var (tradeWins, tradeLosses) = TradingBox.GetWinLossCount(_tradingBot.Positions);
var pnl = _tradingBot.GetProfitAndLoss();
var fees = _tradingBot.GetTotalFees();
var netPnl = pnl - fees; // Net PnL after fees
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
.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
var longPositionCount = _tradingBot.Positions.Values
@@ -745,7 +746,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
CreateDate = _state.State.CreateDate,
TradeWins = tradeWins,
TradeLosses = tradeLosses,
Pnl = pnl,
Pnl = pnl, // Gross PnL before fees
NetPnL = netPnl, // Net PnL after fees
Roi = roi,
Volume = volume,
Fees = fees,

View File

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

View File

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

View File

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

View File

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

View File

@@ -50,4 +50,7 @@ public class AgentSummary
[Id(14)]
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")
.HasColumnType("integer");
b.Property<decimal>("NetPnL")
.HasColumnType("numeric");
b.Property<DateTime?>("Runtime")
.HasColumnType("timestamp with time zone");
@@ -250,6 +253,10 @@ namespace Managing.Infrastructure.Databases.Migrations
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<decimal>("NetPnL")
.HasPrecision(18, 8)
.HasColumnType("numeric(18,8)");
b.Property<decimal>("Pnl")
.HasPrecision(18, 8)
.HasColumnType("numeric(18,8)");

View File

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

View File

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

View File

@@ -24,6 +24,7 @@ public class BotEntity
public int TradeWins { get; set; }
public int TradeLosses { get; set; }
public decimal Pnl { get; set; }
public decimal NetPnL { get; set; }
public decimal Roi { get; set; }
public decimal Volume { 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.TradeLosses).IsRequired();
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.Volume).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.TradeLosses = bot.TradeLosses;
existingEntity.Pnl = bot.Pnl;
existingEntity.NetPnL = bot.NetPnL;
existingEntity.Roi = bot.Roi;
existingEntity.Volume = bot.Volume;
existingEntity.Fees = bot.Fees;

View File

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

View File

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

View File

@@ -11,6 +11,7 @@
export interface Account {
id?: number;
name: string;
exchange: TradingExchanges;
type: AccountType;
@@ -357,8 +358,8 @@ export enum SignalType {
}
export interface Position {
accountName: string;
date: Date;
accountId: number;
originDirection: TradeDirection;
ticker: Ticker;
moneyManagement: LightMoneyManagement;
@@ -367,6 +368,8 @@ export interface Position {
TakeProfit1: Trade;
TakeProfit2?: Trade | null;
ProfitAndLoss?: ProfitAndLoss | null;
uiFees?: number;
gasFees?: number;
status: PositionStatus;
signalIdentifier?: string | null;
identifier: string;
@@ -430,7 +433,6 @@ export enum PositionStatus {
Canceled = "Canceled",
Rejected = "Rejected",
Updating = "Updating",
PartiallyFilled = "PartiallyFilled",
Filled = "Filled",
Flipped = "Flipped",
Finished = "Finished",
@@ -950,6 +952,7 @@ export interface TopStrategiesViewModel {
export interface StrategyPerformance {
strategyName?: string | null;
pnL?: number;
netPnL?: number;
agentName?: string | null;
}
@@ -961,6 +964,7 @@ export interface StrategyRoiPerformance {
strategyName?: string | null;
roi?: number;
pnL?: number;
netPnL?: number;
volume?: number;
}
@@ -971,6 +975,7 @@ export interface TopAgentsByPnLViewModel {
export interface AgentPerformance {
agentName?: string | null;
pnL?: number;
netPnL?: number;
totalROI?: number;
totalVolume?: number;
activeStrategiesCount?: number;
@@ -981,6 +986,7 @@ export interface UserStrategyDetailsViewModel {
name?: string | null;
state?: BotStatus;
pnL?: number;
netPnL?: number;
roiPercentage?: number;
runtime?: Date;
winRate?: number;
@@ -1017,6 +1023,7 @@ export interface DailySnapshot {
totalStrategies?: number;
totalVolume?: number;
totalPnL?: number;
netPnL?: number;
totalOpenInterest?: number;
totalPositionCount?: number;
}
@@ -1038,16 +1045,18 @@ export interface PaginatedAgentIndexResponse {
export interface AgentSummaryViewModel {
agentName?: string | null;
totalPnL?: number;
netPnL?: number;
totalROI?: number;
wins?: number;
losses?: number;
activeStrategiesCount?: number;
totalVolume?: number;
totalBalance?: number;
totalFees?: number;
}
export enum SortableFields {
TotalPnL = "TotalPnL",
NetPnL = "NetPnL",
TotalROI = "TotalROI",
Wins = "Wins",
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>
<div className="stat bg-base-200 rounded-lg">
<div className="stat-title">PnL</div>
<div className="stat-value text-success">{formatCurrency(strategyData.pnL)}</div>
<div className="stat-title">Net PnL</div>
<div className="stat-value text-success">{formatCurrency(strategyData.netPnL)}</div>
</div>
<div className="stat bg-base-200 rounded-lg">
<div className="stat-title">Backtest</div>
@@ -283,8 +283,8 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
<div className="card-body">
<h3 className="card-title">PnL $</h3>
<div className="text-2xl font-bold">{formatCurrency(strategyData.pnL)}</div>
<div className="text-sm">
{formatCurrency((strategyData.pnL || 0) * 0.1)} Today
<div className="text-sm text-gray-400">
Net: {formatCurrency(strategyData.netPnL)}
</div>
</div>
</div>

View File

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