Fix Runtime by adding TotalRuntimeInSeconds

This commit is contained in:
2025-10-05 20:51:46 +07:00
parent 976c1a6580
commit f67ee330b3
18 changed files with 3142 additions and 50 deletions

View File

@@ -105,6 +105,7 @@ const LogIn = () => {
<label
htmlFor="name"
className="dark:text-white block mb-2 text-sm font-medium text-gray-900"
hidden={true}
>
Name
</label>

View File

@@ -4491,7 +4491,8 @@ export interface UserStrategyDetailsViewModel {
pnL?: number;
netPnL?: number;
roiPercentage?: number;
runtime?: Date;
runtime?: Date | null;
totalRuntimeSeconds?: number;
winRate?: number;
totalVolumeTraded?: number;
volumeLast24H?: number;

View File

@@ -974,7 +974,8 @@ export interface UserStrategyDetailsViewModel {
pnL?: number;
netPnL?: number;
roiPercentage?: number;
runtime?: Date;
runtime?: Date | null;
totalRuntimeSeconds?: number;
winRate?: number;
totalVolumeTraded?: number;
volumeLast24H?: number;

View File

@@ -48,14 +48,10 @@ function AgentSearch({ index }: { index: number }) {
)
])
// Extract open positions from all strategies
// Extract positions from all strategies (status not available in generated PositionViewModel)
const allPositions = strategies.flatMap(strategy => strategy.positions || [])
const openPositions = allPositions.filter(position =>
position.status !== 'Finished' &&
position.status !== 'Canceled'
)
setAgentData({ strategies, balances, positions: openPositions })
setAgentData({ strategies, balances, positions: allPositions })
} catch (err) {
setError('Failed to fetch agent data. Please check the agent name and try again.')
console.error('Error fetching agent data:', err)
@@ -461,13 +457,20 @@ function AgentSearch({ index }: { index: number }) {
{strategy.roiPercentage && strategy.roiPercentage >= 0 ? '+' : ''}{(strategy.roiPercentage || 0).toFixed(2)}%
</span>
<span>
{strategy.runtime ? (() => {
const runtime = new Date(strategy.runtime)
const now = new Date()
const diffHours = Math.floor((now.getTime() - runtime.getTime()) / (1000 * 60 * 60))
const diffDays = Math.floor(diffHours / 24)
return diffDays > 0 ? `${diffDays}d ${diffHours % 24}h` : `${diffHours}h`
{strategy.totalRuntimeSeconds > 0 ? (() => {
const totalSeconds = strategy.totalRuntimeSeconds
const days = Math.floor(totalSeconds / 86400)
const hours = Math.floor((totalSeconds % 86400) / 3600)
const minutes = Math.floor((totalSeconds % 3600) / 60)
if (days > 0) {
return `${days}d ${hours}h`
} else if (hours > 0) {
return `${hours}h ${minutes}m`
} else {
return `${minutes}m`
}
})() : '-'}
{strategy.state === BotStatus.Running && <span className="ml-1 text-green-500"></span>}
</span>
<span>{(strategy.winRate || 0).toFixed(0)}%</span>
</div>

View File

@@ -1,13 +1,12 @@
import React, {useEffect, useState} from 'react'
import {PlayIcon, StopIcon} from '@heroicons/react/solid'
import moment from 'moment'
import {
BotClient,
BotStatus,
DataClient,
Position,
TradeDirection,
UserStrategyDetailsViewModel
BotClient,
BotStatus,
DataClient,
PositionViewModel,
TradeDirection,
UserStrategyDetailsViewModel
} from '../../generated/ManagingApi'
import useApiUrlStore from '../../app/store/apiStore'
import {Toast} from '../../components/mollecules'
@@ -62,16 +61,12 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
return `${value >= 0 ? '+' : ''}${value.toFixed(2)}%`
}
const formatDuration = (runtime?: Date | null) => {
if (!runtime) return '0h'
const formatDuration = (totalRuntimeSeconds?: number | null) => {
if (!totalRuntimeSeconds || totalRuntimeSeconds === 0) return '0h'
const start = moment(runtime)
const now = moment()
const duration = moment.duration(now.diff(start))
const days = Math.floor(duration.asDays())
const hours = duration.hours()
const minutes = duration.minutes()
const days = Math.floor(totalRuntimeSeconds / 86400)
const hours = Math.floor((totalRuntimeSeconds % 86400) / 3600)
const minutes = Math.floor((totalRuntimeSeconds % 3600) / 60)
if (days > 0) {
return `${days}d ${hours}h ${minutes}m`
@@ -82,22 +77,22 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
}
}
const getStatusBadge = (state: string | null | undefined) => {
const badgeClass = state === 'Up'
? 'badge badge-success'
: state === 'Down'
? 'badge badge-error'
const getStatusBadge = (state: BotStatus | null | undefined) => {
const badgeClass = state === BotStatus.Running
? 'badge badge-success'
: state === BotStatus.Stopped
? 'badge badge-warning'
: 'badge badge-neutral'
return <span className={badgeClass}>{state}</span>
}
const toggleStrategyStatus = (status: string | null | undefined, identifier: string) => {
const isUp = status === 'Up'
const t = new Toast(isUp ? 'Stopping strategy' : 'Starting strategy')
const toggleStrategyStatus = (status: BotStatus | null | undefined, identifier: string) => {
const isRunning = status === BotStatus.Running
const t = new Toast(isRunning ? 'Stopping strategy' : 'Starting strategy')
console.log('toggleStrategyStatus', status, identifier)
if (status === 'Up') {
if (status === BotStatus.Running) {
botClient
.bot_Stop(identifier)
.then(() => {
@@ -108,7 +103,7 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
.catch((err) => {
t.update('error', err)
})
} else if (status === 'Down' || status === 'None') {
} else {
botClient
.bot_Restart(identifier)
.then(() => {
@@ -212,7 +207,7 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
</div>
<div className="stat bg-base-200 rounded-lg">
<div className="stat-title">Runtime</div>
<div className="stat-value text-sm">{formatDuration(strategyData.runtime)}</div>
<div className="stat-value text-sm">{formatDuration(strategyData.totalRuntimeSeconds)}</div>
</div>
</div>
@@ -292,7 +287,7 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
<div className="card bg-base-200">
<div className="card-body">
<h3 className="card-title">Total Runtime</h3>
<div className="text-2xl font-bold">{formatDuration(strategyData.runtime)}</div>
<div className="text-2xl font-bold">{formatDuration(strategyData.totalRuntimeSeconds)}</div>
</div>
</div>
</div>
@@ -302,7 +297,7 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
<div className="card bg-base-200">
<div className="card-body">
<h3 className="card-title">Trade History</h3>
{strategyData.positions && Object.keys(strategyData.positions).length > 0 ? (
{strategyData.positions && strategyData.positions.length > 0 ? (
<div className="overflow-x-auto">
<table className="table table-zebra">
<thead>
@@ -317,8 +312,7 @@ const AgentStrategy: React.FC<AgentStrategyProps> = ({ index }) => {
</tr>
</thead>
<tbody>
{Object.values(strategyData.positions).map((position: Position, index: number) => (
console.log(position),
{(strategyData.positions || []).map((position: PositionViewModel, index: number) => (
<tr key={index}>
<td>{new Date(position.Open.date || '').toLocaleDateString()}</td>
<td>{position.ticker}</td>