Update front and fix back
This commit is contained in:
@@ -28,11 +28,11 @@ public static class PlatformSummaryExtensions
|
||||
VolumeChange24h = abstractionsModel.VolumeChange24h,
|
||||
OpenInterestChange24h = abstractionsModel.OpenInterestChange24h,
|
||||
PositionCountChange24h = abstractionsModel.PositionCountChange24h,
|
||||
VolumeByAsset = abstractionsModel.VolumeByAsset,
|
||||
PositionCountByAsset = abstractionsModel.PositionCountByAsset,
|
||||
PositionCountByDirection = abstractionsModel.PositionCountByDirection.ToDictionary(
|
||||
VolumeByAsset = abstractionsModel.VolumeByAsset ?? new Dictionary<string, decimal>(),
|
||||
PositionCountByAsset = abstractionsModel.PositionCountByAsset ?? new Dictionary<string, int>(),
|
||||
PositionCountByDirection = abstractionsModel.PositionCountByDirection?.ToDictionary(
|
||||
kvp => kvp.Key.ToString(),
|
||||
kvp => kvp.Value),
|
||||
kvp => kvp.Value) ?? new Dictionary<string, int>(),
|
||||
LastUpdated = abstractionsModel.LastUpdated,
|
||||
Last24HourSnapshot = abstractionsModel.Last24HourSnapshot
|
||||
};
|
||||
|
||||
@@ -50,95 +50,95 @@ namespace Managing.Api.Models.Responses
|
||||
/// <summary>
|
||||
/// Total number of agents on the platform
|
||||
/// </summary>
|
||||
public int TotalAgents { get; set; }
|
||||
public required int TotalAgents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total number of active strategies across all agents
|
||||
/// </summary>
|
||||
public int TotalActiveStrategies { get; set; }
|
||||
public required int TotalActiveStrategies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total platform-wide profit and loss in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformPnL { get; set; }
|
||||
public required decimal TotalPlatformPnL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total volume traded across all agents in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformVolume { get; set; }
|
||||
public required decimal TotalPlatformVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total volume traded across all agents in the last 24 hours in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformVolumeLast24h { get; set; }
|
||||
public required decimal TotalPlatformVolumeLast24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total open interest across all positions in USD
|
||||
/// </summary>
|
||||
public decimal TotalOpenInterest { get; set; }
|
||||
public required decimal TotalOpenInterest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total number of open positions across all strategies
|
||||
/// </summary>
|
||||
public int TotalPositionCount { get; set; }
|
||||
public required int TotalPositionCount { get; set; }
|
||||
|
||||
// 24-hour changes
|
||||
/// <summary>
|
||||
/// Change in agent count over the last 24 hours
|
||||
/// </summary>
|
||||
public int AgentsChange24h { get; set; }
|
||||
public required int AgentsChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in strategy count over the last 24 hours
|
||||
/// </summary>
|
||||
public int StrategiesChange24h { get; set; }
|
||||
public required int StrategiesChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in PnL over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal PnLChange24h { get; set; }
|
||||
public required decimal PnLChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in volume over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal VolumeChange24h { get; set; }
|
||||
public required decimal VolumeChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in open interest over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal OpenInterestChange24h { get; set; }
|
||||
public required decimal OpenInterestChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in position count over the last 24 hours
|
||||
/// </summary>
|
||||
public int PositionCountChange24h { get; set; }
|
||||
public required int PositionCountChange24h { get; set; }
|
||||
|
||||
// Breakdowns
|
||||
/// <summary>
|
||||
/// Volume breakdown by asset/ticker
|
||||
/// </summary>
|
||||
public Dictionary<string, decimal> VolumeByAsset { get; set; } = new();
|
||||
public required Dictionary<string, decimal> VolumeByAsset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position count breakdown by asset/ticker
|
||||
/// </summary>
|
||||
public Dictionary<string, int> PositionCountByAsset { get; set; } = new();
|
||||
public required Dictionary<string, int> PositionCountByAsset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position count breakdown by direction (Long/Short)
|
||||
/// </summary>
|
||||
public Dictionary<string, int> PositionCountByDirection { get; set; } = new();
|
||||
public required Dictionary<string, int> PositionCountByDirection { get; set; }
|
||||
|
||||
// Metadata
|
||||
/// <summary>
|
||||
/// When the data was last updated
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; }
|
||||
public required DateTime LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the last 24-hour snapshot was taken
|
||||
/// </summary>
|
||||
public DateTime Last24HourSnapshot { get; set; }
|
||||
public required DateTime Last24HourSnapshot { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -50,69 +50,125 @@ public interface IPlatformSummaryGrain : IGrainWithStringKey
|
||||
/// <summary>
|
||||
/// Base class for platform metrics events
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public abstract class PlatformMetricsEvent
|
||||
{
|
||||
[Id(0)]
|
||||
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a new strategy is deployed
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class StrategyDeployedEvent : PlatformMetricsEvent
|
||||
{
|
||||
[Id(1)]
|
||||
public Guid StrategyId { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public string AgentName { get; set; } = string.Empty;
|
||||
|
||||
[Id(3)]
|
||||
public string StrategyName { get; set; } = string.Empty;
|
||||
|
||||
[Id(4)]
|
||||
public decimal InitialVolume { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal InitialPnL { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a strategy is stopped
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class StrategyStoppedEvent : PlatformMetricsEvent
|
||||
{
|
||||
[Id(1)]
|
||||
public Guid StrategyId { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public string AgentName { get; set; } = string.Empty;
|
||||
|
||||
[Id(3)]
|
||||
public string StrategyName { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a new position is opened
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class PositionOpenedEvent : PlatformMetricsEvent
|
||||
{
|
||||
[Id(1)]
|
||||
public Guid PositionId { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public Guid StrategyId { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public string Ticker { get; set; } = string.Empty;
|
||||
|
||||
[Id(4)]
|
||||
public decimal Size { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal NotionalValue { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public TradeDirection Direction { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a position is closed
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class PositionClosedEvent : PlatformMetricsEvent
|
||||
{
|
||||
[Id(1)]
|
||||
public Guid PositionId { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public Guid StrategyId { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public string Ticker { get; set; } = string.Empty;
|
||||
|
||||
[Id(4)]
|
||||
public decimal RealizedPnL { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal Volume { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a trade is executed
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class TradeExecutedEvent : PlatformMetricsEvent
|
||||
{
|
||||
[Id(1)]
|
||||
public Guid TradeId { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public Guid PositionId { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public Guid StrategyId { get; set; }
|
||||
|
||||
[Id(4)]
|
||||
public string Ticker { get; set; } = string.Empty;
|
||||
|
||||
[Id(5)]
|
||||
public decimal Volume { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public decimal PnL { get; set; }
|
||||
|
||||
[Id(7)]
|
||||
public decimal Fee { get; set; }
|
||||
|
||||
[Id(8)]
|
||||
public TradeDirection Direction { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Orleans;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Grains;
|
||||
@@ -5,64 +6,127 @@ namespace Managing.Application.Abstractions.Grains;
|
||||
/// <summary>
|
||||
/// State model for Platform Summary Grain
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class PlatformSummaryGrainState
|
||||
{
|
||||
[Id(0)]
|
||||
public DateTime LastUpdated { get; set; }
|
||||
|
||||
[Id(1)]
|
||||
public DateTime LastSnapshot { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public bool HasPendingChanges { get; set; }
|
||||
|
||||
// Current metrics
|
||||
[Id(3)]
|
||||
public int TotalAgents { get; set; }
|
||||
|
||||
[Id(4)]
|
||||
public int TotalActiveStrategies { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal TotalPlatformPnL { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public decimal TotalPlatformVolume { get; set; }
|
||||
|
||||
[Id(7)]
|
||||
public decimal TotalOpenInterest { get; set; }
|
||||
|
||||
[Id(8)]
|
||||
public int TotalPositionCount { get; set; }
|
||||
|
||||
// 24-hour ago values (for comparison)
|
||||
[Id(9)]
|
||||
public int TotalAgents24hAgo { get; set; }
|
||||
|
||||
[Id(10)]
|
||||
public int TotalActiveStrategies24hAgo { get; set; }
|
||||
|
||||
[Id(11)]
|
||||
public decimal TotalPlatformPnL24hAgo { get; set; }
|
||||
|
||||
[Id(12)]
|
||||
public decimal TotalPlatformVolume24hAgo { get; set; }
|
||||
|
||||
[Id(13)]
|
||||
public decimal TotalOpenInterest24hAgo { get; set; }
|
||||
|
||||
[Id(14)]
|
||||
public int TotalPositionCount24hAgo { get; set; }
|
||||
|
||||
// Historical snapshots
|
||||
[Id(15)]
|
||||
public List<HourlySnapshot> HourlySnapshots { get; set; } = new();
|
||||
|
||||
[Id(16)]
|
||||
public List<DailySnapshot> DailySnapshots { get; set; } = new();
|
||||
|
||||
// Volume breakdown by asset
|
||||
[Id(17)]
|
||||
public Dictionary<string, decimal> VolumeByAsset { get; set; } = new();
|
||||
|
||||
// Position count breakdown
|
||||
[Id(18)]
|
||||
public Dictionary<string, int> PositionCountByAsset { get; set; } = new();
|
||||
|
||||
[Id(19)]
|
||||
public Dictionary<TradeDirection, int> PositionCountByDirection { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hourly snapshot of platform metrics
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class HourlySnapshot
|
||||
{
|
||||
[Id(0)]
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
[Id(1)]
|
||||
public int TotalAgents { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public int TotalStrategies { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public decimal TotalVolume { get; set; }
|
||||
|
||||
[Id(4)]
|
||||
public decimal TotalPnL { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal TotalOpenInterest { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public int TotalPositionCount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Daily snapshot of platform metrics
|
||||
/// </summary>
|
||||
[GenerateSerializer]
|
||||
public class DailySnapshot
|
||||
{
|
||||
[Id(0)]
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
[Id(1)]
|
||||
public int TotalAgents { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
public int TotalStrategies { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public decimal TotalVolume { get; set; }
|
||||
|
||||
[Id(4)]
|
||||
public decimal TotalPnL { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public decimal TotalOpenInterest { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public int TotalPositionCount { get; set; }
|
||||
}
|
||||
|
||||
@@ -10,93 +10,93 @@ public class PlatformSummaryViewModel
|
||||
/// <summary>
|
||||
/// Total number of agents on the platform
|
||||
/// </summary>
|
||||
public int TotalAgents { get; set; }
|
||||
public required int TotalAgents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total number of active strategies across all agents
|
||||
/// </summary>
|
||||
public int TotalActiveStrategies { get; set; }
|
||||
public required int TotalActiveStrategies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total platform-wide profit and loss in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformPnL { get; set; }
|
||||
public required decimal TotalPlatformPnL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total volume traded across all agents in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformVolume { get; set; }
|
||||
public required decimal TotalPlatformVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total volume traded across all agents in the last 24 hours in USD
|
||||
/// </summary>
|
||||
public decimal TotalPlatformVolumeLast24h { get; set; }
|
||||
public required decimal TotalPlatformVolumeLast24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total open interest across all positions in USD
|
||||
/// </summary>
|
||||
public decimal TotalOpenInterest { get; set; }
|
||||
public required decimal TotalOpenInterest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total number of open positions across all strategies
|
||||
/// </summary>
|
||||
public int TotalPositionCount { get; set; }
|
||||
public required int TotalPositionCount { get; set; }
|
||||
|
||||
// 24-hour changes
|
||||
/// <summary>
|
||||
/// Change in agent count over the last 24 hours
|
||||
/// </summary>
|
||||
public int AgentsChange24h { get; set; }
|
||||
public required int AgentsChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in strategy count over the last 24 hours
|
||||
/// </summary>
|
||||
public int StrategiesChange24h { get; set; }
|
||||
public required int StrategiesChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in PnL over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal PnLChange24h { get; set; }
|
||||
public required decimal PnLChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in volume over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal VolumeChange24h { get; set; }
|
||||
public required decimal VolumeChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in open interest over the last 24 hours
|
||||
/// </summary>
|
||||
public decimal OpenInterestChange24h { get; set; }
|
||||
public required decimal OpenInterestChange24h { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change in position count over the last 24 hours
|
||||
/// </summary>
|
||||
public int PositionCountChange24h { get; set; }
|
||||
public required int PositionCountChange24h { get; set; }
|
||||
|
||||
// Breakdowns
|
||||
/// <summary>
|
||||
/// Volume breakdown by asset/ticker
|
||||
/// </summary>
|
||||
public Dictionary<string, decimal> VolumeByAsset { get; set; } = new();
|
||||
public required Dictionary<string, decimal> VolumeByAsset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position count breakdown by asset/ticker
|
||||
/// </summary>
|
||||
public Dictionary<string, int> PositionCountByAsset { get; set; } = new();
|
||||
public required Dictionary<string, int> PositionCountByAsset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position count breakdown by direction (Long/Short)
|
||||
/// </summary>
|
||||
public Dictionary<TradeDirection, int> PositionCountByDirection { get; set; } = new();
|
||||
public required Dictionary<TradeDirection, int> PositionCountByDirection { get; set; }
|
||||
|
||||
// Metadata
|
||||
/// <summary>
|
||||
/// When the data was last updated
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; }
|
||||
public required DateTime LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the last 24-hour snapshot was taken
|
||||
/// </summary>
|
||||
public DateTime Last24HourSnapshot { get; set; }
|
||||
public required DateTime Last24HourSnapshot { get; set; }
|
||||
}
|
||||
|
||||
@@ -168,7 +168,8 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
|
||||
_state.State.PositionCountByDirection[TradeDirection.Long] = totalLongPositions;
|
||||
_state.State.PositionCountByDirection[TradeDirection.Short] = totalShortPositions;
|
||||
|
||||
_logger.LogDebug("Updated position breakdown from bot statistics: {AssetCount} assets, Long={LongPositions}, Short={ShortPositions}",
|
||||
_logger.LogDebug(
|
||||
"Updated position breakdown from bot statistics: {AssetCount} assets, Long={LongPositions}, Short={ShortPositions}",
|
||||
positionsByAsset.Count, totalLongPositions, totalShortPositions);
|
||||
}
|
||||
else
|
||||
@@ -222,7 +223,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
|
||||
return Task.FromResult(_state.State.TotalPlatformPnL);
|
||||
}
|
||||
|
||||
public Task<decimal> GetTotalOpenInterestAsync()
|
||||
public Task<decimal> GetTotalOpenInterest()
|
||||
{
|
||||
return Task.FromResult(_state.State.TotalOpenInterest);
|
||||
}
|
||||
@@ -276,6 +277,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
|
||||
{
|
||||
_state.State.VolumeByAsset[asset] = 0;
|
||||
}
|
||||
|
||||
_state.State.VolumeByAsset[asset] += evt.Volume;
|
||||
|
||||
_state.State.HasPendingChanges = true;
|
||||
@@ -296,6 +298,7 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
|
||||
{
|
||||
_state.State.VolumeByAsset[asset] = 0;
|
||||
}
|
||||
|
||||
_state.State.VolumeByAsset[asset] += evt.Volume;
|
||||
|
||||
_state.State.HasPendingChanges = true;
|
||||
@@ -404,9 +407,9 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable
|
||||
PositionCountChange24h = state.TotalPositionCount - state.TotalPositionCount24hAgo,
|
||||
|
||||
// Breakdowns
|
||||
VolumeByAsset = state.VolumeByAsset,
|
||||
PositionCountByAsset = state.PositionCountByAsset,
|
||||
PositionCountByDirection = state.PositionCountByDirection,
|
||||
VolumeByAsset = state.VolumeByAsset ?? new Dictionary<string, decimal>(),
|
||||
PositionCountByAsset = state.PositionCountByAsset ?? new Dictionary<string, int>(),
|
||||
PositionCountByDirection = state.PositionCountByDirection ?? new Dictionary<TradeDirection, int>(),
|
||||
|
||||
// Metadata
|
||||
LastUpdated = state.LastUpdated,
|
||||
|
||||
@@ -4577,6 +4577,19 @@ export interface PlatformSummaryViewModel {
|
||||
totalPlatformPnL?: number;
|
||||
totalPlatformVolume?: number;
|
||||
totalPlatformVolumeLast24h?: number;
|
||||
totalOpenInterest?: number;
|
||||
totalPositionCount?: number;
|
||||
agentsChange24h?: number;
|
||||
strategiesChange24h?: number;
|
||||
pnLChange24h?: number;
|
||||
volumeChange24h?: number;
|
||||
openInterestChange24h?: number;
|
||||
positionCountChange24h?: number;
|
||||
volumeByAsset?: { [key: string]: number; } | null;
|
||||
positionCountByAsset?: { [key: string]: number; } | null;
|
||||
positionCountByDirection?: { [key: string]: number; } | null;
|
||||
lastUpdated?: Date;
|
||||
last24HourSnapshot?: Date;
|
||||
}
|
||||
|
||||
export interface PaginatedAgentIndexResponse {
|
||||
|
||||
@@ -967,6 +967,19 @@ export interface PlatformSummaryViewModel {
|
||||
totalPlatformPnL?: number;
|
||||
totalPlatformVolume?: number;
|
||||
totalPlatformVolumeLast24h?: number;
|
||||
totalOpenInterest?: number;
|
||||
totalPositionCount?: number;
|
||||
agentsChange24h?: number;
|
||||
strategiesChange24h?: number;
|
||||
pnLChange24h?: number;
|
||||
volumeChange24h?: number;
|
||||
openInterestChange24h?: number;
|
||||
positionCountChange24h?: number;
|
||||
volumeByAsset?: { [key: string]: number; } | null;
|
||||
positionCountByAsset?: { [key: string]: number; } | null;
|
||||
positionCountByDirection?: { [key: string]: number; } | null;
|
||||
lastUpdated?: Date;
|
||||
last24HourSnapshot?: Date;
|
||||
}
|
||||
|
||||
export interface PaginatedAgentIndexResponse {
|
||||
|
||||
@@ -85,6 +85,12 @@ function PlatformSummary({ index }: { index: number }) {
|
||||
)
|
||||
}
|
||||
|
||||
const formatPercentageChange = (current: number, change: number) => {
|
||||
if (current === 0) return '0%'
|
||||
const percentage = (change / (current - change)) * 100
|
||||
return `${percentage >= 0 ? '+' : ''}${percentage.toFixed(1)}%`
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-96">
|
||||
@@ -121,8 +127,11 @@ function PlatformSummary({ index }: { index: number }) {
|
||||
<div className="text-3xl font-bold text-white mb-1">
|
||||
{formatCurrency(platformData?.totalPlatformVolume || 0)}
|
||||
</div>
|
||||
<div className="text-green-500">
|
||||
+{formatCurrency(platformData?.totalPlatformVolumeLast24h || 0)} Today
|
||||
<div className={`text-sm ${(platformData?.volumeChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{(platformData?.volumeChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.volumeChange24h || 0)} Today
|
||||
<span className="ml-2 text-gray-400">
|
||||
({formatPercentageChange(platformData?.totalPlatformVolume || 0, platformData?.volumeChange24h || 0)})
|
||||
</span>
|
||||
</div>
|
||||
{/* Simple chart placeholder - you can replace with actual chart */}
|
||||
<div className="mt-4 h-16 flex items-end">
|
||||
@@ -230,19 +239,25 @@ function PlatformSummary({ index }: { index: number }) {
|
||||
</div>
|
||||
|
||||
{/* Platform Summary Stats */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Agents</h3>
|
||||
<div className="text-3xl font-bold text-white">
|
||||
<div className="text-3xl font-bold text-white mb-1">
|
||||
{formatNumber(platformData?.totalAgents || 0)}
|
||||
</div>
|
||||
<div className={`text-sm ${(platformData?.agentsChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{formatChangeIndicator(platformData?.agentsChange24h || 0)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Active Strategies</h3>
|
||||
<div className="text-3xl font-bold text-white">
|
||||
<div className="text-3xl font-bold text-white mb-1">
|
||||
{formatNumber(platformData?.totalActiveStrategies || 0)}
|
||||
</div>
|
||||
<div className={`text-sm ${(platformData?.strategiesChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{formatChangeIndicator(platformData?.strategiesChange24h || 0)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
@@ -250,6 +265,131 @@ function PlatformSummary({ index }: { index: number }) {
|
||||
<div 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 ${(platformData?.pnLChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{(platformData?.pnLChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.pnLChange24h || 0)} Today
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Open Interest</h3>
|
||||
<div className="text-3xl font-bold text-white mb-1">
|
||||
{formatCurrency(platformData?.totalOpenInterest || 0)}
|
||||
</div>
|
||||
<div className={`text-sm ${(platformData?.openInterestChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{(platformData?.openInterestChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.openInterestChange24h || 0)} Today
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Position Metrics */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Positions</h3>
|
||||
<div className="text-3xl font-bold text-white mb-1">
|
||||
{formatNumber(platformData?.totalPositionCount || 0)}
|
||||
</div>
|
||||
<div className={`text-sm ${(platformData?.positionCountChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||
{formatChangeIndicator(platformData?.positionCountChange24h || 0)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Long Positions</h3>
|
||||
<div className="text-3xl font-bold text-green-400 mb-1">
|
||||
{formatNumber(platformData?.positionCountByDirection?.Long || 0)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-400">
|
||||
{platformData?.totalPositionCount ?
|
||||
((platformData.positionCountByDirection?.Long || 0) / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-2">Short Positions</h3>
|
||||
<div className="text-3xl font-bold text-red-400 mb-1">
|
||||
{formatNumber(platformData?.positionCountByDirection?.Short || 0)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-400">
|
||||
{platformData?.totalPositionCount ?
|
||||
((platformData.positionCountByDirection?.Short || 0) / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Volume and Positions by Asset */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
|
||||
{/* Volume by Asset */}
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-4">Volume by Asset</h3>
|
||||
<div className="space-y-3 max-h-80 overflow-y-auto">
|
||||
{platformData?.volumeByAsset && Object.keys(platformData.volumeByAsset).length > 0 ? (
|
||||
Object.entries(platformData.volumeByAsset)
|
||||
.sort(([,a], [,b]) => b - a)
|
||||
.slice(0, 10)
|
||||
.map(([asset, volume]) => (
|
||||
<div key={asset} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
|
||||
<span className="text-xs font-bold text-white">
|
||||
{asset.substring(0, 2)}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-white font-medium">{asset}</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-white font-semibold">
|
||||
{formatCurrency(volume)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-gray-500 text-sm">No volume data available</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Positions by Asset */}
|
||||
<div className="bg-base-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-400 mb-4">Positions by Asset</h3>
|
||||
<div className="space-y-3 max-h-80 overflow-y-auto">
|
||||
{platformData?.positionCountByAsset && Object.keys(platformData.positionCountByAsset).length > 0 ? (
|
||||
Object.entries(platformData.positionCountByAsset)
|
||||
.sort(([,a], [,b]) => b - a)
|
||||
.slice(0, 10)
|
||||
.map(([asset, count]) => (
|
||||
<div key={asset} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 bg-purple-500 rounded-full flex items-center justify-center">
|
||||
<span className="text-xs font-bold text-white">
|
||||
{asset.substring(0, 2)}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-white font-medium">{asset}</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-white font-semibold">
|
||||
{formatNumber(count)} positions
|
||||
</div>
|
||||
<div className="text-xs text-gray-400">
|
||||
{platformData?.totalPositionCount ?
|
||||
(count / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-gray-500 text-sm">No position data available</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Data Freshness Indicator */}
|
||||
<div className="bg-base-200 rounded-lg p-4">
|
||||
<div className="flex items-center justify-between text-sm text-gray-400">
|
||||
<span>Last updated: {platformData?.lastUpdated ? new Date(platformData.lastUpdated).toLocaleString() : 'Unknown'}</span>
|
||||
<span>24h snapshot: {platformData?.last24HourSnapshot ? new Date(platformData.last24HourSnapshot).toLocaleString() : 'Unknown'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user