Update dashboard
This commit is contained in:
@@ -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<IndicatorsDisplayProps> = ({ indicators, className = "" }) => {
|
||||
const processedIndicators = indicators.map(getIndicatorParameters).filter(Boolean);
|
||||
|
||||
return (
|
||||
<div className={`flex flex-wrap gap-1 ${className}`}>
|
||||
{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 (
|
||||
<div key={index} className="tooltip" data-tip={tooltipContent}>
|
||||
<div className={`badge ${getBadgeColor(indicator.signalType)} badge-sm`}>
|
||||
{formatIndicatorType(indicator.type)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default IndicatorsDisplay;
|
||||
@@ -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'
|
||||
|
||||
@@ -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<TradingBot[]>([])
|
||||
const [bots, setBots] = useState<TradingBotResponse[]>([])
|
||||
const [accounts, setAccounts] = useState<Account[]>([])
|
||||
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 (
|
||||
<IndicatorsDisplay indicators={indicators} />
|
||||
);
|
||||
},
|
||||
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)
|
||||
|
||||
@@ -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<IBotRowDetailsProps> = ({
|
||||
@@ -18,7 +18,8 @@ const BotRowDetails: React.FC<IBotRowDetailsProps> = ({
|
||||
candles,
|
||||
positions,
|
||||
signals,
|
||||
moneyManagement
|
||||
config,
|
||||
agentName
|
||||
} = bot;
|
||||
|
||||
return (
|
||||
@@ -43,8 +44,8 @@ const BotRowDetails: React.FC<IBotRowDetailsProps> = ({
|
||||
<CardText
|
||||
title="Money Management"
|
||||
content={
|
||||
"SL: " +(moneyManagement?.stopLoss * 100).toFixed(2) + "% TP: " +
|
||||
(moneyManagement?.takeProfit * 100).toFixed(2) + "%"
|
||||
"SL: " +(config.moneyManagement?.stopLoss * 100).toFixed(2) + "% TP: " +
|
||||
(config.moneyManagement?.takeProfit * 100).toFixed(2) + "%"
|
||||
}
|
||||
></CardText>
|
||||
|
||||
|
||||
@@ -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<BacktestTableProps> = ({list, isFetching}) => {
|
||||
const [rows, setRows] = useState<Backtest[]>([])
|
||||
@@ -207,34 +165,10 @@ const BacktestTable: React.FC<BacktestTableProps> = ({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 (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{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 (
|
||||
<div key={index} className="tooltip" data-tip={tooltipContent}>
|
||||
<div className={`badge ${getBadgeColor(indicator.signalType)} badge-sm`}>
|
||||
{formatIndicatorType(indicator.type)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<IndicatorsDisplay indicators={indicators} />
|
||||
);
|
||||
},
|
||||
disableFilters: true,
|
||||
|
||||
@@ -258,7 +258,7 @@ const BotList: React.FC<IBotList> = ({ list }) => {
|
||||
<div className="mb-4">
|
||||
{/* Bot Name - Always on its own line */}
|
||||
<h2 className="card-title text-sm mb-3">
|
||||
{bot.config.ticker}
|
||||
{bot.config.name}
|
||||
</h2>
|
||||
|
||||
{/* Badge Container - Responsive */}
|
||||
@@ -282,6 +282,10 @@ const BotList: React.FC<IBotList> = ({ list }) => {
|
||||
<div className="columns-2">
|
||||
<div>
|
||||
<div>
|
||||
<CardText
|
||||
title="Ticker"
|
||||
content={bot.config.ticker}
|
||||
></CardText>
|
||||
<CardText
|
||||
title="Scenario"
|
||||
content={bot.config.scenarioName ?? bot.config.scenario?.name}
|
||||
@@ -290,8 +294,11 @@ const BotList: React.FC<IBotList> = ({ list }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="columns-2">
|
||||
<CardText
|
||||
title="Agent"
|
||||
content={bot.agentName}
|
||||
></CardText>
|
||||
<CardSignal signals={bot.signals}></CardSignal>
|
||||
<CardText title="Type" content={bot.config.flipPosition ? 'Flipping' : 'Simple'}></CardText>
|
||||
</div>
|
||||
<div className="columns-2">
|
||||
<CardPosition
|
||||
|
||||
Reference in New Issue
Block a user