diff --git a/src/Managing.WebApp/src/components/mollecules/IndicatorsDisplay/IndicatorsDisplay.tsx b/src/Managing.WebApp/src/components/mollecules/IndicatorsDisplay/IndicatorsDisplay.tsx new file mode 100644 index 0000000..e7bc429 --- /dev/null +++ b/src/Managing.WebApp/src/components/mollecules/IndicatorsDisplay/IndicatorsDisplay.tsx @@ -0,0 +1,80 @@ +import React from 'react' +import type {Indicator, IndicatorType} from '../../../generated/ManagingApi' +import {SignalType} from '../../../generated/ManagingApi' + +interface IndicatorsDisplayProps { + indicators: Indicator[] + className?: string +} + +// Helper function to get indicator parameters from scenario indicators +const getIndicatorParameters = (indicator: Indicator) => { + if (!indicator) return null; + + return { + name: indicator.name || 'Unnamed Indicator', + type: indicator.type, + signalType: indicator.signalType, + period: indicator.period, + fastPeriods: indicator.fastPeriods, + slowPeriods: indicator.slowPeriods, + signalPeriods: indicator.signalPeriods, + multiplier: indicator.multiplier, + smoothPeriods: indicator.smoothPeriods, + stochPeriods: indicator.stochPeriods, + cyclePeriods: indicator.cyclePeriods + }; +}; + +// Helper function to get badge color based on signal type +const getBadgeColor = (signalType: SignalType) => { + switch (signalType) { + case SignalType.Signal: + return 'badge-primary'; + case SignalType.Trend: + return 'badge-secondary'; + case SignalType.Context: + return 'badge-accent'; + default: + return 'badge-neutral'; + } +}; + +// Helper function to format indicator type for display +const formatIndicatorType = (type: IndicatorType) => { + return type.replace(/([A-Z])/g, ' $1').trim(); +}; + +const IndicatorsDisplay: React.FC = ({ indicators, className = "" }) => { + const processedIndicators = indicators.map(getIndicatorParameters).filter(Boolean); + + return ( +
+ {processedIndicators.map((indicator: any, index: number) => { + if (!indicator) return null; + + // Build tooltip content with indicator parameters + const tooltipContent = ` + ${indicator.period ? `Period: ${indicator.period}` : ''} + ${indicator.fastPeriods ? `Fast: ${indicator.fastPeriods}` : ''} + ${indicator.slowPeriods ? `Slow: ${indicator.slowPeriods}` : ''} + ${indicator.signalPeriods ? `Signal: ${indicator.signalPeriods}` : ''} + ${indicator.multiplier ? `Multiplier: ${indicator.multiplier}` : ''} + ${indicator.smoothPeriods ? `Smooth: ${indicator.smoothPeriods}` : ''} + ${indicator.stochPeriods ? `Stoch: ${indicator.stochPeriods}` : ''} + ${indicator.cyclePeriods ? `Cycle: ${indicator.cyclePeriods}` : ''} + `.trim().replace(/\n\s+/g, '\n'); + + return ( +
+
+ {formatIndicatorType(indicator.type)} +
+
+ ); + })} +
+ ); +}; + +export default IndicatorsDisplay; \ No newline at end of file diff --git a/src/Managing.WebApp/src/components/mollecules/index.tsx b/src/Managing.WebApp/src/components/mollecules/index.tsx index 7869d6d..537405a 100644 --- a/src/Managing.WebApp/src/components/mollecules/index.tsx +++ b/src/Managing.WebApp/src/components/mollecules/index.tsx @@ -13,3 +13,4 @@ export { default as GridTile } from './GridTile/GridTile' export { default as SelectColumnFilter } from './Table/SelectColumnFilter' export { default as Card } from './Card/Card' export { default as ConfigDisplayModal } from './ConfigDisplayModal/ConfigDisplayModal' +export { default as IndicatorsDisplay } from './IndicatorsDisplay/IndicatorsDisplay' diff --git a/src/Managing.WebApp/src/components/organism/ActiveBots/ActiveBots.tsx b/src/Managing.WebApp/src/components/organism/ActiveBots/ActiveBots.tsx index e34ff13..16500e6 100644 --- a/src/Managing.WebApp/src/components/organism/ActiveBots/ActiveBots.tsx +++ b/src/Managing.WebApp/src/components/organism/ActiveBots/ActiveBots.tsx @@ -3,15 +3,15 @@ import React, {useEffect, useState} from 'react' import {Hub} from '../../../app/providers/Hubs' import useApiUrlStore from '../../../app/store/apiStore' -import type {Account, TradingBot} from '../../../generated/ManagingApi' +import type {Account, TradingBotResponse} from '../../../generated/ManagingApi' import {AccountClient, BotClient, TradeDirection, TradeStatus,} from '../../../generated/ManagingApi' -import {SelectColumnFilter, Table} from '../../mollecules' +import {IndicatorsDisplay, SelectColumnFilter, Table} from '../../mollecules' import StatusBadge from '../StatusBadge/StatusBadge' import Summary from '../Trading/Summary' import BotRowDetails from './botRowDetails' export default function ActiveBots() { - const [bots, setBots] = useState([]) + const [bots, setBots] = useState([]) const [accounts, setAccounts] = useState([]) const { apiUrl } = useApiUrlStore() @@ -64,23 +64,31 @@ export default function ActiveBots() { { Filter: SelectColumnFilter, Header: 'Ticker', - accessor: 'ticker', + accessor: 'config.ticker', disableSortBy: true, }, { - Header: 'Account', - accessor: 'accountName', + Header: 'Name', + accessor: 'config.name', }, { Filter: SelectColumnFilter, Header: 'Timeframe', - accessor: 'timeframe', + accessor: 'config.timeframe', disableSortBy: true, }, { - Filter: SelectColumnFilter, - Header: 'Scenario', - accessor: 'scenario', + Header: 'Indicators', + accessor: 'config.scenario.indicators', + Cell: ({cell}: any) => { + const bot = cell.row.original as TradingBotResponse; + const indicators = bot.config?.scenario?.indicators || []; + + return ( + + ); + }, + disableFilters: true, disableSortBy: true, }, { @@ -161,12 +169,12 @@ export default function ActiveBots() { const setupHubConnection = async () => { const hub = new Hub('bothub', apiUrl).hub - hub.on('BotsSubscription', (data: TradingBot[]) => { + hub.on('BotsSubscription', (data: TradingBotResponse[]) => { // eslint-disable-next-line no-console console.log( 'bot List', - bots.map((bot: TradingBot) => { - return bot.name + bots.map((bot: TradingBotResponse) => { + return bot.config.name }) ) setBots(data) diff --git a/src/Managing.WebApp/src/components/organism/ActiveBots/botRowDetails.tsx b/src/Managing.WebApp/src/components/organism/ActiveBots/botRowDetails.tsx index 110fb39..782f933 100644 --- a/src/Managing.WebApp/src/components/organism/ActiveBots/botRowDetails.tsx +++ b/src/Managing.WebApp/src/components/organism/ActiveBots/botRowDetails.tsx @@ -1,9 +1,9 @@ -import { TradeChart, CardPositionItem } from '..' -import { Backtest, MoneyManagement, TradingBot } from '../../../generated/ManagingApi' -import { CardPosition, CardText } from '../../mollecules' +import {CardPositionItem, TradeChart} from '..' +import {TradingBotResponse} from '../../../generated/ManagingApi' +import {CardPosition, CardText} from '../../mollecules' interface IBotRowDetailsProps { - bot: TradingBot; + bot: TradingBotResponse; } const BotRowDetails: React.FC = ({ @@ -18,7 +18,8 @@ const BotRowDetails: React.FC = ({ candles, positions, signals, - moneyManagement + config, + agentName } = bot; return ( @@ -43,8 +44,8 @@ const BotRowDetails: React.FC = ({ diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx index 6b5ff3c..de23658 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx @@ -3,9 +3,9 @@ import React, {useEffect, useState} from 'react' import useApiUrlStore from '../../../app/store/apiStore' import useBacktestStore from '../../../app/store/backtestStore' -import type {Backtest, Indicator, IndicatorType} from '../../../generated/ManagingApi' -import {BacktestClient, SignalType} from '../../../generated/ManagingApi' -import {CardText, ConfigDisplayModal, SelectColumnFilter, Table} from '../../mollecules' +import type {Backtest} from '../../../generated/ManagingApi' +import {BacktestClient} from '../../../generated/ManagingApi' +import {CardText, ConfigDisplayModal, IndicatorsDisplay, SelectColumnFilter, Table} from '../../mollecules' import {UnifiedTradingModal} from '../index' import Toast from '../../mollecules/Toast/Toast' @@ -16,49 +16,7 @@ interface BacktestTableProps { isFetching?: boolean } -// Helper function to get indicator parameters from scenario indicators -const getIndicatorParameters = (indicator: Indicator) => { - if (!indicator) return null; - - return { - name: indicator.name || 'Unnamed Indicator', - type: indicator.type, - signalType: indicator.signalType, - period: indicator.period, - fastPeriods: indicator.fastPeriods, - slowPeriods: indicator.slowPeriods, - signalPeriods: indicator.signalPeriods, - multiplier: indicator.multiplier, - smoothPeriods: indicator.smoothPeriods, - stochPeriods: indicator.stochPeriods, - cyclePeriods: indicator.cyclePeriods - }; -}; -// Helper function to get indicators from scenario -const getScenarioIndicators = (backtest: Backtest) => { - if (!backtest.config?.scenario?.indicators) return []; - return backtest.config.scenario.indicators.map(getIndicatorParameters).filter(Boolean); -}; - -// Helper function to get badge color based on signal type -const getBadgeColor = (signalType: SignalType) => { - switch (signalType) { - case SignalType.Signal: - return 'badge-primary'; - case SignalType.Trend: - return 'badge-secondary'; - case SignalType.Context: - return 'badge-accent'; - default: - return 'badge-neutral'; - } -}; - -// Helper function to format indicator type for display -const formatIndicatorType = (type: IndicatorType) => { - return type.replace(/([A-Z])/g, ' $1').trim(); -}; const BacktestTable: React.FC = ({list, isFetching}) => { const [rows, setRows] = useState([]) @@ -207,34 +165,10 @@ const BacktestTable: React.FC = ({list, isFetching}) => { accessor: 'config.scenario.indicators', Cell: ({cell}: any) => { const backtest = cell.row.original as Backtest; - const indicators = getScenarioIndicators(backtest); + const indicators = backtest.config?.scenario?.indicators || []; return ( -
- {indicators.map((indicator: any, index: number) => { - if (!indicator) return null; - - // Build tooltip content with indicator parameters - const tooltipContent = ` - ${indicator.period ? `Period: ${indicator.period}` : ''} - ${indicator.fastPeriods ? `Fast: ${indicator.fastPeriods}` : ''} - ${indicator.slowPeriods ? `Slow: ${indicator.slowPeriods}` : ''} - ${indicator.signalPeriods ? `Signal: ${indicator.signalPeriods}` : ''} - ${indicator.multiplier ? `Multiplier: ${indicator.multiplier}` : ''} - ${indicator.smoothPeriods ? `Smooth: ${indicator.smoothPeriods}` : ''} - ${indicator.stochPeriods ? `Stoch: ${indicator.stochPeriods}` : ''} - ${indicator.cyclePeriods ? `Cycle: ${indicator.cyclePeriods}` : ''} - `.trim().replace(/\n\s+/g, '\n'); - - return ( -
-
- {formatIndicatorType(indicator.type)} -
-
- ); - })} -
+ ); }, disableFilters: true, diff --git a/src/Managing.WebApp/src/pages/botsPage/botList.tsx b/src/Managing.WebApp/src/pages/botsPage/botList.tsx index 971b90b..e20a17f 100644 --- a/src/Managing.WebApp/src/pages/botsPage/botList.tsx +++ b/src/Managing.WebApp/src/pages/botsPage/botList.tsx @@ -258,7 +258,7 @@ const BotList: React.FC = ({ list }) => {
{/* Bot Name - Always on its own line */}

- {bot.config.ticker} + {bot.config.name}

{/* Badge Container - Responsive */} @@ -282,6 +282,10 @@ const BotList: React.FC = ({ list }) => {
+ = ({ list }) => {
+ -