Add net Pnl in db
This commit is contained in:
@@ -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
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ public static class Enums
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum SortableFields
|
public enum SortableFields
|
||||||
{
|
{
|
||||||
TotalPnL,
|
NetPnL,
|
||||||
TotalROI,
|
TotalROI,
|
||||||
Wins,
|
Wins,
|
||||||
Losses,
|
Losses,
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
1445
src/Managing.Infrastructure.Database/Migrations/20250928144516_AddNetPnLToAgentSummary.Designer.cs
generated
Normal file
1445
src/Managing.Infrastructure.Database/Migrations/20250928144516_AddNetPnLToAgentSummary.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1449
src/Managing.Infrastructure.Database/Migrations/20250928145325_AddNetPnLToBot.Designer.cs
generated
Normal file
1449
src/Managing.Infrastructure.Database/Migrations/20250928145325_AddNetPnLToBot.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)");
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user