= ({
const cooldownRecommendations = getCooldownRecommendations();
+ // Calculate average trades per day
+ const getAverageTradesPerDay = () => {
+ if (positions.length === 0) return "0.00";
+
+ // Get all trade dates and sort them
+ const tradeDates = positions.map(position => new Date(position.open.date)).sort((a, b) => a.getTime() - b.getTime());
+
+ if (tradeDates.length < 2) return positions.length.toString();
+
+ // Calculate the date range in days
+ const firstTradeDate = tradeDates[0];
+ const lastTradeDate = tradeDates[tradeDates.length - 1];
+ const diffInMs = lastTradeDate.getTime() - firstTradeDate.getTime();
+ const diffInDays = Math.max(1, diffInMs / (1000 * 60 * 60 * 24)); // Ensure at least 1 day
+
+ const averageTradesPerDay = positions.length / diffInDays;
+ return averageTradesPerDay.toFixed(2);
+ };
+
return (
<>
@@ -325,6 +344,10 @@ const BacktestRowDetails: React.FC = ({
title="Median Cooldown"
content={cooldownRecommendations.median + " candles"}
>
+
diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx
index b715295..e9c621f 100644
--- a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx
+++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx
@@ -3,7 +3,7 @@ import React, {useEffect, useState} from 'react'
import {useQuery} from '@tanstack/react-query'
import useApiUrlStore from '../../../app/store/apiStore'
-import type {Backtest, StartBotRequest, Ticker,} from '../../../generated/ManagingApi'
+import type {Backtest, StartBotRequest, Ticker, TradingBotConfig} from '../../../generated/ManagingApi'
import {BacktestClient, BotClient, MoneyManagementClient} from '../../../generated/ManagingApi'
import type {IBacktestCards} from '../../../global/type'
import {CardText, SelectColumnFilter, Table, Toast} from '../../mollecules'
@@ -58,19 +58,39 @@ const BacktestTable: React.FC = ({ list, isFetching, setBacktest
moneyManagementName.toLowerCase() === 'custom' ||
moneyManagementName.toLowerCase().includes('custom');
- const request: StartBotRequest = {
+ // Create TradingBotConfig from the backtest configuration
+ const tradingBotConfig: TradingBotConfig = {
accountName: backtest.config.accountName,
- botType: backtest.config.botType,
- isForWatchOnly: isForWatchOnly,
- // Only use the money management name if it's not a custom money management
- moneyManagementName: isCustomMoneyManagement ? '' : moneyManagementName,
- scenario: backtest.config.scenarioName,
- ticker: backtest.config.ticker as Ticker,
+ ticker: backtest.config.ticker,
+ scenarioName: backtest.config.scenarioName,
timeframe: backtest.config.timeframe,
- initialTradingBalance: initialTradingBalance,
+ botType: backtest.config.botType,
+ isForWatchingOnly: isForWatchOnly,
+ isForBacktest: false, // This is for running a live bot
cooldownPeriod: backtest.config.cooldownPeriod,
maxLossStreak: backtest.config.maxLossStreak,
+ maxPositionTimeHours: backtest.config.maxPositionTimeHours,
+ flipOnlyWhenInProfit: backtest.config.flipOnlyWhenInProfit,
+ flipPosition: backtest.config.flipPosition,
name: botName,
+ botTradingBalance: initialTradingBalance,
+ // Use the money management from backtest if it's custom, otherwise leave null and use moneyManagementName
+ moneyManagement: isCustomMoneyManagement ?
+ (backtest.config.moneyManagement || {
+ name: 'default',
+ leverage: 1,
+ stopLoss: 0.01,
+ takeProfit: 0.02,
+ timeframe: backtest.config.timeframe
+ }) :
+ backtest.config.moneyManagement, // Always provide a valid MoneyManagement object
+ closeEarlyWhenProfitable: backtest.config.closeEarlyWhenProfitable || false
+ };
+
+ const request: StartBotRequest = {
+ config: tradingBotConfig,
+ // Only use the money management name if it's not a custom money management
+ moneyManagementName: isCustomMoneyManagement ? undefined : moneyManagementName
}
await client
diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts
index f53309a..d1fa72b 100644
--- a/src/Managing.WebApp/src/generated/ManagingApi.ts
+++ b/src/Managing.WebApp/src/generated/ManagingApi.ts
@@ -2699,6 +2699,7 @@ export interface TradingBotConfig {
flipPosition: boolean;
name: string;
maxPositionTimeHours?: number | null;
+ closeEarlyWhenProfitable?: boolean;
flipOnlyWhenInProfit: boolean;
}
@@ -3113,20 +3114,8 @@ export interface RunBacktestRequest {
}
export interface StartBotRequest {
- botType?: BotType;
- identifier?: string | null;
- ticker?: Ticker;
- scenario?: string | null;
- timeframe?: Timeframe;
- accountName?: string | null;
+ config?: TradingBotConfig | null;
moneyManagementName?: string | null;
- isForWatchOnly?: boolean;
- initialTradingBalance?: number;
- cooldownPeriod?: number;
- maxLossStreak?: number;
- name?: string | null;
- maxPositionTimeHours?: number | null;
- flipOnlyWhenInProfit?: boolean;
}
export interface TradingBot {
diff --git a/src/Managing.WebApp/src/global/type.tsx b/src/Managing.WebApp/src/global/type.tsx
index d9eb759..f611157 100644
--- a/src/Managing.WebApp/src/global/type.tsx
+++ b/src/Managing.WebApp/src/global/type.tsx
@@ -116,6 +116,7 @@ export type IBacktestsFormInput = {
maxLossStreak: number
maxPositionTimeHours?: number | null
flipOnlyWhenInProfit?: boolean
+ closeEarlyWhenProfitable?: boolean
}
export type IBacktestCards = {