From 32ac342a20bb1fc48177c3b4ef55d317e22b1f20 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Sun, 12 Oct 2025 15:42:38 +0700 Subject: [PATCH] Update bundle backtests --- .cursor/rules/fullstack.mdc | 2 +- .../Controllers/BacktestController.cs | 10 ++----- .../Grains/BundleBacktestGrain.cs | 21 ++++++++++++-- .../Workers/BundleBacktestWorker.cs | 20 ++++++++++--- .../BundleBacktestUniversalConfig.cs | 6 ---- .../src/generated/ManagingApi.ts | 1 - .../pages/backtestPage/BundleRequestModal.tsx | 28 ++----------------- 7 files changed, 40 insertions(+), 48 deletions(-) diff --git a/.cursor/rules/fullstack.mdc b/.cursor/rules/fullstack.mdc index 080100a4..d8edf8ea 100644 --- a/.cursor/rules/fullstack.mdc +++ b/.cursor/rules/fullstack.mdc @@ -75,7 +75,7 @@ Key Principles - Use mobile-first approach for responsive design. - Place static content and interfaces at file end. - Use content variables for static content outside render functions. - - Minimize 'use client', 'useEffect', and 'setState'. Favor RSC. + - Never use useEffect() to fetch data, use tanstack UseQuery instead - Wrap client components in Suspense with fallback. - Use dynamic loading for non-critical components. - Optimize images: WebP format, size data, lazy loading. diff --git a/src/Managing.Api/Controllers/BacktestController.cs b/src/Managing.Api/Controllers/BacktestController.cs index 33593735..10f5f22a 100644 --- a/src/Managing.Api/Controllers/BacktestController.cs +++ b/src/Managing.Api/Controllers/BacktestController.cs @@ -462,11 +462,6 @@ public class BacktestController : BaseController { var user = await GetUser(); - // Validate universal configuration - if (string.IsNullOrEmpty(request.UniversalConfig.AccountName)) - { - return BadRequest("Account name is required in universal configuration"); - } if (string.IsNullOrEmpty(request.UniversalConfig.ScenarioName) && request.UniversalConfig.Scenario == null) { @@ -510,8 +505,9 @@ public class BacktestController : BaseController /// Generates individual backtest requests from variant configuration /// /// The bundle backtest request + /// The account name to use for all backtests /// List of individual backtest requests - private List GenerateBacktestRequests(RunBundleBacktestRequest request) + private List GenerateBacktestRequests(RunBundleBacktestRequest request, string accountName) { var backtestRequests = new List(); @@ -523,7 +519,7 @@ public class BacktestController : BaseController { var config = new TradingBotConfigRequest { - AccountName = request.UniversalConfig.AccountName, + AccountName = accountName, Ticker = ticker, Timeframe = request.UniversalConfig.Timeframe, IsForWatchingOnly = request.UniversalConfig.IsForWatchingOnly, diff --git a/src/Managing.Application/Grains/BundleBacktestGrain.cs b/src/Managing.Application/Grains/BundleBacktestGrain.cs index 370810f3..20021379 100644 --- a/src/Managing.Application/Grains/BundleBacktestGrain.cs +++ b/src/Managing.Application/Grains/BundleBacktestGrain.cs @@ -105,7 +105,7 @@ public class BundleBacktestGrain : Grain, IBundleBacktestGrain, IRemindable await backtester.UpdateBundleBacktestRequestAsync(bundleRequest); // Generate backtest requests from variant configuration - var backtestRequests = GenerateBacktestRequestsFromVariants(bundleRequest); + var backtestRequests = await GenerateBacktestRequestsFromVariants(bundleRequest); if (backtestRequests == null || !backtestRequests.Any()) { throw new InvalidOperationException("Failed to generate backtest requests from variants"); @@ -133,7 +133,7 @@ public class BundleBacktestGrain : Grain, IBundleBacktestGrain, IRemindable /// /// Generates individual backtest requests from variant configuration /// - private List GenerateBacktestRequestsFromVariants(BundleBacktestRequest bundleRequest) + private async Task> GenerateBacktestRequestsFromVariants(BundleBacktestRequest bundleRequest) { try { @@ -149,6 +149,21 @@ public class BundleBacktestGrain : Grain, IBundleBacktestGrain, IRemindable return new List(); } + // Get the first account for the user using AccountService + var firstAccount = await ServiceScopeHelpers.WithScopedService( + _scopeFactory, + async service => + { + var accounts = await service.GetAccountsByUserAsync(bundleRequest.User, hideSecrets: true, getBalance: false); + return accounts.FirstOrDefault(); + }); + + if (firstAccount == null) + { + _logger.LogError("No accounts found for user {UserId} in bundle request {RequestId}", bundleRequest.User.Id, bundleRequest.RequestId); + return new List(); + } + var backtestRequests = new List(); foreach (var dateRange in dateTimeRanges) @@ -159,7 +174,7 @@ public class BundleBacktestGrain : Grain, IBundleBacktestGrain, IRemindable { var config = new TradingBotConfigRequest { - AccountName = universalConfig.AccountName, + AccountName = firstAccount.Name, Ticker = ticker, Timeframe = universalConfig.Timeframe, IsForWatchingOnly = universalConfig.IsForWatchingOnly, diff --git a/src/Managing.Application/Workers/BundleBacktestWorker.cs b/src/Managing.Application/Workers/BundleBacktestWorker.cs index 0c1d08f1..d01657cd 100644 --- a/src/Managing.Application/Workers/BundleBacktestWorker.cs +++ b/src/Managing.Application/Workers/BundleBacktestWorker.cs @@ -94,7 +94,7 @@ public class BundleBacktestWorker : BaseWorker await backtester.UpdateBundleBacktestRequestAsync(bundleRequest); // Generate backtest requests from the new variant structure - var backtestRequests = GenerateBacktestRequestsFromVariants(bundleRequest); + var backtestRequests = await GenerateBacktestRequestsFromVariants(bundleRequest); if (backtestRequests == null || !backtestRequests.Any()) { throw new InvalidOperationException("Failed to generate backtest requests from variants"); @@ -297,7 +297,7 @@ public class BundleBacktestWorker : BaseWorker var succeededIds = new HashSet(failedBundle.Results ?? new List()); // Generate backtest requests from the new variant structure - var originalRequests = GenerateBacktestRequestsFromVariants(failedBundle); + var originalRequests = await GenerateBacktestRequestsFromVariants(failedBundle); if (originalRequests == null || !originalRequests.Any()) continue; for (int i = failedBundle.CompletedBacktests; i < originalRequests.Count; i++) @@ -339,7 +339,7 @@ public class BundleBacktestWorker : BaseWorker /// /// Generates individual backtest requests from variant configuration /// - private List GenerateBacktestRequestsFromVariants(BundleBacktestRequest bundleRequest) + private async Task> GenerateBacktestRequestsFromVariants(BundleBacktestRequest bundleRequest) { try { @@ -355,6 +355,18 @@ public class BundleBacktestWorker : BaseWorker return new List(); } + // Get the first account for the user using AccountService + using var scope = _serviceProvider.CreateScope(); + var accountService = scope.ServiceProvider.GetRequiredService(); + var accounts = await accountService.GetAccountsByUserAsync(bundleRequest.User, hideSecrets: true, getBalance: false); + var firstAccount = accounts.FirstOrDefault(); + + if (firstAccount == null) + { + _logger.LogError("No accounts found for user {UserId} in bundle request {RequestId}", bundleRequest.User.Id, bundleRequest.RequestId); + return new List(); + } + var backtestRequests = new List(); foreach (var dateRange in dateTimeRanges) @@ -365,7 +377,7 @@ public class BundleBacktestWorker : BaseWorker { var config = new TradingBotConfigRequest { - AccountName = universalConfig.AccountName, + AccountName = firstAccount.Name, Ticker = ticker, Timeframe = universalConfig.Timeframe, IsForWatchingOnly = universalConfig.IsForWatchingOnly, diff --git a/src/Managing.Domain/Backtests/BundleBacktestUniversalConfig.cs b/src/Managing.Domain/Backtests/BundleBacktestUniversalConfig.cs index 22e266c4..4aa95855 100644 --- a/src/Managing.Domain/Backtests/BundleBacktestUniversalConfig.cs +++ b/src/Managing.Domain/Backtests/BundleBacktestUniversalConfig.cs @@ -9,12 +9,6 @@ namespace Managing.Domain.Backtests; /// public class BundleBacktestUniversalConfig { - /// - /// The account name to use for all backtests - /// - [Required] - public string AccountName { get; set; } = string.Empty; - /// /// The timeframe for trading decisions /// diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts index 3414a40a..24266fa8 100644 --- a/src/Managing.WebApp/src/generated/ManagingApi.ts +++ b/src/Managing.WebApp/src/generated/ManagingApi.ts @@ -4399,7 +4399,6 @@ export interface RunBundleBacktestRequest { } export interface BundleBacktestUniversalConfig { - accountName: string; timeframe: Timeframe; isForWatchingOnly: boolean; botTradingBalance: number; diff --git a/src/Managing.WebApp/src/pages/backtestPage/BundleRequestModal.tsx b/src/Managing.WebApp/src/pages/backtestPage/BundleRequestModal.tsx index a7aa506b..f7536528 100644 --- a/src/Managing.WebApp/src/pages/backtestPage/BundleRequestModal.tsx +++ b/src/Managing.WebApp/src/pages/backtestPage/BundleRequestModal.tsx @@ -1,6 +1,5 @@ import React, {useEffect, useRef, useState} from 'react'; import { - AccountClient, BacktestClient, BundleBacktestRequest, BundleBacktestUniversalConfig, @@ -47,7 +46,6 @@ const BundleRequestModal: React.FC = ({ // Form state for creating new bundle requests const [strategyName, setStrategyName] = useState(''); - const [selectedAccount, setSelectedAccount] = useState(''); const [selectedTimeframe, setSelectedTimeframe] = useState(Timeframe.FifteenMinutes); const [selectedTickers, setSelectedTickers] = useState([]); const [startingCapital, setStartingCapital] = useState(10000); @@ -70,15 +68,9 @@ const BundleRequestModal: React.FC = ({ // API clients const backtestClient = new BacktestClient({} as any, apiUrl); - const accountClient = new AccountClient({} as any, apiUrl); const dataClient = new DataClient({} as any, apiUrl); // Fetch data - const { data: accounts } = useQuery({ - queryFn: () => accountClient.account_GetAccounts(), - queryKey: ['accounts'], - }); - const { data: tickers } = useQuery({ queryFn: () => dataClient.data_GetTickers(selectedTimeframe), queryKey: ['tickers', selectedTimeframe], @@ -210,7 +202,7 @@ const BundleRequestModal: React.FC = ({ // Create bundle backtest request const handleCreateBundle = async () => { - if (!strategyName || !selectedAccount || selectedTickers.length === 0) { + if (!strategyName || selectedTickers.length === 0) { new Toast('Please fill in all required fields', false); return; } @@ -221,7 +213,6 @@ const BundleRequestModal: React.FC = ({ } const universalConfig: BundleBacktestUniversalConfig = { - accountName: selectedAccount, timeframe: selectedTimeframe, isForWatchingOnly: false, botTradingBalance: startingCapital, @@ -439,21 +430,6 @@ const BundleRequestModal: React.FC = ({ /> - {/* Account Selection */} - - - {/* Scenario Builder */}
@@ -834,7 +810,7 @@ const BundleRequestModal: React.FC = ({