{isForWatchOnly
? 'The bot will run in watch-only mode and will not execute trades.'
diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx
index e994dfa..19be777 100644
--- a/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx
+++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestCards.tsx
@@ -1,22 +1,13 @@
-import { DotsVerticalIcon, TrashIcon } from '@heroicons/react/solid'
+import {DotsVerticalIcon, TrashIcon} from '@heroicons/react/solid'
import moment from 'moment'
import React from 'react'
import useApiUrlStore from '../../../app/store/apiStore'
-import type {
- Backtest,
- MoneyManagement,
- StartBotRequest,
- Ticker,
-} from '../../../generated/ManagingApi'
-import {
- BacktestClient,
- BotClient,
- BotType,
-} from '../../../generated/ManagingApi'
-import type { IBacktestCards } from '../../../global/type'
+import type {Backtest, MoneyManagement, StartBotRequest, Ticker,} from '../../../generated/ManagingApi'
+import {BacktestClient, BotClient, BotType,} from '../../../generated/ManagingApi'
+import type {IBacktestCards} from '../../../global/type'
import MoneyManagementModal from '../../../pages/settingsPage/moneymanagement/moneyManagementModal'
-import { CardPosition, CardText, Toast } from '../../mollecules'
+import {CardPosition, CardText, Toast} from '../../mollecules'
import CardPositionItem from '../Trading/CardPositionItem'
import TradeChart from '../Trading/TradeChart/TradeChart'
@@ -73,6 +64,7 @@ const BacktestCards: React.FC = ({ list, setBacktests }) => {
scenario: backtest.scenario,
ticker: backtest.ticker as Ticker,
timeframe: backtest.timeframe,
+ initialTradingBalance: 1000,
}
await client
@@ -89,6 +81,10 @@ const BacktestCards: React.FC = ({ list, setBacktests }) => {
const t = new Toast('Optimized backtest is running')
const client = new BacktestClient({}, apiUrl)
+ // Calculate dates for the API call
+ const startDate = backtest.candles[0].date
+ const endDate = backtest.candles[backtest.candles.length - 1].date
+
await client
.backtest_Run(
backtest.accountName,
@@ -96,12 +92,13 @@ const BacktestCards: React.FC = ({ list, setBacktests }) => {
backtest.ticker as Ticker,
backtest.scenario,
backtest.timeframe,
- false,
- daysBetween(backtest.candles[0].date),
- backtest.walletBalances[0].value,
- '',
- false,
- backtest.optimizedMoneyManagement
+ false, // watchOnly
+ backtest.walletBalances[0].value, // balance
+ '', // moneyManagementName (empty since we're passing the optimized moneyManagement object)
+ startDate, // startDate
+ endDate, // endDate
+ false, // save
+ backtest.optimizedMoneyManagement // moneyManagement object
)
.then((backtest: Backtest) => {
t.update('success', `${backtest.ticker} Backtest Succeeded`)
diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx
index 64ef1ed..919be98 100644
--- a/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx
+++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx
@@ -1,28 +1,23 @@
-import { useQuery } from '@tanstack/react-query'
-import React, { useEffect, useState } from 'react'
-import { useForm, type SubmitHandler } from 'react-hook-form'
+import {useQuery} from '@tanstack/react-query'
+import React, {useEffect, useState} from 'react'
+import {type SubmitHandler, useForm} from 'react-hook-form'
import useApiUrlStore from '../../../app/store/apiStore'
import {
- Backtest,
- MoneyManagement,
- Ticker,
+ AccountClient,
+ Backtest,
+ BacktestClient,
+ BotType,
+ DataClient,
+ MoneyManagement,
+ MoneyManagementClient,
+ ScenarioClient,
+ Ticker,
+ Timeframe,
} from '../../../generated/ManagingApi'
-import {
- AccountClient,
- BacktestClient,
- BotType,
- DataClient,
- MoneyManagementClient,
- ScenarioClient,
- Timeframe,
-} from '../../../generated/ManagingApi'
-import type {
- BacktestModalProps,
- IBacktestsFormInput,
-} from '../../../global/type'
-import { Loader, Slider } from '../../atoms'
-import { Modal, Toast } from '../../mollecules'
+import type {BacktestModalProps, IBacktestsFormInput,} from '../../../global/type'
+import {Loader, Slider} from '../../atoms'
+import {Modal, Toast} from '../../mollecules'
import FormInput from '../../mollecules/FormInput/FormInput'
import CustomMoneyManagement from '../CustomMoneyManagement/CustomMoneyManagement'
@@ -100,6 +95,8 @@ const BacktestModal: React.FC = ({
// Use the name of the money management strategy if custom is not provided
const moneyManagementName = customMoneyManagement ? undefined : selectedMoneyManagement
+ console.log(customMoneyManagement)
+
backtestClient
.backtest_Run(
form.accountName,
@@ -122,7 +119,6 @@ const BacktestModal: React.FC = ({
if (showLoopSlider && selectedLoopQuantity > loopCount) {
const nextCount = loopCount + 1
const mm: MoneyManagement = {
- balanceAtRisk: backtest.optimizedMoneyManagement.balanceAtRisk,
leverage: backtest.optimizedMoneyManagement.leverage,
name: backtest.optimizedMoneyManagement.name + nextCount,
stopLoss: backtest.optimizedMoneyManagement.stopLoss,
@@ -148,6 +144,7 @@ const BacktestModal: React.FC = ({
function onMoneyManagementChange(e: any) {
if (e.target.value === 'custom') {
setShowCustomMoneyManagement(true)
+ setCustomMoneyManagement(e.target.value)
} else {
setShowCustomMoneyManagement(false)
setCustomMoneyManagement(undefined)
@@ -280,6 +277,32 @@ const BacktestModal: React.FC = ({
+ {/* Losing streak info */}
+ {(() => {
+ // Find the selected money management object
+ let mm: MoneyManagement | undefined = undefined;
+ if (showCustomMoneyManagement && customMoneyManagement) {
+ mm = { ...customMoneyManagement, stopLoss: customMoneyManagement.stopLoss / 100 };
+ } else if (selectedMoneyManagement) {
+ mm = moneyManagements.find((m) => m.name === selectedMoneyManagement);
+ }
+ // Use actual initial balance and a minimum threshold
+ const initialBalance = balance;
+ const minBalance = 10; // You can make this configurable if needed
+ if (mm && mm.leverage && mm.stopLoss && initialBalance > minBalance) {
+ const perLoss = mm.leverage * mm.stopLoss;
+ if (perLoss > 0 && perLoss < 1) {
+ const streak = Math.floor(Math.log(minBalance / initialBalance) / Math.log(1 - perLoss));
+ return (
+
+ Max losing streak before balance drops below {minBalance}: {streak} trades (with leverage x{mm.leverage} and stop loss {Math.round(mm.stopLoss * 10000) / 100}% per trade, starting from {initialBalance})
+