Update plateform summary
This commit is contained in:
@@ -340,16 +340,6 @@ public class DataController : ControllerBase
|
|||||||
[HttpGet("GetTopStrategies")]
|
[HttpGet("GetTopStrategies")]
|
||||||
public async Task<ActionResult<TopStrategiesViewModel>> GetTopStrategies()
|
public async Task<ActionResult<TopStrategiesViewModel>> GetTopStrategies()
|
||||||
{
|
{
|
||||||
const string cacheKey = "TopStrategies";
|
|
||||||
|
|
||||||
// Check if the top strategies are already cached
|
|
||||||
var cachedStrategies = _cacheService.GetValue<TopStrategiesViewModel>(cacheKey);
|
|
||||||
|
|
||||||
if (cachedStrategies != null)
|
|
||||||
{
|
|
||||||
return Ok(cachedStrategies);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get active bots
|
// Get active bots
|
||||||
var activeBots = await _mediator.Send(new GetBotsByStatusCommand(BotStatus.Running));
|
var activeBots = await _mediator.Send(new GetBotsByStatusCommand(BotStatus.Running));
|
||||||
|
|
||||||
@@ -372,12 +362,43 @@ public class DataController : ControllerBase
|
|||||||
.ToList()
|
.ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cache the result for 10 minutes
|
|
||||||
_cacheService.SaveValue(cacheKey, topStrategies, TimeSpan.FromMinutes(10));
|
|
||||||
|
|
||||||
return Ok(topStrategies);
|
return Ok(topStrategies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the top 3 performing strategies based on ROI percentage.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="TopStrategiesByRoiViewModel"/> containing the top performing strategies by ROI.</returns>
|
||||||
|
[HttpGet("GetTopStrategiesByRoi")]
|
||||||
|
public async Task<ActionResult<TopStrategiesByRoiViewModel>> GetTopStrategiesByRoi()
|
||||||
|
{
|
||||||
|
// Get active bots
|
||||||
|
var activeBots = await _mediator.Send(new GetBotsByStatusCommand(BotStatus.Running));
|
||||||
|
|
||||||
|
// Filter bots with valid ROI data and order by ROI
|
||||||
|
var botsWithRoi = activeBots
|
||||||
|
.Select(bot => new { Bot = bot, Roi = bot.Roi, PnL = bot.Pnl, Volume = bot.Volume })
|
||||||
|
.OrderByDescending(item => item.Roi)
|
||||||
|
.Take(3)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Map to view model
|
||||||
|
var topStrategiesByRoi = new TopStrategiesByRoiViewModel
|
||||||
|
{
|
||||||
|
TopStrategiesByRoi = botsWithRoi
|
||||||
|
.Select(item => new StrategyRoiPerformance
|
||||||
|
{
|
||||||
|
StrategyName = item.Bot.Name,
|
||||||
|
Roi = item.Roi,
|
||||||
|
PnL = item.PnL,
|
||||||
|
Volume = item.Volume
|
||||||
|
})
|
||||||
|
.ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(topStrategiesByRoi);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves list of the active strategies for a user with detailed information
|
/// Retrieves list of the active strategies for a user with detailed information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -474,13 +495,13 @@ public class DataController : ControllerBase
|
|||||||
{
|
{
|
||||||
// Get the platform summary grain
|
// Get the platform summary grain
|
||||||
var platformSummaryGrain = _grainFactory.GetGrain<IPlatformSummaryGrain>("platform-summary");
|
var platformSummaryGrain = _grainFactory.GetGrain<IPlatformSummaryGrain>("platform-summary");
|
||||||
|
|
||||||
// Get the platform summary from the grain (handles caching and real-time updates)
|
// Get the platform summary from the grain (handles caching and real-time updates)
|
||||||
var abstractionsSummary = await platformSummaryGrain.GetPlatformSummaryAsync();
|
var abstractionsSummary = await platformSummaryGrain.GetPlatformSummaryAsync();
|
||||||
|
|
||||||
// Convert to API ViewModel
|
// Convert to API ViewModel
|
||||||
var summary = abstractionsSummary.ToApiViewModel();
|
var summary = abstractionsSummary.ToApiViewModel();
|
||||||
|
|
||||||
return Ok(summary);
|
return Ok(summary);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Managing.Api.Models.Responses;
|
using Managing.Api.Models.Responses;
|
||||||
|
using Managing.Common;
|
||||||
using AbstractionsPlatformSummaryViewModel = Managing.Application.Abstractions.Models.PlatformSummaryViewModel;
|
using AbstractionsPlatformSummaryViewModel = Managing.Application.Abstractions.Models.PlatformSummaryViewModel;
|
||||||
|
|
||||||
namespace Managing.Api.Extensions;
|
namespace Managing.Api.Extensions;
|
||||||
@@ -28,13 +29,13 @@ public static class PlatformSummaryExtensions
|
|||||||
VolumeChange24h = abstractionsModel.VolumeChange24h,
|
VolumeChange24h = abstractionsModel.VolumeChange24h,
|
||||||
OpenInterestChange24h = abstractionsModel.OpenInterestChange24h,
|
OpenInterestChange24h = abstractionsModel.OpenInterestChange24h,
|
||||||
PositionCountChange24h = abstractionsModel.PositionCountChange24h,
|
PositionCountChange24h = abstractionsModel.PositionCountChange24h,
|
||||||
VolumeByAsset = abstractionsModel.VolumeByAsset ?? new Dictionary<string, decimal>(),
|
VolumeByAsset = abstractionsModel.VolumeByAsset ?? new Dictionary<Enums.Ticker, decimal>(),
|
||||||
PositionCountByAsset = abstractionsModel.PositionCountByAsset ?? new Dictionary<string, int>(),
|
PositionCountByAsset = abstractionsModel.PositionCountByAsset ?? new Dictionary<Enums.Ticker, int>(),
|
||||||
PositionCountByDirection = abstractionsModel.PositionCountByDirection?.ToDictionary(
|
PositionCountByDirection = abstractionsModel.PositionCountByDirection?.ToDictionary(
|
||||||
kvp => kvp.Key.ToString(),
|
kvp => kvp.Key,
|
||||||
kvp => kvp.Value) ?? new Dictionary<string, int>(),
|
kvp => kvp.Value) ?? new Dictionary<Enums.TradeDirection, int>(),
|
||||||
LastUpdated = abstractionsModel.LastUpdated,
|
LastUpdated = abstractionsModel.LastUpdated,
|
||||||
Last24HourSnapshot = abstractionsModel.Last24HourSnapshot
|
Last24HourSnapshot = abstractionsModel.Last24HourSnapshot
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Managing.Common;
|
||||||
|
|
||||||
namespace Managing.Api.Models.Responses
|
namespace Managing.Api.Models.Responses
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -9,39 +11,39 @@ namespace Managing.Api.Models.Responses
|
|||||||
/// AgentName of the agent
|
/// AgentName of the agent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total profit and loss in USD
|
/// Total profit and loss in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal TotalPnL { get; set; }
|
public decimal TotalPnL { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total return on investment as a percentage
|
/// Total return on investment as a percentage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal TotalROI { get; set; }
|
public decimal TotalROI { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of winning trades
|
/// Number of winning trades
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Wins { get; set; }
|
public int Wins { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of losing trades
|
/// Number of losing trades
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Losses { get; set; }
|
public int Losses { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of active strategies for this agent
|
/// Number of active strategies for this agent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ActiveStrategiesCount { get; set; }
|
public int ActiveStrategiesCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total volume traded by this agent in USD
|
/// Total volume traded by this agent in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal TotalVolume { get; set; }
|
public decimal TotalVolume { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Platform-wide statistics without individual agent details
|
/// Platform-wide statistics without individual agent details
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -51,96 +53,96 @@ namespace Managing.Api.Models.Responses
|
|||||||
/// Total number of agents on the platform
|
/// Total number of agents on the platform
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int TotalAgents { get; set; }
|
public required int TotalAgents { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total number of active strategies across all agents
|
/// Total number of active strategies across all agents
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int TotalActiveStrategies { get; set; }
|
public required int TotalActiveStrategies { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total platform-wide profit and loss in USD
|
/// Total platform-wide profit and loss in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal TotalPlatformPnL { get; set; }
|
public required decimal TotalPlatformPnL { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total volume traded across all agents in USD
|
/// Total volume traded across all agents in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal TotalPlatformVolume { get; set; }
|
public required decimal TotalPlatformVolume { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total volume traded across all agents in the last 24 hours in USD
|
/// Total volume traded across all agents in the last 24 hours in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal TotalPlatformVolumeLast24h { get; set; }
|
public required decimal TotalPlatformVolumeLast24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total open interest across all positions in USD
|
/// Total open interest across all positions in USD
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal TotalOpenInterest { get; set; }
|
public required decimal TotalOpenInterest { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total number of open positions across all strategies
|
/// Total number of open positions across all strategies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int TotalPositionCount { get; set; }
|
public required int TotalPositionCount { get; set; }
|
||||||
|
|
||||||
// 24-hour changes
|
// 24-hour changes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in agent count over the last 24 hours
|
/// Change in agent count over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int AgentsChange24h { get; set; }
|
public required int AgentsChange24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in strategy count over the last 24 hours
|
/// Change in strategy count over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int StrategiesChange24h { get; set; }
|
public required int StrategiesChange24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in PnL over the last 24 hours
|
/// Change in PnL over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal PnLChange24h { get; set; }
|
public required decimal PnLChange24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in volume over the last 24 hours
|
/// Change in volume over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal VolumeChange24h { get; set; }
|
public required decimal VolumeChange24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in open interest over the last 24 hours
|
/// Change in open interest over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required decimal OpenInterestChange24h { get; set; }
|
public required decimal OpenInterestChange24h { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change in position count over the last 24 hours
|
/// Change in position count over the last 24 hours
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required int PositionCountChange24h { get; set; }
|
public required int PositionCountChange24h { get; set; }
|
||||||
|
|
||||||
// Breakdowns
|
// Breakdowns
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Volume breakdown by asset/ticker
|
/// Volume breakdown by asset/ticker
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required Dictionary<string, decimal> VolumeByAsset { get; set; }
|
public required Dictionary<Enums.Ticker, decimal> VolumeByAsset { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Position count breakdown by asset/ticker
|
/// Position count breakdown by asset/ticker
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required Dictionary<string, int> PositionCountByAsset { get; set; }
|
public required Dictionary<Enums.Ticker, int> PositionCountByAsset { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Position count breakdown by direction (Long/Short)
|
/// Position count breakdown by direction (Long/Short)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required Dictionary<string, int> PositionCountByDirection { get; set; }
|
public required Dictionary<Enums.TradeDirection, int> PositionCountByDirection { get; set; }
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the data was last updated
|
/// When the data was last updated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required DateTime LastUpdated { get; set; }
|
public required DateTime LastUpdated { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the last 24-hour snapshot was taken
|
/// When the last 24-hour snapshot was taken
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required DateTime Last24HourSnapshot { get; set; }
|
public required DateTime Last24HourSnapshot { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Response model containing a list of agent summaries for the agent index
|
/// Response model containing a list of agent summaries for the agent index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -150,10 +152,10 @@ namespace Managing.Api.Models.Responses
|
|||||||
/// List of agent summaries sorted by performance
|
/// List of agent summaries sorted by performance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AgentSummaryViewModel> AgentSummaries { get; set; } = new List<AgentSummaryViewModel>();
|
public List<AgentSummaryViewModel> AgentSummaries { get; set; } = new List<AgentSummaryViewModel>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time filter applied to the data
|
/// Time filter applied to the data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TimeFilter { get; set; } = "Total";
|
public string TimeFilter { get; set; } = "Total";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,32 @@ namespace Managing.Api.Models.Responses
|
|||||||
public decimal PnL { get; set; }
|
public decimal PnL { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a high-performing strategy with its name and ROI value
|
||||||
|
/// </summary>
|
||||||
|
public class StrategyRoiPerformance
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the strategy bot
|
||||||
|
/// </summary>
|
||||||
|
public string StrategyName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return on Investment percentage of the strategy
|
||||||
|
/// </summary>
|
||||||
|
public decimal Roi { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Profit and Loss value of the strategy
|
||||||
|
/// </summary>
|
||||||
|
public decimal PnL { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume traded by the strategy
|
||||||
|
/// </summary>
|
||||||
|
public decimal Volume { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// View model containing the top performing strategies by ROI
|
/// View model containing the top performing strategies by ROI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,4 +52,15 @@ namespace Managing.Api.Models.Responses
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<StrategyPerformance> TopStrategies { get; set; } = new List<StrategyPerformance>();
|
public List<StrategyPerformance> TopStrategies { get; set; } = new List<StrategyPerformance>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View model containing the top performing strategies by ROI
|
||||||
|
/// </summary>
|
||||||
|
public class TopStrategiesByRoiViewModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// List of the top performing strategies by ROI
|
||||||
|
/// </summary>
|
||||||
|
public List<StrategyRoiPerformance> TopStrategiesByRoi { get; set; } = new List<StrategyRoiPerformance>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1904,6 +1904,41 @@ export class DataClient extends AuthorizedApiBase {
|
|||||||
return Promise.resolve<TopStrategiesViewModel>(null as any);
|
return Promise.resolve<TopStrategiesViewModel>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data_GetTopStrategiesByRoi(): Promise<TopStrategiesByRoiViewModel> {
|
||||||
|
let url_ = this.baseUrl + "/Data/GetTopStrategiesByRoi";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.transformOptions(options_).then(transformedOptions_ => {
|
||||||
|
return this.http.fetch(url_, transformedOptions_);
|
||||||
|
}).then((_response: Response) => {
|
||||||
|
return this.processData_GetTopStrategiesByRoi(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processData_GetTopStrategiesByRoi(response: Response): Promise<TopStrategiesByRoiViewModel> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as TopStrategiesByRoiViewModel;
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<TopStrategiesByRoiViewModel>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
data_GetUserStrategies(agentName: string | null | undefined): Promise<UserStrategyDetailsViewModel[]> {
|
data_GetUserStrategies(agentName: string | null | undefined): Promise<UserStrategyDetailsViewModel[]> {
|
||||||
let url_ = this.baseUrl + "/Data/GetUserStrategies?";
|
let url_ = this.baseUrl + "/Data/GetUserStrategies?";
|
||||||
if (agentName !== undefined && agentName !== null)
|
if (agentName !== undefined && agentName !== null)
|
||||||
@@ -4554,6 +4589,17 @@ export interface StrategyPerformance {
|
|||||||
pnL?: number;
|
pnL?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TopStrategiesByRoiViewModel {
|
||||||
|
topStrategiesByRoi?: StrategyRoiPerformance[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StrategyRoiPerformance {
|
||||||
|
strategyName?: string | null;
|
||||||
|
roi?: number;
|
||||||
|
pnL?: number;
|
||||||
|
volume?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface UserStrategyDetailsViewModel {
|
export interface UserStrategyDetailsViewModel {
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
state?: BotStatus;
|
state?: BotStatus;
|
||||||
@@ -4585,9 +4631,9 @@ export interface PlatformSummaryViewModel {
|
|||||||
volumeChange24h?: number;
|
volumeChange24h?: number;
|
||||||
openInterestChange24h?: number;
|
openInterestChange24h?: number;
|
||||||
positionCountChange24h?: number;
|
positionCountChange24h?: number;
|
||||||
volumeByAsset?: { [key: string]: number; } | null;
|
volumeByAsset?: { [key in keyof typeof Ticker]?: number; } | null;
|
||||||
positionCountByAsset?: { [key: string]: number; } | null;
|
positionCountByAsset?: { [key in keyof typeof Ticker]?: number; } | null;
|
||||||
positionCountByDirection?: { [key: string]: number; } | null;
|
positionCountByDirection?: { [key in keyof typeof TradeDirection]?: number; } | null;
|
||||||
lastUpdated?: Date;
|
lastUpdated?: Date;
|
||||||
last24HourSnapshot?: Date;
|
last24HourSnapshot?: Date;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -944,6 +944,17 @@ export interface StrategyPerformance {
|
|||||||
pnL?: number;
|
pnL?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TopStrategiesByRoiViewModel {
|
||||||
|
topStrategiesByRoi?: StrategyRoiPerformance[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StrategyRoiPerformance {
|
||||||
|
strategyName?: string | null;
|
||||||
|
roi?: number;
|
||||||
|
pnL?: number;
|
||||||
|
volume?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface UserStrategyDetailsViewModel {
|
export interface UserStrategyDetailsViewModel {
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
state?: BotStatus;
|
state?: BotStatus;
|
||||||
@@ -975,9 +986,9 @@ export interface PlatformSummaryViewModel {
|
|||||||
volumeChange24h?: number;
|
volumeChange24h?: number;
|
||||||
openInterestChange24h?: number;
|
openInterestChange24h?: number;
|
||||||
positionCountChange24h?: number;
|
positionCountChange24h?: number;
|
||||||
volumeByAsset?: { [key: string]: number; } | null;
|
volumeByAsset?: { [key in keyof typeof Ticker]?: number; } | null;
|
||||||
positionCountByAsset?: { [key: string]: number; } | null;
|
positionCountByAsset?: { [key in keyof typeof Ticker]?: number; } | null;
|
||||||
positionCountByDirection?: { [key: string]: number; } | null;
|
positionCountByDirection?: { [key in keyof typeof TradeDirection]?: number; } | null;
|
||||||
lastUpdated?: Date;
|
lastUpdated?: Date;
|
||||||
last24HourSnapshot?: Date;
|
last24HourSnapshot?: Date;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
import React, {useEffect, useState} from 'react'
|
||||||
import useApiUrlStore from '../../app/store/apiStore'
|
import useApiUrlStore from '../../app/store/apiStore'
|
||||||
import {DataClient, type PlatformSummaryViewModel, type TopStrategiesViewModel} from '../../generated/ManagingApi'
|
import {
|
||||||
|
DataClient,
|
||||||
|
type PlatformSummaryViewModel,
|
||||||
|
type TopStrategiesByRoiViewModel,
|
||||||
|
type TopStrategiesViewModel
|
||||||
|
} from '../../generated/ManagingApi'
|
||||||
|
|
||||||
function PlatformSummary({ index }: { index: number }) {
|
function PlatformSummary({ index }: { index: number }) {
|
||||||
const { apiUrl } = useApiUrlStore()
|
const { apiUrl } = useApiUrlStore()
|
||||||
const [platformData, setPlatformData] = useState<PlatformSummaryViewModel | null>(null)
|
const [platformData, setPlatformData] = useState<PlatformSummaryViewModel | null>(null)
|
||||||
|
|
||||||
const [topStrategies, setTopStrategies] = useState<TopStrategiesViewModel | null>(null)
|
const [topStrategies, setTopStrategies] = useState<TopStrategiesViewModel | null>(null)
|
||||||
|
const [topStrategiesByRoi, setTopStrategiesByRoi] = useState<TopStrategiesByRoiViewModel | null>(null)
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
@@ -18,13 +24,15 @@ function PlatformSummary({ index }: { index: number }) {
|
|||||||
const client = new DataClient({}, apiUrl)
|
const client = new DataClient({}, apiUrl)
|
||||||
|
|
||||||
// Fetch all platform data in parallel
|
// Fetch all platform data in parallel
|
||||||
const [platform, top] = await Promise.all([
|
const [platform, top, topRoi] = await Promise.all([
|
||||||
client.data_GetPlatformSummary(),
|
client.data_GetPlatformSummary(),
|
||||||
client.data_GetTopStrategies()
|
client.data_GetTopStrategies(),
|
||||||
|
client.data_GetTopStrategiesByRoi()
|
||||||
])
|
])
|
||||||
|
|
||||||
setPlatformData(platform)
|
setPlatformData(platform)
|
||||||
setTopStrategies(top)
|
setTopStrategies(top)
|
||||||
|
setTopStrategiesByRoi(topRoi)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError('Failed to fetch platform data')
|
setError('Failed to fetch platform data')
|
||||||
console.error('Error fetching platform data:', err)
|
console.error('Error fetching platform data:', err)
|
||||||
@@ -164,17 +172,17 @@ function PlatformSummary({ index }: { index: number }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Top 3 Rising (placeholder - using same data for now) */}
|
{/* Top 3 Rising (by ROI) */}
|
||||||
<div className="bg-base-200 rounded-lg p-6">
|
<div className="bg-base-200 rounded-lg p-6">
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<span className="text-2xl">📈</span>
|
<span className="text-2xl">📈</span>
|
||||||
<h3 className="text-lg font-semibold text-gray-400">Top 3 Rising</h3>
|
<h3 className="text-lg font-semibold text-gray-400">Top 3 by ROI</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{topStrategies?.topStrategies?.slice(0, 3).map((strategy, index) => (
|
{topStrategiesByRoi?.topStrategiesByRoi?.slice(0, 3).map((strategy, index) => (
|
||||||
<div key={index} className="flex items-center justify-between">
|
<div key={index} className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
|
<div className="w-8 h-8 bg-green-500 rounded-full flex items-center justify-center">
|
||||||
<span className="text-xs font-bold text-white">
|
<span className="text-xs font-bold text-white">
|
||||||
{strategy.strategyName?.charAt(0) || 'S'}
|
{strategy.strategyName?.charAt(0) || 'S'}
|
||||||
</span>
|
</span>
|
||||||
@@ -183,49 +191,22 @@ function PlatformSummary({ index }: { index: number }) {
|
|||||||
<div className="text-sm text-white font-medium">
|
<div className="text-sm text-white font-medium">
|
||||||
{strategy.strategyName || '[Strategy Name]'}
|
{strategy.strategyName || '[Strategy Name]'}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-gray-400">📧</div>
|
<div className="text-xs text-gray-400">
|
||||||
|
Vol: {formatCurrency(strategy.volume || 0)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="text-right">
|
||||||
<span className="text-red-500">🔴</span>
|
<div className={`text-sm font-bold ${(strategy.roi || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
||||||
<span className="text-sm text-white">1,200</span>
|
{(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)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)) || (
|
)) || (
|
||||||
<div className="text-gray-500 text-sm">No rising strategies found</div>
|
<div className="text-gray-500 text-sm">No ROI data available</div>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Top 3 Strategies */}
|
|
||||||
<div className="bg-base-200 rounded-lg p-6">
|
|
||||||
<div className="flex items-center gap-2 mb-4">
|
|
||||||
<span className="text-2xl">⚡</span>
|
|
||||||
<h3 className="text-lg font-semibold text-gray-400">Top 3 Strategies</h3>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-3">
|
|
||||||
{topStrategies?.topStrategies?.slice(0, 3).map((strategy, index) => {
|
|
||||||
// Calculate a mock percentage for display
|
|
||||||
const percentage = Math.abs((strategy.pnL || 0) / 100 * 10).toFixed(0)
|
|
||||||
return (
|
|
||||||
<div key={index} className="flex items-center justify-between">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-8 h-8 bg-yellow-500 rounded-full flex items-center justify-center">
|
|
||||||
<span className="text-xs font-bold text-black">⚡</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="text-sm text-white font-medium">
|
|
||||||
{strategy.strategyName || '[Strategy Name]'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="text-green-500 text-sm font-bold">
|
|
||||||
+{percentage}%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}) || (
|
|
||||||
<div className="text-gray-500 text-sm">No strategies found</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user