Update Agent search to display the balance tracked

This commit is contained in:
2025-10-03 15:55:47 +07:00
parent 7c13ad5f06
commit 83ee4f633c
3 changed files with 146 additions and 18 deletions

View File

@@ -4497,12 +4497,28 @@ export interface UserStrategyDetailsViewModel {
volumeLast24H?: number; volumeLast24H?: number;
wins?: number; wins?: number;
losses?: number; losses?: number;
positions?: Position[] | null; positions?: PositionViewModel[] | null;
identifier?: string; identifier?: string;
walletBalances?: { [key: string]: number; } | null; walletBalances?: { [key: string]: number; } | null;
ticker?: Ticker; ticker?: Ticker;
} }
export interface PositionViewModel {
date: Date;
accountId: number;
originDirection: TradeDirection;
ticker: Ticker;
Open: Trade;
StopLoss: Trade;
TakeProfit1: Trade;
ProfitAndLoss?: ProfitAndLoss | null;
uiFees?: number;
gasFees?: number;
status: PositionStatus;
signalIdentifier?: string | null;
identifier: string;
}
export interface PlatformSummaryViewModel { export interface PlatformSummaryViewModel {
lastUpdated?: Date; lastUpdated?: Date;
lastSnapshot?: Date; lastSnapshot?: Date;
@@ -4556,6 +4572,7 @@ export interface AgentSummaryViewModel {
totalVolume?: number; totalVolume?: number;
totalBalance?: number; totalBalance?: number;
totalFees?: number; totalFees?: number;
backtestCount?: number;
} }
export enum SortableFields { export enum SortableFields {
@@ -4577,8 +4594,7 @@ export interface AgentBalanceHistory {
export interface AgentBalance { export interface AgentBalance {
agentName?: string | null; agentName?: string | null;
totalValue?: number; totalBalanceValue?: number;
totalAccountUsdValue?: number;
botsAllocationUsdValue?: number; botsAllocationUsdValue?: number;
pnL?: number; pnL?: number;
time?: Date; time?: Date;

View File

@@ -980,12 +980,28 @@ export interface UserStrategyDetailsViewModel {
volumeLast24H?: number; volumeLast24H?: number;
wins?: number; wins?: number;
losses?: number; losses?: number;
positions?: Position[] | null; positions?: PositionViewModel[] | null;
identifier?: string; identifier?: string;
walletBalances?: { [key: string]: number; } | null; walletBalances?: { [key: string]: number; } | null;
ticker?: Ticker; ticker?: Ticker;
} }
export interface PositionViewModel {
date: Date;
accountId: number;
originDirection: TradeDirection;
ticker: Ticker;
Open: Trade;
StopLoss: Trade;
TakeProfit1: Trade;
ProfitAndLoss?: ProfitAndLoss | null;
uiFees?: number;
gasFees?: number;
status: PositionStatus;
signalIdentifier?: string | null;
identifier: string;
}
export interface PlatformSummaryViewModel { export interface PlatformSummaryViewModel {
lastUpdated?: Date; lastUpdated?: Date;
lastSnapshot?: Date; lastSnapshot?: Date;
@@ -1039,6 +1055,7 @@ export interface AgentSummaryViewModel {
totalVolume?: number; totalVolume?: number;
totalBalance?: number; totalBalance?: number;
totalFees?: number; totalFees?: number;
backtestCount?: number;
} }
export enum SortableFields { export enum SortableFields {
@@ -1060,8 +1077,7 @@ export interface AgentBalanceHistory {
export interface AgentBalance { export interface AgentBalance {
agentName?: string | null; agentName?: string | null;
totalValue?: number; totalBalanceValue?: number;
totalAccountUsdValue?: number;
botsAllocationUsdValue?: number; botsAllocationUsdValue?: number;
pnL?: number; pnL?: number;
time?: Date; time?: Date;

View File

@@ -1,11 +1,13 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import {Card, FormInput, GridTile} from '../../components/mollecules' import {Card, FormInput, GridTile} from '../../components/mollecules'
import useApiUrlStore from '../../app/store/apiStore' import useApiUrlStore from '../../app/store/apiStore'
import Plot from 'react-plotly.js'
import useTheme from '../../hooks/useTheme'
import { import {
type AgentBalanceHistory, type AgentBalanceHistory,
BotStatus, BotStatus,
DataClient, DataClient,
type Position, type PositionViewModel,
TradeDirection, TradeDirection,
type UserStrategyDetailsViewModel type UserStrategyDetailsViewModel
} from '../../generated/ManagingApi' } from '../../generated/ManagingApi'
@@ -13,7 +15,7 @@ import {
interface AgentData { interface AgentData {
strategies: UserStrategyDetailsViewModel[] strategies: UserStrategyDetailsViewModel[]
balances: AgentBalanceHistory | null balances: AgentBalanceHistory | null
positions: Position[] positions: PositionViewModel[]
} }
@@ -77,8 +79,7 @@ function AgentSearch({ index }: { index: number }) {
// Get the most recent balance // Get the most recent balance
const latestBalance = balances[balances.length - 1] const latestBalance = balances[balances.length - 1]
return { return {
totalValue: latestBalance.totalValue || 0, totalBalanceValue: latestBalance.totalBalanceValue || 0,
totalAccountValue: latestBalance.totalAccountUsdValue || 0,
botsAllocation: latestBalance.botsAllocationUsdValue || 0, botsAllocation: latestBalance.botsAllocationUsdValue || 0,
} }
} }
@@ -126,8 +127,33 @@ function AgentSearch({ index }: { index: number }) {
} }
} }
// Prepare chart data for balance history
const prepareChartData = () => {
const balances = agentData?.balances?.agentBalances
if (!balances || balances.length === 0) return null
// Sort by time to ensure proper chronological order
const sortedBalances = [...balances].sort((a, b) =>
new Date(a.time || 0).getTime() - new Date(b.time || 0).getTime()
)
const dates = sortedBalances.map(balance => new Date(balance.time || 0))
const totalBalanceValues = sortedBalances.map(balance => balance.totalBalanceValue || 0)
const botsAllocationValues = sortedBalances.map(balance => balance.botsAllocationUsdValue || 0)
const pnlValues = sortedBalances.map(balance => balance.pnL || 0)
return {
dates,
totalBalanceValues,
botsAllocationValues,
pnlValues
}
}
const summary = calculateSummary() const summary = calculateSummary()
const currentBalance = getCurrentBalance() const currentBalance = getCurrentBalance()
const chartData = prepareChartData()
const theme = useTheme().themeProperty()
return ( return (
<div className="container mx-auto pt-6 space-y-6"> <div className="container mx-auto pt-6 space-y-6">
@@ -189,7 +215,7 @@ function AgentSearch({ index }: { index: number }) {
<span className={`text-sm font-medium ${ <span className={`text-sm font-medium ${
position.originDirection === TradeDirection.Long ? 'text-green-500' : 'text-red-500' position.originDirection === TradeDirection.Long ? 'text-green-500' : 'text-red-500'
}`}> }`}>
{position.originDirection === TradeDirection.Long ? 'Long' : 'Short'} {position.moneyManagement.leverage}x {position.originDirection === TradeDirection.Long ? 'Long' : 'Short'} {position.Open.leverage}x
</span> </span>
</div> </div>
@@ -221,14 +247,10 @@ function AgentSearch({ index }: { index: number }) {
{currentBalance && ( {currentBalance && (
<div className="mb-6 p-4 bg-primary/10 rounded-lg border border-primary/20"> <div className="mb-6 p-4 bg-primary/10 rounded-lg border border-primary/20">
<h3 className="text-lg font-semibold mb-2">Current Balance</h3> <h3 className="text-lg font-semibold mb-2">Current Balance</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<div className="text-sm opacity-70">Total Balance</div> <div className="text-sm opacity-70">Total Balance Value</div>
<div className="text-2xl font-bold">${currentBalance.totalValue.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div> <div className="text-2xl font-bold">${currentBalance.totalBalanceValue.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div>
</div>
<div>
<div className="text-sm opacity-70">Account USDC Value</div>
<div className="text-xl font-semibold">${currentBalance.totalAccountValue.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div>
</div> </div>
<div> <div>
<div className="text-sm opacity-70">Bots Allocation</div> <div className="text-sm opacity-70">Bots Allocation</div>
@@ -238,6 +260,80 @@ function AgentSearch({ index }: { index: number }) {
</div> </div>
)} )}
{/* Balance History Chart */}
{chartData && (
<div className="mb-6 p-4 bg-primary/10 rounded-lg border border-primary/20">
<h3 className="text-lg font-semibold mb-4">Balance History</h3>
<Plot
data={[
{
x: chartData.dates,
y: chartData.totalBalanceValues,
type: 'scatter' as const,
mode: 'lines+markers' as const,
name: 'Total Balance Value',
line: { color: theme.primary, width: 3 },
marker: { size: 6 }
},
{
x: chartData.dates,
y: chartData.botsAllocationValues,
type: 'scatter' as const,
mode: 'lines+markers' as const,
name: 'Bots Allocation',
line: { color: theme.success, width: 3 },
marker: { size: 6 }
},
{
x: chartData.dates,
y: chartData.pnlValues,
type: 'scatter' as const,
mode: 'lines+markers' as const,
name: 'PnL',
line: { color: theme.warning, width: 3 },
marker: { size: 6 }
}
]}
layout={{
title: {
text: 'Agent Balance Trends Over Time',
font: { color: theme.neutral }
},
xaxis: {
title: {
text: 'Date',
font: { color: theme.neutral }
},
color: theme.neutral,
gridcolor: theme.accent
},
yaxis: {
title: {
text: 'Value (USD)',
font: { color: theme.neutral }
},
color: theme.neutral,
gridcolor: theme.accent
},
plot_bgcolor: 'transparent',
paper_bgcolor: 'transparent',
font: { color: theme.neutral },
legend: {
font: { color: theme.neutral }
},
margin: { t: 50, r: 50, b: 50, l: 50 },
hovermode: 'x unified'
}}
config={{
displayModeBar: true,
displaylogo: false,
modeBarButtonsToRemove: ['pan2d', 'lasso2d', 'select2d']
}}
style={{ width: '100%', height: '400px' }}
/>
</div>
)}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<Card name="Total Volume Traded"> <Card name="Total Volume Traded">
<div className="stat"> <div className="stat">