Fix lastStartTime update

This commit is contained in:
2025-10-07 02:00:39 +07:00
parent f43117e6c6
commit 719ce96e11
5 changed files with 76 additions and 14 deletions

View File

@@ -174,9 +174,10 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
_state.State.StartupTime = DateTime.UtcNow;
}
// Track runtime: set LastStartTime when bot starts and clear LastStopTime
_state.State.LastStartTime = DateTime.UtcNow;
_state.State.LastStopTime = null;
if (previousStatus != BotStatus.Running)
{
_state.State.LastStartTime = DateTime.UtcNow;
}
await _state.WriteStateAsync();
@@ -217,6 +218,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
await _state.WriteStateAsync();
await SaveBotAsync(BotStatus.Running);
}
_logger.LogInformation("LiveTradingBotGrain {GrainId} is already running", this.GetPrimaryKey());
return;
}
@@ -305,7 +307,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
_state.State.LastStopTime = DateTime.UtcNow;
_state.State.LastStartTime = null; // Clear since bot is no longer running
_logger.LogInformation("Bot {GrainId} accumulated {Seconds} seconds of runtime. Total: {TotalSeconds} seconds",
_logger.LogInformation(
"Bot {GrainId} accumulated {Seconds} seconds of runtime. Total: {TotalSeconds} seconds",
this.GetPrimaryKey(), currentSessionSeconds, _state.State.AccumulatedRunTimeSeconds);
}
@@ -781,7 +784,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Unable to load user for bot {BotId} while saving stats", _state.State.Identifier);
_logger.LogWarning(ex, "Unable to load user for bot {BotId} while saving stats",
_state.State.Identifier);
}
}

View File

@@ -2215,6 +2215,61 @@ export class DataClient extends AuthorizedApiBase {
}
return Promise.resolve<string[]>(null as any);
}
data_GetStrategiesPaginated(pageNumber: number | undefined, pageSize: number | undefined, name: string | null | undefined, ticker: string | null | undefined, agentName: string | null | undefined, sortBy: BotSortableColumn | undefined, sortDirection: string | null | undefined): Promise<PaginatedResponseOfTradingBotResponse> {
let url_ = this.baseUrl + "/Data/GetStrategiesPaginated?";
if (pageNumber === null)
throw new Error("The parameter 'pageNumber' cannot be null.");
else if (pageNumber !== undefined)
url_ += "pageNumber=" + encodeURIComponent("" + pageNumber) + "&";
if (pageSize === null)
throw new Error("The parameter 'pageSize' cannot be null.");
else if (pageSize !== undefined)
url_ += "pageSize=" + encodeURIComponent("" + pageSize) + "&";
if (name !== undefined && name !== null)
url_ += "name=" + encodeURIComponent("" + name) + "&";
if (ticker !== undefined && ticker !== null)
url_ += "ticker=" + encodeURIComponent("" + ticker) + "&";
if (agentName !== undefined && agentName !== null)
url_ += "agentName=" + encodeURIComponent("" + agentName) + "&";
if (sortBy === null)
throw new Error("The parameter 'sortBy' cannot be null.");
else if (sortBy !== undefined)
url_ += "sortBy=" + encodeURIComponent("" + sortBy) + "&";
if (sortDirection !== undefined && sortDirection !== null)
url_ += "sortDirection=" + encodeURIComponent("" + sortDirection) + "&";
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_GetStrategiesPaginated(_response);
});
}
protected processData_GetStrategiesPaginated(response: Response): Promise<PaginatedResponseOfTradingBotResponse> {
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 PaginatedResponseOfTradingBotResponse;
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<PaginatedResponseOfTradingBotResponse>(null as any);
}
}
export class MoneyManagementClient extends AuthorizedApiBase {
@@ -4223,6 +4278,7 @@ export interface TradingBotResponse {
candles: Candle[];
winRate: number;
profitAndLoss: number;
roi: number;
identifier: string;
agentName: string;
createDate: Date;
@@ -4247,6 +4303,7 @@ export enum BotSortableColumn {
Ticker = "Ticker",
Status = "Status",
StartupTime = "StartupTime",
Roi = "Roi",
Pnl = "Pnl",
WinRate = "WinRate",
AgentName = "AgentName",

View File

@@ -753,6 +753,7 @@ export interface TradingBotResponse {
candles: Candle[];
winRate: number;
profitAndLoss: number;
roi: number;
identifier: string;
agentName: string;
createDate: Date;
@@ -777,6 +778,7 @@ export enum BotSortableColumn {
Ticker = "Ticker",
Status = "Status",
StartupTime = "StartupTime",
Roi = "Roi",
Pnl = "Pnl",
WinRate = "WinRate",
AgentName = "AgentName",

View File

@@ -3,7 +3,7 @@ import React, {useState} from 'react'
import 'react-toastify/dist/ReactToastify.css'
import useApiUrlStore from '../../app/store/apiStore'
import {UnifiedTradingModal} from '../../components/organism'
import {BotClient, BotStatus, UserClient} from '../../generated/ManagingApi'
import {BotClient, BotSortableColumn, BotStatus, UserClient} from '../../generated/ManagingApi'
import BotList from './botList'
import {useQuery} from '@tanstack/react-query'
@@ -33,15 +33,15 @@ const Bots: React.FC = () => {
queryFn: () => {
switch (activeTab) {
case 0: // All Active Bots
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, undefined, 'CreatedAt', 'Desc')
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, undefined, BotSortableColumn.Roi, 'Desc')
case 1: // My Active Bots
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, currentUser?.agentName, 'CreatedAt', 'Desc')
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, currentUser?.agentName, BotSortableColumn.Roi, 'Desc')
case 2: // My Down Bots
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Stopped, undefined, undefined, currentUser?.agentName, 'CreatedAt', 'Desc')
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Stopped, undefined, undefined, currentUser?.agentName, BotSortableColumn.Roi, 'Desc')
case 3: // Saved Bots
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Saved, undefined, undefined, currentUser?.agentName, 'CreatedAt', 'Desc')
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Saved, undefined, undefined, currentUser?.agentName, BotSortableColumn.Roi, 'Desc')
default:
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, undefined, undefined, undefined, undefined, 'CreatedAt', 'Desc')
return botClient.bot_GetBotsPaginated(pageNumber, pageSize, undefined, undefined, undefined, undefined, BotSortableColumn.Roi, 'Desc')
}
},
queryKey: ['paginatedBots', activeTab, pageNumber, pageSize, currentUser?.agentName],

View File

@@ -161,7 +161,6 @@ function AgentSearch({ index }: { index: number }) {
const chartData = prepareChartData()
const theme = useTheme().themeProperty()
const openPositions = (agentData?.positions || []).filter(p => [
PositionStatus.New,
PositionStatus.Updating,
PositionStatus.Filled,
PositionStatus.Flipped